Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I manually bind data from a ModelStateDictionary to a presentation model with ASP.NET MVC?

Tags:

I wrote an application using ASP.NET MVC 5 framework. I am using a two way binding between the views and the ViewModels.

Since I am using two way binding, I get the benefit of client and server side validation which is cool. However, when I send a POST request to the server, and the request handler throws an exception, I want to redirect the user to the GET method.

When the redirect happens, I want to save the model state so that the page looks the same when I display the errors. I am able to save the state model and the errors using ActionFilters and TempData via this approach. However, when the request is redirected, from POST to GET the model state is saved as System.Web.Mvc.ModelStateDictionary object which is a key/value pair with all the user input that came from the POST request.

In order to present the page correctly to the end user, I need to bind the data in System.Web.Mvc.ModelStateDictionary to my own presentation model.

How can I bind the System.Web.Mvc.ModelStateDictionary object to my presentation object?

Here is how my code looks like

[ImportModelStateFromTempData]
public ActionResult show(int id)
{

    var prsenter = new UserProfileDetailsPresenter(id);

    ModelStateDictionary tmp = TempData["Support.ModelStateTempDataTransfer"];

    if(tmp != null)
    {
        // Some how map tmp to prsenter
    }

    return View(prsenter);

}

[HttpPost]
[ValidateAntiForgeryToken]
[ExportModelStateToTempData]
public ActionResult Update(int id, DetailsPresenter model)
{
    try
    {
        if (ModelState.IsValid)
        {
            var updater = new UpdateAddressServiceProvider(CurrentUser);

            updater.Handle(model.General);
        }

    }
    catch (Exception exception)
    {
        ModelState.AddModelError("error", exception.Message);
    } finally
    {
        return new RedirectResult(Url.Action("Show", new { Id = id }) + "#General");
    }
}
like image 407
Jaylen Avatar asked Dec 08 '16 18:12

Jaylen


1 Answers

If there's an error, don't redirect, just return the View.

[HttpPost]
[ValidateAntiForgeryToken]
[ExportModelStateToTempData]
public ActionResult Update(int id, DetailsPresenter model)
{
    try
    {
        if (ModelState.IsValid)
        {
            var updater = new UpdateAddressServiceProvider(CurrentUser);

            updater.Handle(model.General);
        }

        return new RedirectResult(Url.Action("Show", new { Id = id }) + "#General");
    }
    catch (Exception exception)
    {
        ModelState.AddModelError("error", exception.Message);

        // Return the named view directly, and pass in the model as it stands.
        return View("Show", model);
    }
}
like image 130
krillgar Avatar answered Sep 22 '22 14:09

krillgar