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

谁说我不能喝 提交于 2019-11-27 01:13:56

问题


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?


回答1:


The model is at:

filterContext.Controller.ViewData.Model



回答2:


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);
    }
}



回答3:


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.)




回答4:


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, 
    }



回答5:


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);
    }
}



来源:https://stackoverflow.com/questions/872796/asp-net-mvc-accessing-view-model-from-a-custom-action-filter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!