如何在 ExecuteResultAsync 中访问 ViewDataDictionary?
How to access ViewDataDictionary inside ExecuteResultAsync?
简介
我正在尝试使用扩展方法装饰 Action - ViewResult
。目标是能够在 Controller
之外的 Decorator 的使用范围内设置 ViewData
。但是,我只能访问 TempData
,而我想在方法 ExecuteResultAsync
中访问 ViewData
。
问题
How to access ViewData from ExecuteResultAsync within use of accessing to ActionContext? Is this the following
scenario at all possible?
场景
所以不要这样写:
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);
}
}
对于 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)
中访问ViewData
。您无法通过已解析的服务访问它。
您可以尝试通过反映 IActionResult
来访问 ViewData
。
尝试
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);
}
}
简介
我正在尝试使用扩展方法装饰 Action - ViewResult
。目标是能够在 Controller
之外的 Decorator 的使用范围内设置 ViewData
。但是,我只能访问 TempData
,而我想在方法 ExecuteResultAsync
中访问 ViewData
。
问题
How to access ViewData from ExecuteResultAsync within use of accessing to ActionContext? Is this the following scenario at all possible?
场景
所以不要这样写:
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);
}
}
对于 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)
中访问ViewData
。您无法通过已解析的服务访问它。
您可以尝试通过反映 IActionResult
来访问 ViewData
。
尝试
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);
}
}