【问题标题】:Asp.net mvc - Accessing view Model from a custom Action filterAsp.net mvc - 从自定义操作过滤器访问视图模型
【发布时间】:2009-05-16 16:52:11
【问题描述】:

我正在尝试访问传递给操作过滤器 OnActionExecuted 中的视图的模型数据。有谁知道这是否可能?

我正在尝试做这样的事情:

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

    sitemap.SetCurrentNode(model.Name);
}

有什么建议吗?

【问题讨论】:

    标签: c# asp.net-mvc custom-action-filter


    【解决方案1】:

    模型位于:

    filterContext.Controller.ViewData.Model
    

    【讨论】:

    • @Korayem - 取决于您尝试访问它的时间。如果你在控制器动作执行后得到它,它应该是 viewmodel 的一个实例。
    • 所有方法对我来说都是空的(OnActionExecuting、OnActionExecuted、OnResultExecuting、OnResultExecuted)
    • 请查看pipeline schematics,了解何时在视图数据上设置模型。
    • ViewData.Model在ActionFilter的OnActionExecution方法中不可用,如果要获取OnActionExecution中的模型,请参阅this answer
    【解决方案2】:

    我不知道为什么,但即使模型绑定在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);
        }
    }
    

    【讨论】:

      【解决方案3】:

      base.OnActionExecuted() 调用该方法的最后一行为我解决了“模型为空”问题。

      (这是对@Steven Lyons 答案的评论,但我将作为答案发布,因为我无法发表评论。)

      【讨论】:

        【解决方案4】:

        在 .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, 
            }
        

        【讨论】:

          【解决方案5】:

          如果您得到 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);
              }
          }
          

          【讨论】:

          • 这段代码来自哪里?奇怪的是,我一直在寻找这个问题的答案,特别是在最近一个项目中连接面包屑解决方案的背景下!
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多