ModelState.AddModelError for Ajax loaded partials - ajax

I have a partial view on my main page that loads a form, the model is below:
public class CreateRequestViewModel
{
[Required]
public short ClientId { get; set; }
[Required]
public Guid SystemId { get; set; }
[Required]
public string RequestedUsername { get; set; }
public string TicketReference { get; set; }
public string Notes { get; set; }
public List<SelectListItem> Clients { get; set; }
public List<SelectListItem> Systems { get; set; }
}
This is the partial view:
#model Models.CreateRequestViewModel
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row">
<div class="col-lg-4 col-md-4 col-sm-12">
<h1>Create a Request</h1>
</div>
<div class="col-lg-8 col-md-8 col-sm-12 right">
<div class="form-group">
#Html.DropDownListFor(m => m.ClientId, Model.Clients, htmlAttributes: new { #class = "form-control form-control-lg", #id = "ClientSelect" })
#Html.ValidationMessageFor(m => m.ClientId, "", htmlAttributes: new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.DropDownListFor(m => m.SystemId, Model.Systems, htmlAttributes: new { #class = "form-control form-control-lg", #id = "ClientSystemSelect" })
#Html.ValidationMessageFor(m => m.SystemId, "", htmlAttributes: new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.TextBoxFor(m => m.RequestedUsername, htmlAttributes: new { #class = "form-control form-control-lg", #placeholder = "Username" })
#Html.ValidationMessageFor(m => m.RequestedUsername, "", htmlAttributes: new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.TextBoxFor(m => m.TicketReference, htmlAttributes: new { #class = "form-control form-control-lg", #placeholder = "Ticket reference" })
</div>
<div class="form-group">
#Html.TextAreaFor(m => m.Notes, htmlAttributes: new { #class = "form-control form-control-lg", #rows = 3, #placeholder = "Notes..." })
</div>
<input type="Submit" class="btn btn-secondary btn-block send-request" value="Submit" name="">
</div>
</div>
This is how I'm loading the page:
<div class="container">
<div class="row">
<div class="col-lg-6">
<form asp-action="CreateRequest" asp-controller="Access"
data-ajax="true"
data-ajax-method="POST"
data-ajax-mode="replace"
data-ajax-update="#createRequest">
<div id="createRequest">
#await Html.PartialAsync("_CreateRequest", Model.CreateRequestModel)
</div>
</form>
</div>
</div>
</div>
With the model as it is and using the unobtrusive javascript, leaving the RequestedUsername blank for example will result in the form not being submitted and a validation message appearing for it. This is great.
However, I have a requirement to check the form data against entries in a database first and throw an error if there's an existing record. I thought that, with all the client side validation passing, I'd use ModelState.AddModelError in the controller like so:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult CreateRequest(CreateRequestViewModel model)
{
if(model.RequestedUsername == "someincorrectvalue"){ //actual logic removed for brevity
ModelState.AddModelError("RequestedUsername", "Already in use");
}
if(!ModelState.IsValid)
{
//reset lists on model, removed
return PartialView("_CreateRequest", model);
}
_logger.LogInformation("CreateRequest successful");
return RedirectToAction(nameof(Index));
}
However, if I use ModelState.AddModelError, the return PartialView("_CreateRequest", model) call ends up reloading the whole page as if it's returning a full View.
I'm at a loss as to why this is happening. The difference I can see is that i'm adding a ModelState error inside the controller, whereas validation is happening client side otherwise.
Anyone have an idea?

So, this turned out to be a combination of problems. To begin with, the unobtrusive Ajax scripts I had within my solution were not performing. I don't know why but I replaced them with one from the CDN: https://ajax.aspnetcdn.com/ajax/jquery.unobtrusive-ajax/3.2.5/jquery.unobtrusive-ajax.min.js
That solved the problem of the whole page reloading instead of the partial being returned via unobtrusive ajax.
The second problem was that, on success, I was redirecting to the Index controller action instead of returning a Partial again. This was causing the entire Index page to be rendered inside the div i'd chosen as my ajax target. My controller action now looks like this:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult CreateRequest(CreateRequestViewModel model)
{
if(model.RequestedUsername == "someincorrectvalue"){ //actual logic removed for brevity
ModelState.AddModelError("RequestedUsername", "Already in use");
}
if(!ModelState.IsValid)
{
//reset lists on model, removed
return PartialView("_CreateRequest", model);
}
_logger.LogInformation("CreateRequest successful");
// reset lists on model, removed
ModelState.Clear(); // get rid ofany model details to make way for a new request
return PartialView("_CreateRequest", model);
}

Related

ASP Core Ajax Posting From Partials

I have a requirement to separate parts of one page into Partial Views and one of those parts contains a form to submit data. I've been playing around with this and have managed to get the form to submit without reloading the page.
However I have two problems:
The form fields don't clear after a successful post
If validation is broken, those validation messages don't appear when returning the result.
I'll admit i'm not too familiar with AJAX in ASP to begin with but hopefully someone can hope. Here's my code:
Model
using System.ComponentModel.DataAnnotations;
namespace MVCValidation.Models
{
public class Thing
{
public int Id { get; set; }
[Required]
public string Value { get; set; }
public string OtherValue { get; set; }
}
}
Main View (_Index.cshtml)
#model MVCValidation.Models.Thing
#{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Ajax Partial Test</h1>
</div>
<div class="row">
<div class="col">
<form asp-controller="Home" asp-action="Edit" data-ajax="true" data-ajax-method="POST">
#await Html.PartialAsync("_Form", Model)
</form>
</div>
</div>
Partial View (_Form.cshtml)
#model MVCValidation.Models.Thing
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new {#class = "text-danger"})
#Html.HiddenFor(m => m.Id)
<div class="form-group">
#Html.LabelFor(m => m.Value, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(m => m.Value, new {htmlAttributes = new { #class = "form-control" }})
#Html.ValidationMessageFor(m => m.Value, "", 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-success"/>
</div>
</div>
</div>
Controller (HomeController)
namespace MVCValidation.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public Thing GetThing()
{
return new Thing(){Id = 1, OtherValue = "Other"};
}
public IActionResult Index()
{
return View(GetThing());
}
[ValidateAntiForgeryToken]
[HttpPost]
public IActionResult Edit(Thing thing)
{
if(ModelState.IsValid)
{
ModelState.Clear();
return PartialView("_Form", GetThing());
}
return PartialView("_Form", thing);
}
}
}
In my _Layout view I have the jquery.unobtrusive-ajax.min.js referenced and it's loading fine. Please can anyone suggest where I'm going wrong?
So, I eventually found this article: https://damienbod.com/2018/11/09/asp-net-core-mvc-ajax-form-requests-using-jquery-unobtrusive/ and saw what I was doing wrong.
I expanded my tag to look like below:
<form asp-controller="Home" asp-action="Edit"
data-ajax="true"
data-ajax-method="POST"
data-ajax-mode="replace"
data-ajax-update="#result">
<div id="result">
#await Html.PartialAsync("_Form", Model)
</div>
</form>
the PartialAsync call now takes place inside a div that ultimately will be the target for the result to populate... so it effectively replaces itself.
I also had to change the controller method to this:
[ValidateAntiForgeryToken]
[HttpPost]
public IActionResult Edit(Thing thing)
{
if(ModelState.IsValid)
{
return RedirectToAction(nameof(Index));
}
return PartialView("_Form", thing);
}
This correctly returns the partial view when the model is invalid, and allows the page to be used again if it is valid.

DropDownList is not passing any values

Creating a dynamic drop down menu for US states that is being called via linq. When I select a state and then click submit i walk though the code and it shows that I am passing null. The list displays as it should, Any guidance will help.
If you need any more information please let me know and ill post it.
Controller
// GET:
[AllowAnonymous]
public ActionResult DealerLogin()
{
var results = (from a in db1.States
where a.CountryID == 221
select new SelectListItem { Value = a.StateID.ToString() , Text = a.Name }).ToList();
}
View
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div class="form-group">
#Html.LabelFor(model => model.StateId, "States", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.StateId, Model.States.Items as List<SelectListItem>, "-- Select --", new { #class = "form-control" })
</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>
}
Model
public class EditProfile2
{
public int StateId { get; set; }
public SelectList States { get; set; }
}
UPDATED
Ok I have updates everything so it matches almost to #Fran answer, seems he was missing a few things but i got it to work. I also took what #Stephen Muecke said and got rid of the validation.
You seem to be going around all the built in stuff that MVC will give you for free.
Try this
You can use attributes to define what is required and to modify the display names without actually writing into your view.
ViewModel:
public class EditProfile2
{
[Required]
[DisplayName("State")]
public int StateId { get; set; }
public SelectList States {get;set;}
}
View: only including the relevant parts
Since we used attributes on our model, we don't have to give the text in the view. we can also use DropDownListFor instead of DropDownList. And also have this declaration add the "--Select State--" option
<div class="form-group">
#Html.LabelFor(model => model.StateId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model.StateId, Model.States, "-- Select State --", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.StateId, "", new { #class = "text-danger" })
</div>
</div>
Because of our previous use of attributes and built in framework elements, our action method can slim down.
Controller Action:
[AllowAnonymous]
public ActionResult DealerLogin()
{
var results = (from a in db1.States
where a.CountryID == 221
select new SelectListItem { Value= a.StateID.ToString(), Text = a.Name }).ToList();
return View(new EditProfile2 { States = new SelectList(results)});
}

MVC 5 Ajax form with field updates asynchronously and still supporting a Full form post

