Is the MVC Model null in the OnExecuted action filter ... or a more elegant way to set the model?

I have an ActionFilter overridden by the OnActionExecuted method. The Context.Controller.ViewData.Model filter is always null for a POST operation. I found the following article, which seems to say that it should not be null, but it must have been an earlier version of MVC. This is MVC3. What should i get?

Model presence inside ActionFilter

UPDATE:

I understood the answer to the original question. I had a custom ActionResult that outputs JSON with custom date formatting. The problem was that the model is not installed in the controller.

In my custom ActionResult, the ExecuteResult method gets the passed ControllerContext, which would be nice if I could set the model there:

context.Controller.ViewData.Model = _data; 

But this is already at the end of the loop, and the result is still not valid in ActionFilter. This means that I need to manually install the model in the controller:

 ControllerContext.Controller.ViewData.Model = model; 

Or

 View(model); 

Which means that I need to keep this in mind every time I use this custom ActionResult. Is there a more elegant way?

GIVE ANOTHER UPDATE:

I found a way to do this, it's just not as elegant as I had hoped.

In my constructor for comstom ActionResult, which I send to the controller, this method will at least always be consistent:

 public JsonNetResult(object data, Controller controller) { SerializerSettings = new JsonSerializerSettings(); _data = data; controller.ControllerContext.Controller.ViewData.Model = _data; } 
+6
source share
2 answers

Another approach is to use a basic controller to automatically process the storage of a collection of action parameters for later use:

 public class BaseController : Controller { protected override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Items["ActionParms"] = filterContext.ActionParameters.ToDictionary(p => p.Key, p => p.Value); base.OnActionExecuting(filterContext); } } 

then in your attribute:

 public override void OnActionExecuted(ActionExecutedContext filterContext) { var dictionary = filterContext.HttpContext.Items["ActionParms"] as Dictionary<string, object>; if (dictionary != null) { foreach (var o in dictionary.Keys) { // do something here } } base.OnActionExecuted(filterContext); } 

It uses HttpContext elements which are not very pleasant, but I do not know that you can access the ViewBag or ViewData in the attribute.

To decide whether you want to process the request in your attribute, you can poll the action name and other parameter information:

 var action = filterContext.ActionDescriptor.ActionName; var parms = filterContext.ActionDescriptor.GetParameters(); foreach (var parameterDescriptor in parms) { // do something here } 
+2
source

I found a solution similar to yours using the OnModelUpdated event to set this property earlier.

I have a ModelBinder:

 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 middleware on the new middleware in the Application_Start () section of Global.asax:

ModelBinders.Binders.DefaultBinder = new CustomModelBinder ();

Finally, you can access your model in ActionFilter:

 public class TraceLog : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext filterContext) { //filterContext.Controller.ViewData.Model now isn't null base.OnActionExecuted(filterContext); } } 
+1
source

Source: https://habr.com/ru/post/889221/


All Articles