43

I am trying to access the Model data passed to the view in the action filter OnActionExecuted. Does anyone know if this is possible?

I am trying to do something like this:

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    //get model data
    //...

    sitemap.SetCurrentNode(model.Name);
}

Any advice?

ebrown
  • 811
  • 1
  • 8
  • 13

5 Answers5

59

The model is at:

filterContext.Controller.ViewData.Model
Steven Lyons
  • 8,138
  • 1
  • 28
  • 27
  • 4
    @Korayem - depends on how early you try and access it. If you get it after the controller action has executed it should be an instance of the viewmodel. – JBeckton Jan 25 '13 at 03:53
  • 10
    It's null for me in all method (OnActionExecuting, OnActionExecuted, OnResultExecuting, OnResultExecuted) – Péter Sep 18 '13 at 11:26
  • 3
    please see the [pipeline schematics](http://www.dotnettricks.com/learn/mvc/detailed-aspnet-mvc-pipeline), to understand when the model is set on the viewdata. – QuantumHive Oct 27 '16 at 12:32
  • `ViewData.Model` is not available in `OnActionExecution` method of ActionFilter, see [this answer](https://stackoverflow.com/questions/61694278/understanding-asp-net-mvc-lifecycle-why-is-model-not-available-in-actionfilter/61724680#61724680) if you want to get the model in `OnActionExecution` – Hooman Bahreini May 11 '20 at 09:24
20

I don't know why but filterContext.Controller.ViewData.Model is always null even when the model bind is executed before OnActionExecuted. I found a solution using the OnModelUpdated event to set that property before.

I have the model binder:

public class CustomModelBinder: DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        controllerContext.Controller.ViewData.Model = bindingContext.Model;
        base.OnModelUpdated(controllerContext, bindingContext);
    }
}

After that you need to set the default binder to your new model binder in Application_Start() section in Global.asax:

ModelBinders.Binders.DefaultBinder = new CustomModelBinder();

Finally you can access your Model in an ActionFilterAttribute:

public class TraceLog : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //filterContext.Controller.ViewData.Model now isn't null
        base.OnActionExecuted(filterContext);
    }
}
BartoszKP
  • 34,786
  • 15
  • 102
  • 130
gustavocs
  • 210
  • 2
  • 5
4

Making the base.OnActionExecuted() call the last line of the method solved the 'Model being null' problem for me.

(This is a comment to @Steven Lyons 's answer, but I'm posting as an answer because I can't comment.)

Arun Kumar A.J
  • 121
  • 1
  • 7
2

In .Net Core you have an ActionArguments IDictionary on the context, with all the parameters from your method

So if you have the following controller method

    [HttpPost]
    public void Post([FromBody]BaseRequest request)
    {
    }

You can access the field like so

    public override void OnActionExecuting(ActionExecutingContext context)
    {
      var request = context.ActionArguments["request"] as BaseRequest;`
      //do whatever, 
    }
Safin Ahmed
  • 560
  • 4
  • 12
1

If you are getting null - as alternative to @Gustavo Clemente's answer you can try overriding OnActionExecuted and passing your viewModel into view in following way:

Action:

[Breadcrumb("Index")]
public ActionResult UnitIndex()
{
    View(new Answers());
}

Attribute:

public class BreadcrumbAttribute : ActionFilterAttribute
{
    public string Page { get; set; }

    public BreadcrumbAttribute(string page)
    {
        Page = page;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var model = (IBreadcrumbs)filterContext.Controller.ViewData.Model;
        model.Breadcrumbs = BreadcrumbHelper.GetBreadCrumbs(string.Format("{0}", filterContext.RouteData.DataTokens["area"]), Page);
    }
}

enter image description here

Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265
  • Where is this code from? Strangely I was looking for an answer to this question specifically in the context of wiring up a breadcrumbs solution in a recent project! – Crescent Fresh Oct 18 '16 at 15:25