[Fixes #4223] Added a facade for ViewComponentResult
This commit is contained in:
parent
8493064fe5
commit
5f4ca4fa66
|
|
@ -139,6 +139,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
services.TryAddSingleton<
|
||||
IViewComponentDescriptorCollectionProvider,
|
||||
DefaultViewComponentDescriptorCollectionProvider>();
|
||||
services.TryAddSingleton<ViewComponentResultExecutor>();
|
||||
|
||||
services.TryAddSingleton<ViewComponentInvokerCache>();
|
||||
services.TryAddTransient<IViewComponentDescriptorProvider, DefaultViewComponentDescriptorProvider>();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,142 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
|
||||
{
|
||||
public class ViewComponentResultExecutor
|
||||
{
|
||||
private readonly HtmlEncoder _htmlEncoder;
|
||||
private readonly HtmlHelperOptions _htmlHelperOptions;
|
||||
private readonly ILogger<ViewComponentResult> _logger;
|
||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||
private readonly ITempDataDictionaryFactory _tempDataDictionaryFactory;
|
||||
private readonly IViewComponentHelper _viewComponentHelper;
|
||||
|
||||
public ViewComponentResultExecutor(
|
||||
IOptions<MvcViewOptions> mvcHelperOptions,
|
||||
IViewComponentHelper viewComponentHelper,
|
||||
ILoggerFactory loggerFactory,
|
||||
HtmlEncoder htmlEncoder,
|
||||
IModelMetadataProvider modelMetadataProvider,
|
||||
ITempDataDictionaryFactory tempDataDictionaryFactory)
|
||||
{
|
||||
if (mvcHelperOptions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(mvcHelperOptions));
|
||||
}
|
||||
|
||||
if (viewComponentHelper == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(viewComponentHelper));
|
||||
}
|
||||
|
||||
if (loggerFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(loggerFactory));
|
||||
}
|
||||
|
||||
if (htmlEncoder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(htmlEncoder));
|
||||
}
|
||||
|
||||
if (modelMetadataProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modelMetadataProvider));
|
||||
}
|
||||
|
||||
if (tempDataDictionaryFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tempDataDictionaryFactory));
|
||||
}
|
||||
|
||||
_htmlHelperOptions = mvcHelperOptions.Value.HtmlHelperOptions;
|
||||
_viewComponentHelper = viewComponentHelper;
|
||||
_logger = loggerFactory.CreateLogger<ViewComponentResult>();
|
||||
_htmlEncoder = htmlEncoder;
|
||||
_modelMetadataProvider = modelMetadataProvider;
|
||||
_tempDataDictionaryFactory = tempDataDictionaryFactory;
|
||||
}
|
||||
|
||||
public async Task ExecuteAsync(ActionContext context, ViewComponentResult viewComponentResult)
|
||||
{
|
||||
var response = context.HttpContext.Response;
|
||||
|
||||
var viewData = viewComponentResult.ViewData;
|
||||
if (viewData == null)
|
||||
{
|
||||
viewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState);
|
||||
}
|
||||
|
||||
var tempData = viewComponentResult.TempData;
|
||||
if (tempData == null)
|
||||
{
|
||||
tempData = _tempDataDictionaryFactory.GetTempData(context.HttpContext);
|
||||
}
|
||||
|
||||
string resolvedContentType;
|
||||
Encoding resolvedContentTypeEncoding;
|
||||
ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
|
||||
viewComponentResult.ContentType,
|
||||
response.ContentType,
|
||||
ViewExecutor.DefaultContentType,
|
||||
out resolvedContentType,
|
||||
out resolvedContentTypeEncoding);
|
||||
|
||||
response.ContentType = resolvedContentType;
|
||||
|
||||
if (viewComponentResult.StatusCode != null)
|
||||
{
|
||||
response.StatusCode = viewComponentResult.StatusCode.Value;
|
||||
}
|
||||
|
||||
using (var writer = new HttpResponseStreamWriter(response.Body, resolvedContentTypeEncoding))
|
||||
{
|
||||
var viewContext = new ViewContext(
|
||||
context,
|
||||
NullView.Instance,
|
||||
viewData,
|
||||
tempData,
|
||||
writer,
|
||||
_htmlHelperOptions);
|
||||
|
||||
(_viewComponentHelper as IViewContextAware)?.Contextualize(viewContext);
|
||||
var result = await GetViewComponentResult(_viewComponentHelper, _logger, viewComponentResult);
|
||||
|
||||
result.WriteTo(writer, _htmlEncoder);
|
||||
}
|
||||
}
|
||||
|
||||
private Task<IHtmlContent> GetViewComponentResult(IViewComponentHelper viewComponentHelper, ILogger logger, ViewComponentResult result)
|
||||
{
|
||||
if (result.ViewComponentType == null && result.ViewComponentName == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatViewComponentResult_NameOrTypeMustBeSet(
|
||||
nameof(ViewComponentResult.ViewComponentName),
|
||||
nameof(ViewComponentResult.ViewComponentType)));
|
||||
}
|
||||
else if (result.ViewComponentType == null)
|
||||
{
|
||||
logger.ViewComponentResultExecuting(result.ViewComponentName);
|
||||
return viewComponentHelper.InvokeAsync(result.ViewComponentName, result.Arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.ViewComponentResultExecuting(result.ViewComponentType);
|
||||
return viewComponentHelper.InvokeAsync(result.ViewComponentType, result.Arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,20 +2,11 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.ViewEngines;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
|
|
@ -68,83 +59,16 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public IViewEngine ViewEngine { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task ExecuteResultAsync(ActionContext context)
|
||||
public override Task ExecuteResultAsync(ActionContext context)
|
||||
{
|
||||
var response = context.HttpContext.Response;
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var services = context.HttpContext.RequestServices;
|
||||
|
||||
var htmlHelperOptions = services.GetRequiredService<IOptions<MvcViewOptions>>().Value.HtmlHelperOptions;
|
||||
var viewComponentHelper = services.GetRequiredService<IViewComponentHelper>();
|
||||
|
||||
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
|
||||
var logger = loggerFactory.CreateLogger<ViewComponentResult>();
|
||||
var htmlEncoder = services.GetRequiredService<HtmlEncoder>();
|
||||
|
||||
var viewData = ViewData;
|
||||
if (viewData == null)
|
||||
{
|
||||
var modelMetadataProvider = services.GetRequiredService<IModelMetadataProvider>();
|
||||
viewData = new ViewDataDictionary(modelMetadataProvider, context.ModelState);
|
||||
}
|
||||
|
||||
var tempData = TempData;
|
||||
if (tempData == null)
|
||||
{
|
||||
var factory = services.GetRequiredService<ITempDataDictionaryFactory>();
|
||||
tempData = factory.GetTempData(context.HttpContext);
|
||||
}
|
||||
|
||||
string resolvedContentType = null;
|
||||
Encoding resolvedContentTypeEncoding = null;
|
||||
ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
|
||||
ContentType,
|
||||
response.ContentType,
|
||||
ViewExecutor.DefaultContentType,
|
||||
out resolvedContentType,
|
||||
out resolvedContentTypeEncoding);
|
||||
|
||||
response.ContentType = resolvedContentType;
|
||||
|
||||
if (StatusCode != null)
|
||||
{
|
||||
response.StatusCode = StatusCode.Value;
|
||||
}
|
||||
|
||||
using (var writer = new HttpResponseStreamWriter(response.Body, resolvedContentTypeEncoding))
|
||||
{
|
||||
var viewContext = new ViewContext(
|
||||
context,
|
||||
NullView.Instance,
|
||||
viewData,
|
||||
tempData,
|
||||
writer,
|
||||
htmlHelperOptions);
|
||||
|
||||
(viewComponentHelper as IViewContextAware)?.Contextualize(viewContext);
|
||||
var result = await GetViewComponentResult(viewComponentHelper, logger);
|
||||
|
||||
result.WriteTo(writer, htmlEncoder);
|
||||
}
|
||||
}
|
||||
|
||||
private Task<IHtmlContent> GetViewComponentResult(IViewComponentHelper viewComponentHelper, ILogger logger)
|
||||
{
|
||||
if (ViewComponentType == null && ViewComponentName == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatViewComponentResult_NameOrTypeMustBeSet(
|
||||
nameof(ViewComponentName),
|
||||
nameof(ViewComponentType)));
|
||||
}
|
||||
else if (ViewComponentType == null)
|
||||
{
|
||||
logger.ViewComponentResultExecuting(ViewComponentName);
|
||||
return viewComponentHelper.InvokeAsync(ViewComponentName, Arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.ViewComponentResultExecuting(ViewComponentType);
|
||||
return viewComponentHelper.InvokeAsync(ViewComponentType, Arguments);
|
||||
}
|
||||
var executor = services.GetRequiredService<ViewComponentResultExecutor>();
|
||||
return executor.ExecuteAsync(context, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -532,6 +532,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
services.AddSingleton<ITempDataProvider, SessionStateTempDataProvider>();
|
||||
services.AddSingleton<HtmlEncoder, HtmlTestEncoder>();
|
||||
services.AddSingleton<IViewBufferScope, TestViewBufferScope>();
|
||||
services.AddSingleton<ViewComponentResultExecutor>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue