代码之家  ›  专栏  ›  技术社区  ›  Arsiwaldi

如何访问ExecuteResultAsync内的ViewDataDictionary?

  •  0
  • Arsiwaldi  · 技术社区  · 5 年前

    简介

    我想装饰一下 Action - ViewResult 使用扩展方法。目标是能够设定的 ViewData 在装饰师的使用范围内,在 Controller . 但是,我只能访问 TempData 但是我想进入 可视数据 方法内部 ExecuteResultAsync .

    问题

    如何在访问ActionContext的过程中从ExecuteResultAsync访问viewData?这是下列吗 可能的情况?

    脚本

    因此,不要写以下内容:

    public async Task<IActionResult> ChangePassword()
    {
        ViewData["Title"] = "Change Password";
        return PartialView("_ChangePasswordPartial",...);
    }
    

    我想让它像这样工作:

    public async Task<IActionResult> ChangePassword()
    {
        return PartialView("_ChangePasswordPartial",...).WithTitle("Change Password");
    }
    

    扩展方法:

    public static IActionResult WithTitle(this IActionResult action, string modalTitle)
    {
        return new ModalTitleDecorator(action,modalTitle);
    }
    

    装饰者:

    public class ModalTitleDecorator : ActionResult
    {
         private readonly IActionResult _actionResult;
         private readonly string _modalTitle;
    
         public ModalTitleDecorator(IActionResult action, string modalTitle)
         {
             _actionResult = action;
             _modalTitle = modalTitle;
         }
    
          public override async Task ExecuteResultAsync(ActionContext context)
          {
    
              var tempData = context.HttpContext.RequestServices.GetService<ITempDataDictionaryFactory>()
                       .GetTempData(context.HttpContext);
    
             //always null...I assume that ViewData is not available according to HttpContext. 
             //TempData is available probably according to passing into next request.
             var viewData = context.HttpContext.RequestServices.GetService<ViewDataDictionary>();
    
             //something like this would be great
             ViewData["Title"] = _modalTitle;
    
             await _actionResult.ExecuteResultAsync(context);
          }
    }
    
    1 回复  |  直到 5 年前
        1
  •  1
  •   Edward    5 年前

    为了 ViewData ,无法通过解决 context.HttpContext.RequestServices.GetService .

    /// <summary>
    /// Gets or sets <see cref="ViewDataDictionary"/> used by <see cref="ViewResult"/> and <see cref="ViewBag"/>.
    /// </summary>
    /// <remarks>
    /// By default, this property is intiailized when <see cref="Controllers.IControllerActivator"/> activates
    /// controllers.
    /// <para>
    /// This property can be accessed after the controller has been activated, for example, in a controller action
    /// or by overriding <see cref="OnActionExecuting(ActionExecutingContext)"/>.
    /// </para>
    /// <para>
    /// This property can be also accessed from within a unit test where it is initialized with
    /// <see cref="EmptyModelMetadataProvider"/>.
    /// </para>
    /// </remarks>
    [ViewDataDictionary]
    public ViewDataDictionary ViewData
    

    如上所述,您只能访问 可视数据 在里面 Controller OnActionExecuting(ActionExecutingContext) . 您无法通过解析的服务访问它。

    你可以试着进入 可视数据 通过反射 IActionResult .

    尝试

    public static class ActionResultExtension
    {
        public static IActionResult WithTitle(this IActionResult action, string modalTitle)
        {
            return new ModalTitleDecorator(action, modalTitle);
        }
    }
    
    public class ModalTitleDecorator : PartialViewResult
    {
        private readonly IActionResult _actionResult;
        private readonly string _modalTitle;
    
        public ModalTitleDecorator(IActionResult action, string modalTitle)
        {
            _actionResult = action;
            _modalTitle = modalTitle;
        }
    
        public override async Task ExecuteResultAsync(ActionContext context)
        {
            ViewDataDictionary viewData = _actionResult
                                        .GetType()
                                        .GetProperty("ViewData")
                                        .GetValue(_actionResult) as ViewDataDictionary;
            if (viewData != null)
            {
                viewData["Title"] = _modalTitle;
            }
            await _actionResult.ExecuteResultAsync(context);
        }
    }