我有一个ActionFilter,它覆盖了OnActionExecuted方法。在POST操作中,filterContext.Controller.ViewData.Model始终为null。我确实发现下面的文章似乎在说它不应该为null,但这一定是MVC的早期版本。这是MVC3。我应该得到什么?
ActionFilter 内的模型可用性
更新:
我已经找到了原来问题的答案。我有一个自定义ActionResult,它使用自定义日期格式化程序输出JSON。问题是没有在控制器中设置模型。
在我的自定义ActionResult中,ExecuteResult方法传递了ControllerContext,如果我能在那里设置Model,那就太好了:
context.Controller.ViewData.Model = _data;
但这已经到了周期的后期,ActionFilter中的结果仍然为null。这似乎意味着我需要在控制器中手动设置模型:
ControllerContext.Controller.ViewData.Model = model;
或
View(model);
这意味着我每次使用这个自定义ActionResult时都需要记住这样做。还有更优雅的方式吗?
另一个更新:
我找到了一种方法——它并不像我希望的那样优雅。
在我向控制器发送的comstom ActionResult的构造函数中,至少它总是一致的:
public JsonNetResult(object data, Controller controller) {
SerializerSettings = new JsonSerializerSettings();
_data = data;
controller.ControllerContext.Controller.ViewData.Model = _data;
}
另一种方法是使用基本控制器来自动处理动作参数集合的存储以供以后使用:
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);
}
}
然后在您的属性中:
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);
}
它使用HttpContext项,这不是很好,但我不知道你是否可以访问属性中的ViewBag或ViewData。
为了决定是否要处理属性中的请求,您可以询问操作名称和其他参数信息:
var action = filterContext.ActionDescriptor.ActionName;
var parms = filterContext.ActionDescriptor.GetParameters();
foreach (var parameterDescriptor in parms)
{
// do something here
}
我发现了一个类似于您的解决方案,以前使用OnModelUpdated事件来设置该属性。
我有ModelBinder:
public class CustomModelBinder: DefaultModelBinder
{
protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
controllerContext.Controller.ViewData.Model = bindingContext.Model;
base.OnModelUpdated(controllerContext, bindingContext);
}
}
之后,您需要在Global.asax:的Application_Start()部分将默认绑定器设置为新模型绑定器
ModelBinders.Binders.DefaultBinder=新的自定义ModelBinder();
最后,您可以在ActionFilter中访问您的模型:
public class TraceLog : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext filterContext) { //filterContext.Controller.ViewData.Model now isn't null base.OnActionExecuted(filterContext); } }