Как получить доступ к ViewDataDictionary внутри ExecuteResultAsync? - PullRequest
0 голосов
/ 31 января 2019

Intro

Я пытаюсь украсить Action - ViewResult при использовании метода расширения.Цель может быть в состоянии установить ViewData при использовании Decorator, за пределами Controller.Однако я могу получить доступ только к TempData, тогда как я хотел бы получить доступ к ViewData внутри метода ExecuteResultAsync.

Вопрос

Как получить доступ к ViewData из ExecuteResultAsync при использовании доступа к ActionContext?Возможен ли вообще следующий сценарий?

Сценарий

Итак, вместо написания следующего:

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 Ответ

0 голосов
/ 31 января 2019

Для 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

Как указано выше, вы можете получить доступ только к ViewData в Controller и OnActionExecuting(ActionExecutingContext).Вы не могли получить к нему доступ разрешенной службой.

Вы можете попытаться получить доступ к ViewData, отразив 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);
    }
}
...