Any way to recover model passed to POST action when inside OnException(ExceptionContext filterContext)?
Asked Answered
B

1

7

Situation is this:

I can't find a way of getting the viewModel that was passed to the POST action method.

[HttpPost]
public ActionResult Edit(SomeCoolModel viewModel)
{
    // Some Exception happens here during the action execution...
}

Inside the overridable OnException for the controller:

protected override void OnException(ExceptionContext filterContext)
{
    ...

    filterContext.Result = new ViewResult
    {
        ViewName = filterContext.RouteData.Values["action"].ToString(),
        TempData = filterContext.Controller.TempData,
        ViewData = filterContext.Controller.ViewData
    };
}

When debugging the code filterContext.Controller.ViewData is null since the exception occurred while the code was executing and no view was returned.

Anyways I see that filterContext.Controller.ViewData.ModelState is filled and has all the values that I need but I don't have the full ViewData => viewModel object available. :(

I want to return the same View with the posted data/ViewModel back to the user in a central point. Hope you get my drift.

Is there any other path I can follow to achieve the objective?

Baneful answered 9/8, 2014 at 0:15 Comment(2)
Not entirely sure I get your drift, but in the OnException() method you could try something like MyModel m = new MyModel(); TryUpdateModel<MyModel>(m); to give you the model, but of course you would need to know the type so not very flexibleBosnia
@StephenMuecke awesome start... It filled the model with the ModelState values but the bad part is what you mentioned: it's not dynamic\flexible. I'm looking to add some bit of dynamic to this. :) If I get this to work it will allow me to avoid writing a lot of repetitive code.Baneful
B
8

You could create a custom model binder that inherits from DefaultModelBinder and assign the model to TempData:

public class MyCustomerBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        base.OnModelUpdated(controllerContext, bindingContext);

        controllerContext.Controller.TempData["model"] = bindingContext.Model;
    }
}

and register it in Global.asax:

ModelBinders.Binders.DefaultBinder = new MyCustomerBinder();

then access it:

protected override void OnException(ExceptionContext filterContext)
{
    var model = filterContext.Controller.TempData["model"];

    ...
}
Bosnia answered 9/8, 2014 at 7:17 Comment(2)
WAO! Worked beautifully... ASP.NET MVC is so good that you can plug into it in so many places: the thing is to know where to plug. God bless your life. :-)Baneful
Two years later and still working as a charm! Thanks.Montfort

© 2022 - 2024 — McMap. All rights reserved.