Jez
Jez

Reputation: 30013

How to have ModelState use the TempData mechanism?

As far as I can tell, there's a bit of a problem with ASP.NET's ModelState mechanism. It only stays around for the context of the current HTTP request. So let's say I just want to use server-side validation. I can write this in my .cshtml view:

@using (Html.BeginForm("Index", "MyController", routeValues: new { Area = "MyArea" }, method: FormMethod.Post, htmlAttributes: new { @autocomplete = "off" }))
{
    @Html.TextBoxFor(m => m.SomeTextbox, new { @class = "form-control" })
    @Html.ValidationMessageFor(m => m.SomeTextbox)
    ...

... where my model is:

public class SomeModel
{
    [Display(Name = "Some Textbox")]
    [Required]
    public string SomeTextbox { get; set; }

If I now check for model state validity in my action method, the validation message ("The Basic Textbox field is required.") is correctly displayed by the ValidationMessageFor helper when I submit the form with no content in the textbox:

public class MyController : Controller
{
    [HttpGet]
    public ActionResult Index()
    {
        return View(new SomeModel());
    }

    [HttpPost]
    public ActionResult Index(SomeModel model)
    {
        if (!ModelState.IsValid)
        {
            // Server-side model validation failed; abort!
            return View(model);
        }
        ...

However, this stops working if, instead of POSTing to /Index, I POST to something like /Update and then do a redirect back to /Index if there's an error in the model. This is because ModelState only lasts for the current HTTP request context, and ValidationMessageFor relies on ModelState to get its error messages. When you redirect back to /Index, this state is lost.

This is exactly what TempData was designed to get around, as it keeps its session state until it is read in a later HTTP request. However, ModelState doesn't seem to use a mechanism like this.

Is there a way to have ModelState use some mechanism like TempData so that if I POST to a different URL and redirect back upon an invalid model state, I correctly get the error messages rendered to the page using ValidationMessageFor (and, more generally, I retain the ModelState from the form submission before I redirected)?

Upvotes: 1

Views: 1007

Answers (1)

Jez
Jez

Reputation: 30013

OK so basically I've found out that what I was describing was the PRG model, which isn't usually used in ASP.NET. You usually POST back to the same URL and so you have the HTTP context in which you POSTed, and only redirect in the case of a success in which case you no longer need the ModelState. People have come up with workarounds to implement PRG in ASP.NET, though, such as:
https://andrewlock.net/post-redirect-get-using-tempdata-in-asp-net-core/

Upvotes: 1

Related Questions