I have a controller action that takes a DateTime? via the query string as part of a post-redirect-get. The controller looks like e.g.
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index(DateTime? date)
{
IndexModel model = new IndexModel();
if (date.HasValue)
{
model.Date = (DateTime)date;
}
else
{
model.Date = DateTime.Now;
}
return View(model);
}
[HttpPost]
public ActionResult Index(IndexModel model)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index", new { date = model.Date.ToString("yyyy-MM-dd hh:mm:ss") });
}
else
{
return View(model);
}
}
}
My model is:
public class IndexModel
{
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MMM yyyy}")]
public DateTime Date { get; set; }
}
And the Razor view is:
@model Mvc3Playground.Models.Home.IndexModel
@using (Html.BeginForm()) {
@Html.EditorFor(m => m.Date);
<input type="submit" />
}
My problem is two fold:
(1) The date formatting applied on the model using the [DisplayFormat] attribute does not work if the query string contains a value for date.
(2) The value held in the model appears to be overwritten with whatever the query string value contains. E.g. if I set a break point inside my Index GET action method, and manually set the date equal to today say, if the query string contains e.g. ?date=1/1/1, then "1/1/1" is displayed in the textbox (the plan is to validate the date and default it if the query string one isn't valid).
Any ideas?
Html helpers first use ModelState when binding so if you ever intend to modify some value which is present in the model state inside a controller action make sure that you remove it from the ModelState first:
[HttpGet]
public ActionResult Index(DateTime? date)
{
IndexModel model = new IndexModel();
if (date.HasValue)
{
// Remove the date variable present in the modelstate which has a wrong format
// and which will be used by the html helpers such as TextBoxFor
ModelState.Remove("date");
model.Date = (DateTime)date;
}
else
{
model.Date = DateTime.Now;
}
return View(model);
}
I must agree that this behavior is not very intuitive but it is by design so people should really get used to it.
Here's what happens:
Html.EditorFor(x => x.Date)
helper uses the value of your view model (which you have set to DateTime.Now
) and of course it applies proper formatting/Home/Index?date=1/1/1
, the Html.EditorFor(x => x.Date)
helper detects that there is a date
variable inside ModelState
equal to 1/1/1
and it uses this value, completely ignoring the value stored inside your view model (which is pretty much the same in terms of DateTime value but no formatting is applied of course).If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With