Asp.net mvc - Accessing view Model from a custom Action filter
Asked Answered
K

5

42

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?

Kinata answered 16/5, 2009 at 16:52 Comment(0)
P
58

The model is at:

filterContext.Controller.ViewData.Model
Prelusive answered 16/5, 2009 at 16:56 Comment(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.Psychosomatics
It's null for me in all method (OnActionExecuting, OnActionExecuted, OnResultExecuting, OnResultExecuted)Tenebrific
please see the pipeline schematics, to understand when the model is set on the viewdata.Faus
ViewData.Model is not available in OnActionExecution method of ActionFilter, see this answer if you want to get the model in OnActionExecutionTierza
U
19

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);
    }
}
Unbelieving answered 11/8, 2014 at 18:32 Comment(0)
N
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.)

Nova answered 5/2, 2019 at 10:59 Comment(0)
I
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, 
    }
Inclinometer answered 12/1, 2017 at 0:8 Comment(0)
M
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

Monoatomic answered 17/11, 2015 at 13:53 Comment(1)
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!Metalworking

© 2022 - 2024 — McMap. All rights reserved.