My Controller ActionMethod For create View is,
public ActionResult Create(int id=0)
{
Employee emp = new Employee();
ViewBag.TribeId = new SelectList(db.Tribes, "TribeId", "TribeName");
return View(emp);
}
I have EF model Employee that is,
public partial class Employee
{
public int EmpIoyeeId { get; set; }
[Display(Name = "FirstName", ResourceType = typeof(Resources.Resource))]
[Required(ErrorMessageResourceType = typeof(Resources.Resource),
ErrorMessageResourceName = "FirstNameRequired")]
public string FirstName { get; set; }
[Display(Name = "Secondname", ResourceType = typeof(Resources.Resource))]
[Required(ErrorMessageResourceType = typeof(Resources.Resource),
ErrorMessageResourceName = "SecondnameRequired")]
public string Secondname { get; set; }
[Display(Name = "TribeId", ResourceType = typeof(Resources.Resource))]
[Required(ErrorMessageResourceType = typeof(Resources.Resource),
ErrorMessageResourceName = "TribeIdRequired")]
public int TribeId { get; set; }
public virtual Tribe Tribe { get; set; }
}
Here, TribeId is Fk in Employee table and Employee EF class
my View page is like,
#model Structure.Employee
#using (Html.BeginForm()
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-sm-4" })
<div class="col-sm-8">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Secondname, htmlAttributes: new { #class = "control-label col-sm-4" })
<div class="col-sm-8">
#Html.EditorFor(model => model.Secondname, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Secondname, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TribeId, #Resource.TribeName, htmlAttributes: new { #class = "control-label col-sm-4" })
<div class="col-sm-8">
#Html.DropDownList("TribeId", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.TribeId, "", new { #class = "text-danger" })
</div>
</div>
}
Now it is working for FirstName and Second name but i dont understand why it is not showing for validation message for TribeId ? I have already check resource file for showing validation message that all is fine.
Hopes for your suggestions.
Thanks
This is what I did in order for the TribeId validation to work
First in your action
public ActionResult Create(int id=0)
{
Employee emp = new Employee();
ViewBag.Tribes = new SelectList(db.Tribes, "TribeId", "TribeName");
return View(emp);
}
and in your view use the following
<div class="form-group">
#Html.LabelFor(model => model.TribeId, "tribe", htmlAttributes: new { #class = "control-label col-sm-4" })
<div class="col-sm-8">
#Html.DropDownListFor(model => model.TribeId, (IEnumerable<SelectListItem>)ViewBag.Tribes, "Select Tribe")
#Html.ValidationMessageFor(model => model.TribeId, "", new { #class = "text-danger" })
</div>
</div>
Hope this helps
Related
I have a form I created in a view which is supposed to submit to two tables using a view model. When I fill in the fields and click submit, I am getting a null reference exception on the vendormodel and refvendormodel after filling everything in on the form and am unsure of the cause. Any help is greatly appreciated.
My Controller method:
[HttpPost]
[Route("Contract/AddVendor")]
[Route("Contract/AddVendor/{addVendor}")]
public IActionResult AddVendorForm(AddVendorVM addVendor)
{
AddVendorVM model = new AddVendorVM();
if(ModelState.IsValid)
{
model.vendormodel.VENDOR_ID = addVendor.vendormodel.VENDOR_ID;
model.refvendormodel.VENDOR_ID = addVendor.refvendormodel.VENDOR_ID;
model.vendormodel.VENDOR_NAME = addVendor.vendormodel.VENDOR_NAME;
model.refvendormodel.ADDRESS = addVendor.refvendormodel.ADDRESS;
model.refvendormodel.CITY = addVendor.refvendormodel.CITY;
model.refvendormodel.STATE = addVendor.refvendormodel.STATE;
model.refvendormodel.ZIP = addVendor.refvendormodel.ZIP;
model.refvendormodel.FIRST_NAME = addVendor.refvendormodel.FIRST_NAME;
model.refvendormodel.LAST_NAME = addVendor.refvendormodel.LAST_NAME;
model.refvendormodel.PHONE = addVendor.refvendormodel.PHONE;
_context.VENDORs.Add(model.vendortmodel);
_context.REF_VENDORs.Add(model.refvendormodel);
_context.SaveChangesAsync();
return RedirectToAction("Edit");
}
return View(model);
}
[HttpGet]
[Route("Contract/AddVendor")]
public IActionResult AddRespondentForm()
{
AddVendorVM model = new AddVendorVM();
return View(model);
}
My View:
<div class="col-md-4">
#using (
Html.BeginForm("AddVendor", "Contract", FormMethod.Post, new { id = "Form1"}))
{
#Html.HiddenFor(m => Model.vendormodel.VENDOR_ID, new { id = "VendorId" })
#Html.HiddenFor(m => Model.refvendormodel.VENDOR_ID, new { id = "VendorId" })
<label class="control-label">Vendor Name:</label>
#Html.TextBoxFor(r => r.vendormodel.VENDOR_NAME)
<label class="control-label">Address:</label>
#Html.TextBoxFor(r => r.refvendormodel.ADDRESS)
<label class="control-label">City:</label>
#Html.TextBoxFor(r => r.refvendormodel.CITY)
<label class="control-label">State:</label>
#Html.TextBoxFor(r => r.refvendormodel.STATE)
<label class="control-label">Zip Code:</label>
#Html.TextBoxFor(r => r.refvendormodel.ZIP)
<label class="control-label">First Name:</label>
#Html.TextBoxFor(r => r.refvendormodel.FIRST_NAME)
<label class="control-label">Last Name:</label>
#Html.TextBoxFor(r => r.refvendormodel.LAST_NAME)
<label class="control-label">Phone Number:</label>
#Html.TextBoxFor(r => r.refvendormodel.PHONE)
<br />
<input type="submit" value="Add Vendor" />
}
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
My model:
public class AddVendorVM
{
public VENDOR vendormodel { get; set; }
public REF_VENDOR refvendormodel { get; set; }
}
You need to change your code like below:
public IActionResult AddVendorForm(AddVendorVM addVendor)
{
ModelState.Remove("vendormodel.VENDOR_ID");
ModelState.Remove("refvendormodel.VENDOR_ID");
if (ModelState.IsValid)
{
VENDOR model1 = addVendor.vendormodel;
REF_VENDOR model2 = addVendor.refvendormodel;
_context.VENDORs.Add(model1);
_context.REF_VENDORs.Add(model2);
_context.SaveChanges();
return RedirectToAction("Edit");
}
return View();
}
The code in your view are meaningless, you can delete them:
#Html.HiddenFor(m => Model.vendormodel.VENDOR_ID, new { id = "VendorId" })
#Html.HiddenFor(m => Model.refvendormodel.VENDOR_ID, new { id = "VendorId" })
Please notice that if your VENDOR_ID is a primary key of model VENDOR,REF_VENDOR.It will be a required column and automatic increase,so if the VENDOR_ID is 0,the validation will never be true,so you need remove the vendormodel.VENDOR_ID modelstate,then the modelstate will be true.
And you need to notice that don't use SaveChangesAsync in a synchronous method.That will not work.
I am trying to learn the correct usage of View Components in ASP.NET Core MVC, so I have the following example: The idea is to render a view with Movie details, and inside of it, the ReviewViewComponent holding a 10-star movie rating widget.
Inside of the View Component's View is a form with radio buttons. The form action name is passed to the View Component (either Create or Edit, depending on if the user already gave a rating). Depending on the received action name, the form inside the View Component will either call the Create or the Edit method inside of the ReviewsController.
This all works until I reach the return call inside of ReviewsController. I would like to be able to return the View Component there and simply render the return result inside the div with id="now-showing-details-rating-div" in Details using AJAX. This works with Partial Views (code commented out in the ReviewsController's Edit method), but it seems it doesn't work with View Components (it just renders the View Component's View as a completely new View, even though I call the AJAX on the form the same way I would if it were in a Partial View).
Am I actually misusing the View Component concept here? In the sense of rendering a portion of a View after form submit, is it actually better to just use Partial Views?
Ajax snippet
$.ajax({
type: "POST",
url: requestUrl,
data: form.serialize(),
success: function (data) {
$("#" + divZaRezultat).html(data);
}
});
ViewModels:
public class MovieDetailsVM
{
public string Title { get; set; }
public int Id { get; set; }
public int Year { get; set; }
public string Actors { get; set; }
public string Country { get; set; }
public string Directors { get; set; }
public int Duration { get; set; }
public string VideoLink { get; set; }
public string AverageRating { get; set; }
public string NumberOfReviews { get; set; }
public ReviewIndexVM CurrentUserReview { get; set; }
}
public class ReviewIndexVM
{
public int ReviewId { get; set; }
public int Rating { get; set; }
public MasterModel User { get; set; }
public MasterModel Movie { get; set; }
}
ViewComponent
public class ReviewViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(string methodName, ReviewIndexVM review)
{
ViewBag.Method = methodName;
return View(review);
}
}
ViewComponent Default View
#model Cinema.DTO.ViewModels.Reviews.ReviewIndexVM
#{
ViewData["Title"] = "Default";
}
<form asp-controller="Reviews" asp-action="#ViewBag.Method">
<input asp-for="ReviewId" hidden />
<input asp-for="Movie.Id" hidden />
<input asp-for="User.Id" hidden />
<div class="rating form-group">
#for (int i = 10; i > 0; i--)
{
<input asp-for="Rating" type="radio" value="#i" id="#($"rating-star-{i}")" onclick="this.form.submit();" class="form-control rating-star"><label class="rating-star-label" for="#($"rating-star-{i}")"></label>
}
</div>
</form>
Views:
#model Cinema.DTO.ViewModels.Movies.MovieDetailsVM
#using Microsoft.AspNetCore.Identity
#using Cinema.Domain.Entities.Identity
#inject SignInManager<ApplicationUser> SignInManager
#inject UserManager<ApplicationUser> UserManager
#{
ViewData["Title"] = "Details";
Layout = "~/Views/Shared/_Layout.cshtml";
bool first = true;
DateTime currentDate = DateTime.Now;
}
<section>
<div class="container">
<div class="content-wrap">
<div class="row">
<h1 class="h2">#Html.DisplayFor(model => model.Title)</h1>
</div>
<div class="row">
<div class="col-md-4">
<img id="movie-poster" class="pull-left" src="~/img/movie-poster.png" />
</div>
<div class="col-md-8">
<ul class="list-unstyled movie-info">
<li>
<span>#Html.DisplayNameFor(model => model.Title)</span>
#Html.DisplayFor(model => model.Title)
</li>
<li>
<span>#Html.DisplayNameFor(model => model.Year)</span>
#Html.DisplayFor(model => model.Year)
</li>
<li>
<span>#Html.DisplayNameFor(model => model.Actors)</span>
#Html.DisplayFor(model => model.Actors)
</li>
<li>
<span>#Html.DisplayNameFor(model => model.Country)</span>
#Html.DisplayFor(model => model.Country)
</li>
<li>
<span>#Html.DisplayNameFor(model => model.Directors)</span>
#Html.DisplayFor(model => model.Directors)
</li>
<li>
<span>#Html.DisplayNameFor(model => model.Duration)</span>
#Html.DisplayFor(model => model.Duration)
</li>
#*<li>
<span>#Html.DisplayNameFor(model => model.GenreMovies)</span>
#Html.DisplayFor(model => model.GenreMovies)
</li>*#
<li>
<span>#Html.DisplayNameFor(model => model.VideoLink)</span>
#Html.DisplayFor(model => model.VideoLink)
</li>
</ul>
Average rating <span class="badge">#Model.AverageRating</span>
<hr />
<div asp-authorize asp-roles="#Roles.User">
Your rating:
<div id="now-showing-details-rating-div">
#if (#Model.CurrentUserReview.ReviewId == 0)
{
#await Component.InvokeAsync("Review", new { methodName = "Create", review = #Model.CurrentUserReview })
}
else
{
#await Component.InvokeAsync("Review", new { methodName = "Edit", review = #Model.CurrentUserReview })
}
</div>
</div>
</div>
</div>
</div>
</section>
#section Scripts {
$(document).ready(function () {
$('.rating-star-label').mouseover(function () {
$('.rating-star').prop('checked', false);
});
});
</script>
}
ReviewsController
[HttpGet]
[Authorize(Roles = Roles.User)]
public async Task<IActionResult> Edit(int reviewId)
{
Review review = await _unit.Reviews.GetAsync(reviewId);
var authorizationResult = await _authorizationService.AuthorizeAsync(User, review, OperationRequirements.Update);
if (authorizationResult.Succeeded)
{
ReviewUpdateVM model = review.ToUpdateVM();
return PartialView(model);
}
else if (User.Identity.IsAuthenticated)
{
return new ForbidResult();
}
else
{
return new ChallengeResult();
}
}
[Authorize(Roles = Roles.User)]
public async Task<IActionResult> Edit(ReviewIndexVM model)
{
Review review = model.Create();
var authorizationResult = await _authorizationService.AuthorizeAsync(User, review, OperationRequirements.Update);
if (authorizationResult.Succeeded)
{
await _unit.Reviews.UpdateAsync(review, model.ReviewId);
await _unit.SaveAsync();
return ViewComponent("Review");
//return Redirect("/Reviews/Details?reviewId=" + review.Id);
}
else if (User.Identity.IsAuthenticated)
{
return new ForbidResult();
}
else
{
return new ChallengeResult();
}
}
}
else if (User.Identity.IsAuthenticated)
{
return new ForbidResult();
}
else
{
return new ChallengeResult();
}
}
Here is a working demo:
Details.cshtml:
#model MovieDetailsVM
#{
ViewData["Title"] = "Details";
Layout = "~/Views/Shared/_Layout.cshtml";
bool first = true;
DateTime currentDate = DateTime.Now;
}
<section>
<div class="container">
<div class="content-wrap">
<div class="row">
<h1 class="h2">#Html.DisplayFor(model => model.Title)</h1>
</div>
<div class="row">
<div class="col-md-8">
<ul class="list-unstyled movie-info">
<li>
<span>#Html.DisplayNameFor(model => model.Title)</span>
#Html.DisplayFor(model => model.Title)
</li>
<li>
<span>#Html.DisplayNameFor(model => model.Year)</span>
#Html.DisplayFor(model => model.Year)
</li>
<li>
<span>#Html.DisplayNameFor(model => model.Actors)</span>
#Html.DisplayFor(model => model.Actors)
</li>
<li>
<span>#Html.DisplayNameFor(model => model.Country)</span>
#Html.DisplayFor(model => model.Country)
</li>
<li>
<span>#Html.DisplayNameFor(model => model.Directors)</span>
#Html.DisplayFor(model => model.Directors)
</li>
<li>
<span>#Html.DisplayNameFor(model => model.Duration)</span>
#Html.DisplayFor(model => model.Duration)
</li>
#*<li>
<span>#Html.DisplayNameFor(model => model.GenreMovies)</span>
#Html.DisplayFor(model => model.GenreMovies)
</li>*#
<li>
<span>#Html.DisplayNameFor(model => model.VideoLink)</span>
#Html.DisplayFor(model => model.VideoLink)
</li>
</ul>
Average rating <span class="badge">#Model.AverageRating</span>
<hr />
<div>
Your rating:
<div id="now-showing-details-rating-div">
#if (#Model.CurrentUserReview == null)
{
#await Component.InvokeAsync("Review", new { methodName = "Create", review = #Model.CurrentUserReview })
}
else
{
#await Component.InvokeAsync("Review", new { methodName = "Edit", review = #Model.CurrentUserReview })
}
</div>
</div>
</div>
</div>
</div>
</div>
</section>
Ajax in Details.cshtml:
#section Scripts {
<script>
$(document).ready(function () {
$('.rating-star-label').mouseover(function () {
$('.rating-star').prop('checked', false);
});
});
function Update() {
$.ajax({
type: "POST",
url: "/Reviews/Edit/#Model.CurrentUserReview.ReviewId",
data: $("form").serialize(),
success: function (data) {
$("#now-showing-details-rating-div").html(data);
}
});
}
</script>
}
Components/Review/Default.cshtml:
#model ReviewIndexVM
#{
ViewData["Title"] = "Default";
}
<form asp-controller="Reviews" asp-action="#ViewBag.Method">
<input asp-for="ReviewId" hidden />
<input asp-for="Movie.Id" hidden />
<input asp-for="User.Id" hidden />
<div class="rating form-group">
#for (int i = 10; i > 0; i--)
{
<input asp-for="Rating" type="radio" value="#i" id="#($"rating-star-{i}")" onclick="Update();" class="form-control rating-star"><label class="rating-star-label" for="#($"rating-star-{i}")"></label>
}
</div>
</form>
Controller:
public class ReviewsController : Controller
{
private readonly Component2_2Context _context;
public ReviewsController(Component2_2Context context)
{
_context = context;
}
// GET: Reviews/Details/5
public async Task<IActionResult> Details(int? id)
{
var reviewIndexVM = await _context.MovieDetailsVM
.Include(m => m.CurrentUserReview)
.FirstOrDefaultAsync(m => m.Id == id);
return View(reviewIndexVM);
}
// GET: Reviews/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var reviewIndexVM = await _context.ReviewIndexVM.FindAsync(id);
if (reviewIndexVM == null)
{
return NotFound();
}
return View(reviewIndexVM);
}
// POST: Reviews/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ReviewId,Rating")] ReviewIndexVM reviewIndexVM)
{
if (id != reviewIndexVM.ReviewId)
{
return NotFound();
}
if (ModelState.IsValid)
{
_context.Update(reviewIndexVM);
await _context.SaveChangesAsync();
return ViewComponent("Review");
}
return new ChallengeResult();
}
ViewComponent:
public class ReviewViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(string methodName, ReviewIndexVM review)
{
ViewBag.Method = methodName;
return View(review);
}
}
Result:
If I have a form for creating a holiday request:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal" style=" position:relative; top:20px;border-radius: 0px; border-color: #F47B20; border-style: solid; border-width: 5px; background-repeat: no-repeat; background-position: right; padding: 60px; background-size: contain; background-color:white ">
<h2 align="center">Holiday Request Form</h2>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.EmployeeID, "Employee Name", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("EmployeeID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.EmployeeID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.StartDate,"Start Date", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.StartDate, "Start Date",new { htmlAttributes = new { #class = "form-control", autocomplete = "off" } })
#Html.ValidationMessageFor(model => model.StartDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FinishDate, "Finish Date",htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FinishDate, new { htmlAttributes = new { #class = "form-control", autocomplete = "off" } })
#Html.ValidationMessageFor(model => model.FinishDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.HoursTaken,"Hours Requested", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.HoursTaken, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.HoursTaken, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Comments, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextAreaFor(
model => model.Comments,
new { placeholder = "Enter Dates and how many Hours per Date Here.", style = "width: 400px; height: 200px;" })
#Html.ValidationMessageFor(model => model.Comments, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Submit" class="btn btn-warning" />
</div>
</div>
</div>
}
But Instead of an Employee selecting their name of a dropdown list, The input will be based from the log in.
I already figured out how to grab the Employees Id from the log in but I am unsure how to use it in a form.
This is how I grabbed it using the controller which works for other aspects of my app
string name = Session["Name"].ToString();
var EmployeeIDCatch = db.Employees.Where(s => s.Email.Equals(name)).Select(s => s.EmployeeID);
Controller:
public ActionResult Create()
{
ViewBag.EmployeeID = new SelectList(db.Employees, "EmployeeID", "FullName");
return View();
string name = Session["Name"].ToString();
var EmployeeIDCatch = db.Employees.Where(s => s.Email.Equals(name)).Select(s => s.EmployeeID);
}
// POST: HolidayRequestForms/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "RequestID,EmployeeID,StartDate,FinishDate,HoursTaken,Comments,YearCreated,MonthCreated,DayCreated,YearOfHoliday,Approved")] HolidayRequestForm holidayRequestForm)
{
if (ModelState.IsValid)
{
db.HolidayRequestForms.Add(holidayRequestForm);
db.SaveChanges();
SendMailToAreaManager();
SendMailToManager();
return RedirectToAction("Index","Calendar");
}
ViewBag.EmployeeID = new SelectList(db.Employees, "EmployeeID", "FullName", holidayRequestForm.EmployeeID);
return View(holidayRequestForm);
}
First remove the following code from your html form:
<div class="form-group">
#Html.LabelFor(model => model.EmployeeID, "Employee Name", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("EmployeeID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.EmployeeID, "", new { #class = "text-danger" })
</div>
</div>
Now update your Create POST method as follows:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "RequestID,StartDate,FinishDate,HoursTaken,Comments,YearCreated,MonthCreated,DayCreated,YearOfHoliday,Approved")] HolidayRequestForm holidayRequestForm)
{
if (ModelState.IsValid)
{
string name = Session["Name"].ToString();
var employeeID = db.Employees.Where(s => s.Email.Equals(name))
.Select(s => s.EmployeeID).FirstOrDefault();
holidayRequestForm.EmployeeID = employeeID;
db.HolidayRequestForms.Add(holidayRequestForm);
db.SaveChanges();
SendMailToAreaManager();
SendMailToManager();
return RedirectToAction("Index","Calendar");
}
return View(holidayRequestForm);
}
I get the following error when I try to add a Schedule.
The column name 'Doctor_id' is specified more than once in the SET clause or column list of an INSERT. A column cannot be assigned more than one value in the same clause. Modify the clause to make sure that a column is updated only once. If this statement updates or inserts columns into a view, column aliasing can conceal the duplication in your code.
Here is my schedule model
[Table("Schedule")]
public class Schedule
{
public int Id { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime Date { get; set; }
[Required]
[DataType(DataType.Time)]
public TimeSpan StartTime { get; set; }
[Required]
[DataType(DataType.Time)]
public TimeSpan EndTime { get; set; }
public bool Booked { get; set; }
public int Doctor_id { get; set; }
//public virtual Doctor Doctor { get; set; }
}
Here is my controller:
public ActionResult CreateSchedule(Schedule schedule)
{
TimeSpan startTime = schedule.StartTime;
TimeSpan endTime = schedule.EndTime;
db.Schedules.Add(schedule);
db.SaveChanges();
}
This is the form
<div class="form-horizontal">
<h4>Schedule</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<input type="hidden" name="Doctor_id" value="#Session["doctorid"]" />
<div class="form-group">
#Html.LabelFor(model => model.Date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Date, new { htmlAttributes = new { #class = "form-control date" } })
#Html.ValidationMessageFor(model => model.Date, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.StartTime, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.StartTime, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.StartTime, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.EndTime, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EndTime, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.EndTime, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
I have a hidden input name Doctor_id with value for the create form.
Please help me with this, thanks.
This is not a repeated question am posting this question after trying all solutions.
I want to perform CRUD on a single View so I got this article
CRUD using SIngle View
It works fine but when I keep the text box empty then the Model is Valid returns false which is correct,after debugging it shows Name field is required but I cant see the error on the View.
Even #Html.ValidationSummary(true) is present in Begin Form
and #Html.ValidationMessageFor(model => model.Name)
So keeping the code short have used only one field
Model
public partial class tblClient
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
A class which handle multiple button
public class HttpParamActionAttribute : ActionNameSelectorAttribute
{
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
{
if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
return true;
var request = controllerContext.RequestContext.HttpContext.Request;
return request[methodInfo.Name] != null;
}
}
Controller
public class EmpController : Controller
{
SampleEntities1 db = new SampleEntities1();
//
// GET: /Emp/
public ActionResult Index(int? id)
{
ViewBag.Operation = id;
ViewBag.Name = db.tblClients.ToList();
tblClient objEmp = db.tblClients.Find(id);
return View(objEmp);
}
[HttpPost]
[HttpParamAction]
[ValidateAntiForgeryToken]
public ActionResult Create(tblClient objEmp)
{
if (ModelState.IsValid)
{
db.tblClients.Add(objEmp);
db.SaveChanges();
}
return RedirectToAction("Index");
}
[HttpPost]
[HttpParamAction]
[ValidateAntiForgeryToken]
public ActionResult Update(tblClient objEmp)
{
if (ModelState.IsValid)
{
db.Entry(objEmp).State = EntityState.Modified;
db.SaveChanges();
}
return RedirectToAction("Index", new { id = 0 });
}
public ActionResult Delete(int id)
{
tblClient objEmp = db.tblClients.Find(id);
db.tblClients.Remove(objEmp);
db.SaveChanges();
return RedirectToAction("Index", new { id = 0 });
}
}
View
#using (Html.BeginForm())
{
<fieldset>
<legend><b>Emp Details</b></legend>
<table border="1" cellpadding="10">
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
Action
</th>
</tr>
#foreach (var item in (IEnumerable<SingleVIewCrud.Models.tblClient>)ViewBag.Name)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.ActionLink("Edit", "Index", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</table>
</fieldset>
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true)
<fieldset>
<legend> <b>Entry Screen</b></legend>
<div class="form-group">
#Html.LabelFor(model => model.Name, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
<p>
<input type="submit" value="Create" name="Create"
style=#((ViewBag.Operation != null && Convert.ToInt32(ViewBag.Operation) > 0) ? "display:none" : "display:block") />
<input type="submit" value="Update" name="Update"
style=#((ViewBag.Operation != null && Convert.ToInt32(ViewBag.Operation) > 0) ? "display:block" : "display:none") />
</p>
</div>
</fieldset>
</div>
}
What is wrong that the validation error message is not displayed.
In both your Create() and Edit() POST methods, if ModelState is invalid, you just redirecting to the Index() view. You need to return the existing view -
if (!ModelState.IsValid()
{
return View(objEmp);
}
// save and redirect
db.tblClients.Add(objEmp);
db.SaveChanges();
return RedirectToAction("Index");
Side note: If you include the jquery.validate.js and jquery.validate.unobtrusive.js scripts, then you will also get client side validation and the POST methods will not even be hit - the validation messages will be displayed and the submit will be cancelled