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?
The model is at:
filterContext.Controller.ViewData.Model
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);
}
}
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,
}
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.)
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