Reputation: 3038
Struggling to figure out why I am getting null returned from BindModel here. I have an attribute that is extending ActionFilterAttribute
...
public class MyCachedAttribute : ActionFilterAttribute
{
private IModelBinder binder = new DefaultModelBinder();
private Type model;
public MyCachedAttribute(Type model)
{
this.model = model;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
ModelBindingContext bindingContext = new ModelBindingContext()
{
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, model),
ModelName = model.Name,
ModelState = filterContext.Controller.ViewData.ModelState,
ValueProvider = filterContext.Controller.ValueProvider
};
object data = binder.BindModel(filterContext.Controller.ControllerContext, bindingContext);
The data
at this point is null
.
Edit: I've come back to this and realised ModelState
is empty (so causing the null
) because the method has no model passed in normally (hence why I am binding in this circumstance, to pick it up).
[MyCached(typeof(FooViewModel))]
public ActionResult Foo()
{
return PartialView(new FooViewModel());
}
How can I generate the ModelState
for the type I have, and pass it into the binder? I am trying to avoid adding the model as an input parameter, since it causes problems, but its looking like I may have to sort those problems instead if this continues being an issue.
Thanks.
Edit2: I am using an ActionFilterAttribute here to modify the model sent as response in some circumstances, and in other circumstances it accepts a model to update in the cache. In this instance I need to bind it.
Upvotes: 0
Views: 1243
Reputation: 5407
You should do model binding in modelbinder. Not ActionFilter. ActionFilters are for intercepting and modifying requests and responses. So, clean up your ActionResult like this.
public ActionResult Foo(FooViewModel model)
{
return PartialView(model);
}
Then create a custom model binder.
public class CachedModelBinder : DefaultModelBinder {
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
object data = base.BindModel(controllerContext, bindingContext);
// data is not null anymore. You can do your custom stuff now, then return the model
return data;
}
And register it in in Application_Start()
in your global.asax.cs
ModelBinders.Binders.Add(typeof(FooViewModel), new CachedModelBinder());
Upvotes: 2