【问题标题】:MVC Model is null in OnExecuted action filter ... or a more elegant way to set the model?MVC 模型在 OnExecuted 操作过滤器中为空......或者设置模型的更优雅的方式?
【发布时间】:2011-05-27 16:24:18
【问题描述】:

我有一个 ActionFilter,它覆盖了 OnActionExecuted 方法。 filterContext.Controller.ViewData.Model 在 POST 操作中始终为空。我确实发现以下文章似乎在说它不应该为空,但这一定是 MVC 的早期版本。这是MVC3。我应该得到什么?

Model availability inside ActionFilter

更新:

我已经找到了原始问题的答案。我有一个自定义 ActionResult,它使用自定义日期格式化程序输出 JSON。问题是模型没有在控制器中设置。

在我的自定义 ActionResult 中,ExecuteResult 方法通过了 ControllerContext,如果我可以在那里设置模型,那就太好了:

context.Controller.ViewData.Model = _data;

但这是周期的后期,结果在 ActionFilter 中仍然为空。这似乎意味着我需要在控制器中手动设置模型:

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;
}

【问题讨论】:

标签: asp.net-mvc-3 model null controller onactionexecuted


【解决方案1】:

另一种方法是使用基本控制器来自动处理动作参数集合的存储以供以后使用:

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
}

【讨论】:

    【解决方案2】:

    我找到了一个像你这样的解决方案,之前使用 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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-05
      • 1970-01-01
      • 2016-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多