ASP.NET MVC - 如何从自定义操作过滤器中访问视图模型

43

我正在尝试在OnActionExecuted操作筛选器中访问传递给视图的模型数据。有人知道是否可能吗?

我想实现类似于以下操作:

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    //get model data
    //...

    sitemap.SetCurrentNode(model.Name);
}

有什么建议吗?

5个回答

59

该模型位于:

filterContext.Controller.ViewData.Model

4
取决于您尝试访问它的时间。如果您在控制器操作执行后获取它,它应该是视图模型的一个实例。 - JBeckton
10
在所有方法中(OnActionExecuting、OnActionExecuted、OnResultExecuting、OnResultExecuted),对于我来说都是 null。 - Péter
3
请查看管道图解,以了解何时将模型设置在ViewData上。 - QuantumHive
ViewData.Model is not available in OnActionExecution method of ActionFilter, see this answer if you want to get the model in OnActionExecution - Hooman Bahreini

20

我不知道为什么,但是即使在OnActionExecuted之前执行了模型绑定,filterContext.Controller.ViewData.Model始终为空。我发现了一种解决方法,使用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();

最后,你可以在一个 ActionFilterAttribute 中访问你的 Model:

public class TraceLog : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //filterContext.Controller.ViewData.Model now isn't null
        base.OnActionExecuted(filterContext);
    }
}

4
在方法的最后一行调用base.OnActionExecuted()解决了“模型为空”的问题。(这是对@Steven Lyons答案的评论,但我发表为答案,因为我无法评论。)

2
在 .Net Core 中,您可以在上下文中使用 ActionArguments IDictionary 获取来自您的方法的所有参数。
因此,如果您有以下控制器方法:
    [HttpPost]
    public void Post([FromBody]BaseRequest request)
    {
    }

您可以像这样访问该字段。
    public override void OnActionExecuting(ActionExecutingContext context)
    {
      var request = context.ActionArguments["request"] as BaseRequest;`
      //do whatever, 
    }

1
如果您得到的是 null - 作为 @Gustavo Clemente 的答案的替代方案,您可以尝试覆盖 OnActionExecuted 并以以下方式将您的 viewModel 传递到视图中: 操作:
[Breadcrumb("Index")]
public ActionResult UnitIndex()
{
    View(new Answers());
}

属性:

public class BreadcrumbAttribute : ActionFilterAttribute
{
    public string Page { get; set; }

    public BreadcrumbAttribute(string page)
    {
        Page = page;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var model = (IBreadcrumbs)filterContext.Controller.ViewData.Model;
        model.Breadcrumbs = BreadcrumbHelper.GetBreadCrumbs(string.Format("{0}", filterContext.RouteData.DataTokens["area"]), Page);
    }
}

enter image description here


这段代码来自哪里?奇怪的是我特别在最近的项目中寻找答案,以便布置面包屑导航解决方案! - Crescent Fresh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接