7

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

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

2 回答 2

2

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

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
}
于 2012-06-26T14:29:34.593 回答
1

我找到了一个像你这样的解决方案,之前使用 OnModelUpdated 事件设置该属性。

我有模型绑定器:

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);
    }
}
于 2014-08-11T18:43:32.877 回答