So I have been using MVC for a while but not a lot of Ajax.
So the issue i have is that I have a create view where the first field of the create view is a Date picker which on change i want ajax to change the selection dropdown of another field on the form. I have the Ajax update working , but the form Post (Create button), now only calls into the Ajax method on the controller. I want the Ajax post back to call the default method Create method on the Controller. So the Create form contains 3 fields
A date (which has the OnChange Ajax submit)
A drop down list of id's and text
other fields as required
I have included the model and cshtml view files (one the partial). The controller is just simply a method taking either the datetime value or the entire model.
So I have the code working where, when the date changes it updates the relevant LocalIds field, but because the 'create' button is inside the Ajax.BeginForm tags, when the create button is pressed, it generates an Ajax call, and I want it to generate a Form Post. What am i missing
CreateModel
public class IdsSelection
{
public string Id { get; set; }
public List<SelectListItem> Selections { get; set; }
}
public class CreateModel
{
[Display(Name="Local Id's")]
public IdsSelection LocalIds;
[Display(Name="Day")]
[Required, DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}",ApplyFormatInEditMode=true)]
public DateTime Date { get; set; }
[Required, Display(Name = "Other Value")]
[Range(1.0, 1000000.0, ErrorMessage ="Value must be greater than zero")]
public decimal OtherValue { get; set; }
public CreateModel()
{
Date = DateTime.Today;
}
}
CreateView.cshtml
#Model Demo.Models.CreateModel
....
#using (Ajax.BeginForm("ChangeDate", "Process", new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET",
UpdateTargetId = "changeid",
}))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<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
{
autofocus = "autofocus",
#class = "form-control",
#Value = Model.Date.ToString("yyyy-MM-dd"),
onchange = "$(this.form).submit();"
}
})
#Html.ValidationMessageFor(model => model.Date, "", new { #class = "text-danger" })
</div>
</div>
#Html.Partial("_ShowIds", Model.LocalIds)
<div class="form-group">
#Html.LabelFor(model => model.OtherValue, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.OtherValue, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.OtherValue, "", 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>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
}
_ShowIds.cshtml
#model Demo.Models.IdsSelection
<div id="changeid" class="form-group">
#Html.Label("Local Id", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#if(Model.Selections.Count == 1) // one
{
#Html.HiddenFor(model => model.Id)
#Html.EditorFor(model => model.Selections[0].Text, new
{
htmlAttributes = new
{
#class = "form-control",
#readonly = "readonly",
}
})
}
else // more entries so show a dropdown
{
#Html.DropDownListFor(model => model.Id, Model.Selections, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model, "", new { #class = "text-danger" })
}
</div>
</div>
You have not shown you controller methods, but assuming the method which generates this view is named Create(), then create a corresponding POST method
[httpPost]
public ActionResult Create(CreateModel model)
for saving the data. The remove #using (Ajax.BeginForm("ChangeDate", "Process", new AjaxOptions() { ..... ])) and replace with a normal form to post back to the server (and you can remove jquery.unobtrusive-ajax.min.js)
#using (Html.BeginForm())
{
....
Next create a controller method that returns your partial view based on the selected date
public PartialViewResult FetchLocalIds(DateTime date)
{
IdsSelection model = // populate model based on selected date
return PartialView("_ShowIds", model);
}
Next, in the view, wrap the current #Html.Partial() in a placeholder element
<div id="localids">
#Html.Partial("_ShowIds", Model.LocalIds)
</div>
Then use jquery to handle the datepickers .change() event and call the FetchLocalIds() method to update the DOM using the .load() function.
$('#Date').change(function() {
$('#localids').load('#Url.Action("FetchLocalIds")', { date: $(this).val() })
})
Note also to remove onchange = "$(this.form).submit();" from the #Html.EditorFor(model => model.Date, new { ... })

MVC 5 Using POSTAL with Models

I am trying to use Postal in Mvc.5.2.3 and Razor.3.2.3 in Visual studio Ultimate 2013, I have many forms to generate for this project and would like to use Views as i would like to Post content to a database as well as send an email out with the information from the form using Postal. I am also creating partial Views for the header and footer so they are always the same and only the content of the email is changed by what forms are used. The email that will be sent will be to the sales department for review, a second email needs to be sent to the person that filled out the form saying thank you and showing the information they sent with the form. I hope this makes sense. I had the database working properly but had so much trouble getting the email system to work i have just started over and just trying to get the email system working properly.
My Model
using Postal;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace APP.Models.Forms.Company
{
public class ContactEmail : Email
{
public ContactEmail() : base("Contact")
{ }
public int ContactId { get; set; }
public Guid TicketId { get; set; }
[Required(ErrorMessage = "Please Enter your First Name!")]
[StringLength(100, MinimumLength = 3)]
[DisplayName("First Name")]
[Display(Order = 1)]
public string FirstName { get; set; }
[Required(ErrorMessage = "Please Enter your Last Name!")]
[StringLength(100, MinimumLength = 3)]
[DisplayName("Last Name")]
[Display(Order = 2)]
public string LastName { get; set; }
[DisplayName("Business Name")]
[Display(Order = 3)]
public string BusinessName { get; set; }
[Required(ErrorMessage = "You have not entered a phone numer, Please enter your phone number so we can get back to you!")]
[DataType(DataType.PhoneNumber)]
[DisplayName("Phone Number")]
[RegularExpression(#"^[01]?[- .]?(\([2-9]\d{2}\)|[2-9]\d{2})[- .]?\d{3}[- .]?\d{4}$", ErrorMessage = "Please enter proper format of one of the following: (555)555-5555, 555-555-5555, 5555555555")]
[StringLength(32)]
[Display(Order = 4)]
public string Phone { get; set; }
[Required(ErrorMessage = "You have not entered an Email address, Please enter your email address!")]
[DataType(DataType.EmailAddress)]
[DisplayName("Email Address")]
[MaxLength(50)]
[RegularExpression(#"^([\w\.\-]+)#([\w\-]+)((\.(\w){2,3})+)$", ErrorMessage = "The Email field is not valid, Please enter a valid email address!")]
[Display(Order = 5)]
public string UserEmailAddress { get; set; }
[Required(ErrorMessage = "You have not entered a message, Please enter a message!")]
[DataType(DataType.MultilineText)]
[StringLength(2000)]
[DisplayName("Message")]
[Display(Order = 6)]
public string Message { get; set; }
public Source Source { get; set; }
public HttpPostedFileBase Upload { get; set; }
[Display(Name = "Full Name")]
public string FullName
{
get
{
return LastName + ", " + FirstName;
}
}
}
}
The Controler:
using APP.Models;
using APP.Models.Forms.Company;
using Postal;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Web;
using System.Web.Mvc;
namespace APP.Controllers
{
public class FormsController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
#region Main Forms Page
// Forms Page Blank with unautherized access
public ActionResult Index()
{
return View();
}
#endregion
#region Contact_Form
// GET: Forms/Create
public ActionResult Contact()
{
return View();
}
// POST: Forms/Submit
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Send(ContactEmail form)
{
var email = new Email("Contact")
{
To = "webmaster#somedomain.com",
MyModel = ContactEmail //Says its a "type" but used like a variable.
}
email.Send();
}
#endregion
#region Condo Form
#endregion
#region Personal Flood Form
#endregion
#region Home Insurance Form
#endregion
#region Renters Insurance Form
#endregion
#region WaterCraft Insurance Form
#endregion
#region Life Insurance Form
#endregion
#region Business Flood Form
#endregion
#region Business Risk Form
#endregion
#region Business Inland Marine Form
#endregion
#region Business Group Health Form
#endregion
#region Form
#endregion
#region Not Available Forms Page
// Forms Page Blank with unautherized access
public ActionResult Not_Available()
{
return View();
}
#endregion
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
Form View:
#model APP.Models.Forms.Company.ContactEmail
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout_LandingPages.cshtml";
}
<div class="box">
<h2>Contact Form</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Contact </h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row">
<div class="col-lg-6">
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
#Html.LabelFor(model => model.BusinessName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.BusinessName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.BusinessName, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
#Html.LabelFor(model => model.Phone, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.Phone, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Phone, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
#Html.LabelFor(model => model.UserEmailAddress, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.UserEmailAddress, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UserEmailAddress, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
#Html.LabelFor(model => model.Message, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Message, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Message, "", new { #class = "text-danger" })
</div>
</div>
</div></div>
<hr />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Submit Form" class="btn btn-default" /> 
<input type="reset" value="Reset Form" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Cancel", "Index", "Home")
</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
My email View is Contact.cshtml and is located in the email folder under Views.
You already have an email object, so just call send:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Send(ContactEmail form)
{
form.Send();
// You could also save this to the database here...
}

jQuery UI Datepicker not Posting to Server after Deployment

So I published a ASP.Net MVC3 project that uses the jQuery UI datepickers on to a IIS server. The datepickers don't seem to post their values and revert to default values on the back end.
Locally, though it works like a charm. It's simple jQuery without any options on the datepicker.
Any clue as to why that would happen?
Let me know what I can post to help find a solution.
Thanks!
The model I am trying to post back:
public class Report
{
[Required]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime From { get; set; }
[Required]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime To { get; set; }
public virtual Car Car { get; set; }
public virtual IEnumerable<Review> Reviews { get; set; }
}
The form I am using:
#model Cars.Models.Report
<h3>Create a report</h3>
#using (Html.BeginForm("Generate", "Report"))
{
<div>
<div class="span-5">
<div class="editor-label">
#Html.LabelFor(model => model.From)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.From, new { #class = "datepicker lilbig" })
</div>
</div>
<div class="span-5 last">
<div class="editor-label">
#Html.LabelFor(model => model.To)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.To, new { #class = "datepicker lilbig" })
</div>
</div>
<div class="span-11 last">
<div class="prepend-5 last">
<input class="bigbtn" type="submit" value="Create" />
</div>
<div>
#Html.ValidationSummary(true)
#Html.ValidationMessageFor(model => model.From)
#Html.ValidationMessageFor(model => model.To)
</div>
</div>
</div>
}
Method I am posting to:
[HttpPost]
public ActionResult Generate(Report model)
{
try
{
MembershipUser currentUser = Membership.GetUser(HttpContext.User.Identity.Name);
Guid id = (Guid)currentUser.ProviderUserKey;
Car currentCar = CarRepository.Get(id);
currentCar.LastReportCreated = DateTime.Now;
currentCar = CarRepository.Update(currentCar, true);
model.Car = currentCar;
model.Reviews = model.Car.Reviews.Where(s => s.LoggedAt.Date >= model.From.Date &&
s.LoggedAt.Date <= model.To.Date);
return View("Report", model);
}
catch(Exception ex)
{
return View("Error");
}
}
The jQuery looks like this:
$(document).ready(function () {
$(".datepicker").datepicker();
});
Check that the datepicker version on the server is current and running bug-free. Also double check your form data before it gets posted - make sure the date fields have values:
$(document).ready(function () {
$("form").submit(function(){
$(".datepicker").each(function(){
alert( $(this).attr("name") +": "+ $(this).value() );
});
});
});

Resources