问题描述
|
我有一个带有OnActionExecuted方法重写的ActionFilter。在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 = new CustomModelBinder();
最后,您可以在ActionFilter中访问模型:
public class TraceLog : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
//filterContext.Controller.ViewData.Model now isn\'t null
base.OnActionExecuted(filterContext);
}
}