/// <inheritdoc /> public async Task InvokeAsync(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var methodInfo = context.ViewComponentDescriptor?.MethodInfo; if (methodInfo == null) { throw new InvalidOperationException(Resources.FormatPropertyOfTypeCannotBeNull( nameof(ViewComponentDescriptor.MethodInfo), nameof(ViewComponentDescriptor))); } var isAsync = typeof(Task).GetTypeInfo().IsAssignableFrom(methodInfo.ReturnType.GetTypeInfo()); IViewComponentResult result; if (isAsync) { result = await InvokeAsyncCore(context); } else { // We support falling back to synchronous if there is no InvokeAsync method, in this case we'll still // execute the IViewResult asynchronously. result = InvokeSyncCore(context); } await result.ExecuteAsync(context); }
/// <summary> /// Renders JSON text to the output. /// </summary> /// <param name="context">The <see cref="ViewComponentContext"/>.</param> public void Execute(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var serializerSettings = _serializerSettings; if (serializerSettings == null) { serializerSettings = context .ViewContext .HttpContext .RequestServices .GetRequiredService<IOptions<MvcJsonOptions>>() .Value .SerializerSettings; } using (var jsonWriter = new JsonTextWriter(context.Writer)) { jsonWriter.CloseOutput = false; var jsonSerializer = JsonSerializer.Create(serializerSettings); jsonSerializer.Serialize(jsonWriter, Value); } }
/// <summary> /// Encodes and writes the <see cref="Content"/>. /// </summary> /// <param name="context">The <see cref="ViewComponentContext"/>.</param> public void Execute(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } context.HtmlEncoder.Encode(context.Writer, Content); }
/// <summary> /// Locates and renders a view specified by <see cref="ViewName"/>. If <see cref="ViewName"/> is <c>null</c>, /// then the view name searched for is<c>"Default"</c>. /// </summary> /// <param name="context">The <see cref="ViewComponentContext"/> for the current component execution.</param> /// <remarks> /// This method synchronously calls and blocks on <see cref="ExecuteAsync(ViewComponentContext)"/>. /// </remarks> public void Execute(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var task = ExecuteAsync(context); task.GetAwaiter().GetResult(); }
/// <summary> /// Renders JSON text to the output. /// </summary> /// <param name="context">The <see cref="ViewComponentContext"/>.</param> /// <returns>A completed <see cref="Task"/>.</returns> public Task ExecuteAsync(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } Execute(context); return Task.FromResult(true); }
private SimpleInjectorViewComponentInvoker CreateViewComponentInvoker(ViewComponentContext context) { IServiceProvider provider = context.ViewContext.HttpContext.RequestServices; return new SimpleInjectorViewComponentInvoker( provider.GetRequiredService<DiagnosticSource>(), provider.GetRequiredService<ILoggerFactory>().CreateLogger<SimpleInjectorViewComponentInvoker>(), provider.GetRequiredService<IViewComponentActivator>(), this.container); }
/// <inheritdoc /> // We don't currently make use of the descriptor or the arguments here (they are available on the context). // We might do this some day to cache which method we select, so resist the urge to 'clean' this without // considering that possibility. public IViewComponentInvoker CreateInstance(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } return new DefaultViewComponentInvoker( _typeActivatorCache, _viewComponentActivator); }
/// <summary>Creates a <see cref="IViewComponentInvoker"/>.</summary> /// <param name="context">The context</param> /// <returns>A <see cref="IViewComponentInvoker"/>.</returns> public IViewComponentInvoker CreateInstance(ViewComponentContext context) { Requires.IsNotNull(context, nameof(context)); if (this.invoker == null) { this.invoker = this.CreateViewComponentInvoker(context); } return this.invoker; }
public static void ViewComponentExecuted( this ILogger logger, ViewComponentContext context, int startTime, object result) { var elapsed = new TimeSpan(Environment.TickCount - startTime); _viewComponentExecuted( logger, context.ViewComponentDescriptor.DisplayName, elapsed.TotalMilliseconds, Convert.ToString(result), null); }
public void DefaultViewComponentActivator_ActivatesViewComponentContext() { // Arrange var activator = new DefaultViewComponentActivator(); var context = new ViewComponentContext(); var instance = new TestViewComponent(); // Act activator.Activate(instance, context); // Assert Assert.Same(context, instance.ViewComponentContext); }
public void DefaultViewComponentActivator_ActivatesViewComponentContext_IgnoresNonPublic() { // Arrange var activator = new DefaultViewComponentActivator(); var context = new ViewComponentContext(); var instance = new VisibilityViewComponent(); // Act activator.Activate(instance, context); // Assert Assert.Same(context, instance.ViewComponentContext); Assert.Null(instance.C); }
public static void ViewComponentAfterViewExecute( this DiagnosticSource diagnosticSource, ViewComponentContext context, IView view) { if (diagnosticSource.IsEnabled("Microsoft.AspNet.Mvc.ViewComponentAfterViewExecute")) { diagnosticSource.Write( "Microsoft.AspNet.Mvc.ViewComponentAfterViewExecute", new { actionDescriptor = context.ViewContext.ActionDescriptor, viewComponentContext = context, view = view }); } }
/// <summary> /// Writes the <see cref="EncodedContent"/>. /// </summary> /// <param name="context">The <see cref="ViewComponentContext"/>.</param> public void Execute(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var htmlWriter = context.Writer as HtmlTextWriter; if (htmlWriter == null) { EncodedContent.WriteTo(context.Writer, context.HtmlEncoder); } else { htmlWriter.Write(EncodedContent); } }
public static void BeforeViewComponent( this DiagnosticSource diagnosticSource, ViewComponentContext context, object viewComponent) { if (diagnosticSource.IsEnabled("Microsoft.AspNet.Mvc.BeforeViewComponent")) { diagnosticSource.Write( "Microsoft.AspNet.Mvc.BeforeViewComponent", new { actionDescriptor = context.ViewContext.ActionDescriptor, viewComponentContext = context, viewComponent = viewComponent }); } }
public IViewComponentResult InvokeSyncCore([NotNull] MethodInfo method, [NotNull] ViewComponentContext context) { var component = CreateComponent(context); object result = null; try { result = method.Invoke(component, context.Arguments); } catch (TargetInvocationException ex) { // Preserve callstack of any user-thrown exceptions. var exceptionInfo = ExceptionDispatchInfo.Capture(ex.InnerException); exceptionInfo.Throw(); } return(CoerceToViewComponentResult(result)); }
private async Task <IViewComponentResult> InvokeAsyncCore( MethodInfo method, ViewComponentContext context) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var component = CreateComponent(context); var result = await ControllerActionExecutor.ExecuteAsync(method, component, context.Arguments); return(CoerceToViewComponentResult(result)); }
public void Invoke(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var method = ViewComponentMethodSelector.FindSyncMethod( context.ViewComponentDescriptor.Type.GetTypeInfo(), context.Arguments); if (method == null) { throw new InvalidOperationException( Resources.FormatViewComponent_CannotFindMethod(ViewComponentMethodSelector.SyncMethodName)); } var result = InvokeSyncCore(method, context); result.Execute(context); }
public IViewComponentResult InvokeSyncCore(MethodInfo method, ViewComponentContext context) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var component = CreateComponent(context); object result = null; using (_logger.ViewComponentScope(context)) { _diagnosticSource.BeforeViewComponent(context, component); _logger.ViewComponentExecuting(context); try { var startTime = Environment.TickCount; result = method.Invoke(component, context.Arguments); var viewComponentResult = CoerceToViewComponentResult(result); _logger.ViewComponentExecuted(context, startTime, viewComponentResult); _diagnosticSource.AfterViewComponent(context, viewComponentResult, component); return(viewComponentResult); } catch (TargetInvocationException ex) { // Preserve callstack of any user-thrown exceptions. var exceptionInfo = ExceptionDispatchInfo.Capture(ex.InnerException); exceptionInfo.Throw(); return(null); // Unreachable } } }
public void Invoke(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var method = ViewComponentMethodSelector.FindSyncMethod( context.ViewComponentDescriptor.Type.GetTypeInfo(), context.Arguments); if (method == null) { throw new InvalidOperationException( Resources.FormatViewComponent_CannotFindMethod(ViewComponentMethodSelector.SyncMethodName)); } var result = InvokeSyncCore(method, context); result.Execute(context); }
/// <inheritdoc /> public virtual void Activate(object viewComponent, ViewComponentContext context) { if (viewComponent == null) { throw new ArgumentNullException(nameof(viewComponent)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var propertiesToActivate = _injectActions.GetOrAdd( viewComponent.GetType(), _getPropertiesToActivate); for (var i = 0; i < propertiesToActivate.Length; i++) { var activateInfo = propertiesToActivate[i]; activateInfo.Activate(viewComponent, context); } }
private async Task <IViewComponentResult> InvokeAsyncCore(ViewComponentContext context) { var component = CreateComponent(context); using (_logger.ViewComponentScope(context)) { var method = context.ViewComponentDescriptor.MethodInfo; var arguments = ControllerActionExecutor.PrepareArguments(context.Arguments, method.GetParameters()); _diagnosticSource.BeforeViewComponent(context, component); _logger.ViewComponentExecuting(context, arguments); var startTimestamp = _logger.IsEnabled(LogLevel.Debug) ? Stopwatch.GetTimestamp() : 0; var result = await ControllerActionExecutor.ExecuteAsync(method, component, arguments); var viewComponentResult = CoerceToViewComponentResult(result); _logger.ViewComponentExecuted(context, startTimestamp, viewComponentResult); _diagnosticSource.AfterViewComponent(context, viewComponentResult, component); return(viewComponentResult); } }
/// <inheritdoc /> public virtual void Activate(object viewComponent, ViewComponentContext context) { if (viewComponent == null) { throw new ArgumentNullException(nameof(viewComponent)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var propertiesToActivate = _injectActions.GetOrAdd( viewComponent.GetType(), _getPropertiesToActivate); for (var i = 0; i < propertiesToActivate.Length; i++) { var activateInfo = propertiesToActivate[i]; activateInfo.Activate(viewComponent, context); } }
public async Task InvokeAsync(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } IViewComponentResult result; var asyncMethod = ViewComponentMethodSelector.FindAsyncMethod( context.ViewComponentDescriptor.Type.GetTypeInfo(), context.Arguments); if (asyncMethod == null) { // We support falling back to synchronous if there is no InvokeAsync method, in this case we'll still // execute the IViewResult asynchronously. var syncMethod = ViewComponentMethodSelector.FindSyncMethod( context.ViewComponentDescriptor.Type.GetTypeInfo(), context.Arguments); if (syncMethod == null) { throw new InvalidOperationException( Resources.FormatViewComponent_CannotFindMethod_WithFallback( ViewComponentMethodSelector.SyncMethodName, ViewComponentMethodSelector.AsyncMethodName)); } else { result = InvokeSyncCore(syncMethod, context); } } else { result = await InvokeAsyncCore(asyncMethod, context); } await result.ExecuteAsync(context); }
public async Task InvokeAsync(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } IViewComponentResult result; var asyncMethod = ViewComponentMethodSelector.FindAsyncMethod( context.ViewComponentDescriptor.Type.GetTypeInfo(), context.Arguments); if (asyncMethod == null) { // We support falling back to synchronous if there is no InvokeAsync method, in this case we'll still // execute the IViewResult asynchronously. var syncMethod = ViewComponentMethodSelector.FindSyncMethod( context.ViewComponentDescriptor.Type.GetTypeInfo(), context.Arguments); if (syncMethod == null) { throw new InvalidOperationException( Resources.FormatViewComponent_CannotFindMethod_WithFallback( ViewComponentMethodSelector.SyncMethodName, ViewComponentMethodSelector.AsyncMethodName)); } else { result = InvokeSyncCore(syncMethod, context); } } else { result = await InvokeAsyncCore(asyncMethod, context); } await result.ExecuteAsync(context); }
private static IViewEngine ResolveViewEngine(ViewComponentContext context) { return context.ViewContext.HttpContext.RequestServices.GetRequiredService<ICompositeViewEngine>(); }
public static void ViewComponentExecuting(this ILogger logger, ViewComponentContext context) { _viewComponentExecuting(logger, context.ViewComponentDescriptor.DisplayName, null); }
/// <summary> /// Locates and renders a view specified by <see cref="ViewName"/>. If <see cref="ViewName"/> is <c>null</c>, /// then the view name searched for is<c>"Default"</c>. /// </summary> /// <param name="context">The <see cref="ViewComponentContext"/> for the current component execution.</param> /// <returns>A <see cref="Task"/> which will complete when view rendering is completed.</returns> public async Task ExecuteAsync(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var viewEngine = ViewEngine ?? ResolveViewEngine(context); var viewData = ViewData ?? context.ViewData; var isNullOrEmptyViewName = string.IsNullOrEmpty(ViewName); string qualifiedViewName; if (!isNullOrEmptyViewName && (ViewName[0] == '~' || ViewName[0] == '/')) { // View name that was passed in is already a rooted path, the view engine will handle this. qualifiedViewName = ViewName; } else { // This will produce a string like: // // Components/Cart/Default // // The view engine will combine this with other path info to search paths like: // // Views/Shared/Components/Cart/Default.cshtml // Views/Home/Components/Cart/Default.cshtml // Areas/Blog/Views/Shared/Components/Cart/Default.cshtml // // This supports a controller or area providing an override for component views. var viewName = isNullOrEmptyViewName ? DefaultViewName : ViewName; qualifiedViewName = string.Format( CultureInfo.InvariantCulture, ViewPathFormat, context.ViewComponentDescriptor.ShortName, viewName); } var view = FindView(context.ViewContext, viewEngine, qualifiedViewName); var childViewContext = new ViewContext( context.ViewContext, view, ViewData ?? context.ViewData, context.Writer); using (view as IDisposable) { if (_diagnosticSource == null) { _diagnosticSource = context.ViewContext.HttpContext.RequestServices.GetRequiredService<DiagnosticSource>(); } _diagnosticSource.ViewComponentBeforeViewExecute(context, view); await view.RenderAsync(childViewContext); _diagnosticSource.ViewComponentAfterViewExecute(context, view); } }
/// <summary> /// Encodes and writes the <see cref="Content"/>. /// </summary> /// <param name="context">The <see cref="ViewComponentContext"/>.</param> /// <returns>A completed <see cref="Task"/>.</returns> public Task ExecuteAsync(ViewComponentContext context) { Execute(context); return TaskCache.CompletedTask; }
private static IViewEngine ResolveViewEngine(ViewComponentContext context) { return(context.ViewContext.HttpContext.RequestServices.GetRequiredService <ICompositeViewEngine>()); }
private void InvokeCore( TextWriter writer, ViewComponentDescriptor descriptor, object[] arguments) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (descriptor == null) { throw new ArgumentNullException(nameof(descriptor)); } var context = new ViewComponentContext(descriptor, arguments, _viewContext, writer); var invoker = _invokerFactory.CreateInstance(context); if (invoker == null) { throw new InvalidOperationException( Resources.FormatViewComponent_IViewComponentFactory_ReturnedNull(descriptor.Type.FullName)); } invoker.Invoke(context); }
/// <summary> /// Locates and renders a view specified by <see cref="ViewName"/>. If <see cref="ViewName"/> is <c>null</c>, /// then the view name searched for is<c>"Default"</c>. /// </summary> /// <param name="context">The <see cref="ViewComponentContext"/> for the current component execution.</param> /// <returns>A <see cref="Task"/> which will complete when view rendering is completed.</returns> public async Task ExecuteAsync(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var viewEngine = ViewEngine ?? ResolveViewEngine(context); var viewContext = context.ViewContext; var viewData = ViewData ?? context.ViewData; var isNullOrEmptyViewName = string.IsNullOrEmpty(ViewName); ViewEngineResult result = null; IEnumerable <string> originalLocations = null; if (!isNullOrEmptyViewName) { // If view name was passed in is already a path, the view engine will handle this. result = viewEngine.GetView(viewContext.ExecutingFilePath, ViewName, isMainPage: false); originalLocations = result.SearchedLocations; } if (result == null || !result.Success) { // This will produce a string like: // // Components/Cart/Default // // The view engine will combine this with other path info to search paths like: // // Views/Shared/Components/Cart/Default.cshtml // Views/Home/Components/Cart/Default.cshtml // Areas/Blog/Views/Shared/Components/Cart/Default.cshtml // // This supports a controller or area providing an override for component views. var viewName = isNullOrEmptyViewName ? DefaultViewName : ViewName; var qualifiedViewName = string.Format( CultureInfo.InvariantCulture, ViewPathFormat, context.ViewComponentDescriptor.ShortName, viewName); result = viewEngine.FindView(viewContext, qualifiedViewName, isMainPage: false); } var view = result.EnsureSuccessful(originalLocations).View; using (view as IDisposable) { if (_diagnosticSource == null) { _diagnosticSource = viewContext.HttpContext.RequestServices.GetRequiredService <DiagnosticSource>(); } _diagnosticSource.ViewComponentBeforeViewExecute(context, view); var childViewContext = new ViewContext( viewContext, view, ViewData ?? context.ViewData, context.Writer); await view.RenderAsync(childViewContext); _diagnosticSource.ViewComponentAfterViewExecute(context, view); } }
public IViewComponentResult InvokeSyncCore(MethodInfo method, ViewComponentContext context) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var component = CreateComponent(context); object result = null; using (_logger.ViewComponentScope(context)) { _diagnosticSource.BeforeViewComponent(context, component); _logger.ViewComponentExecuting(context); try { var startTime = Environment.TickCount; result = method.Invoke(component, context.Arguments); var viewComponentResult = CoerceToViewComponentResult(result); _logger.ViewComponentExecuted(context, startTime, viewComponentResult); _diagnosticSource.AfterViewComponent(context, viewComponentResult, component); return viewComponentResult; } catch (TargetInvocationException ex) { // Preserve callstack of any user-thrown exceptions. var exceptionInfo = ExceptionDispatchInfo.Capture(ex.InnerException); exceptionInfo.Throw(); return null; // Unreachable } } }
protected virtual object CreateComponent(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var services = context.ViewContext.HttpContext.RequestServices; var component = _typeActivatorCache.CreateInstance<object>( services, context.ViewComponentDescriptor.Type); _viewComponentActivator.Activate(component, context); return component; }
/// <summary> /// Writes the <see cref="EncodedContent"/>. /// </summary> /// <param name="context">The <see cref="ViewComponentContext"/>.</param> /// <returns>A completed <see cref="Task"/>.</returns> public Task ExecuteAsync(ViewComponentContext context) { Execute(context); return(TaskCache.CompletedTask); }
private async Task<IHtmlContent> InvokeCoreAsync( ViewComponentDescriptor descriptor, object arguments) { var viewBuffer = new ViewBuffer(_viewBufferScope, descriptor.FullName); using (var writer = new HtmlContentWrapperTextWriter(viewBuffer, _viewContext.Writer.Encoding)) { var context = new ViewComponentContext( descriptor, PropertyHelper.ObjectToDictionary(arguments), _htmlEncoder, _viewContext, writer); var invoker = _invokerFactory.CreateInstance(context); if (invoker == null) { throw new InvalidOperationException( Resources.FormatViewComponent_IViewComponentFactory_ReturnedNull(descriptor.FullName)); } await invoker.InvokeAsync(context); return writer.ContentBuilder; } }
public static IDisposable ViewComponentScope(this ILogger logger, ViewComponentContext context) { return logger.BeginScopeImpl(new ViewComponentLogScope(context.ViewComponentDescriptor)); }
private async Task<IViewComponentResult> InvokeAsyncCore( MethodInfo method, ViewComponentContext context) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var component = CreateComponent(context); using (_logger.ViewComponentScope(context)) { _diagnosticSource.BeforeViewComponent(context, component); _logger.ViewComponentExecuting(context); var startTime = Environment.TickCount; var result = await ControllerActionExecutor.ExecuteAsync(method, component, context.Arguments); var viewComponentResult = CoerceToViewComponentResult(result); _logger.ViewComponentExecuted(context, startTime, viewComponentResult); _diagnosticSource.AfterViewComponent(context, viewComponentResult, component); return viewComponentResult; } }
/// <inheritdoc /> // We don't currently make use of the descriptor or the arguments here (they are available on the context). // We might do this some day to cache which method we select, so resist the urge to 'clean' this without // considering that possibility. public IViewComponentInvoker CreateInstance([NotNull] ViewComponentContext context) { return(new DefaultViewComponentInvoker( _typeActivatorCache, _viewComponentActivator)); }
/// <summary> /// Locates and renders a view specified by <see cref="ViewName"/>. If <see cref="ViewName"/> is <c>null</c>, /// then the view name searched for is<c>"Default"</c>. /// </summary> /// <param name="context">The <see cref="ViewComponentContext"/> for the current component execution.</param> /// <returns>A <see cref="Task"/> which will complete when view rendering is completed.</returns> public async Task ExecuteAsync(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var viewEngine = ViewEngine ?? ResolveViewEngine(context); var viewData = ViewData ?? context.ViewData; var isNullOrEmptyViewName = string.IsNullOrEmpty(ViewName); string qualifiedViewName; if (!isNullOrEmptyViewName && (ViewName[0] == '~' || ViewName[0] == '/')) { // View name that was passed in is already a rooted path, the view engine will handle this. qualifiedViewName = ViewName; } else { // This will produce a string like: // // Components/Cart/Default // // The view engine will combine this with other path info to search paths like: // // Views/Shared/Components/Cart/Default.cshtml // Views/Home/Components/Cart/Default.cshtml // Areas/Blog/Views/Shared/Components/Cart/Default.cshtml // // This supports a controller or area providing an override for component views. var viewName = isNullOrEmptyViewName ? DefaultViewName : ViewName; qualifiedViewName = string.Format( CultureInfo.InvariantCulture, ViewPathFormat, context.ViewComponentDescriptor.ShortName, viewName); } var view = FindView(context.ViewContext, viewEngine, qualifiedViewName); var childViewContext = new ViewContext( context.ViewContext, view, ViewData ?? context.ViewData, context.Writer); using (view as IDisposable) { if (_diagnosticSource == null) { _diagnosticSource = context.ViewContext.HttpContext.RequestServices.GetRequiredService <DiagnosticSource>(); } _diagnosticSource.ViewComponentBeforeViewExecute(context, view); await view.RenderAsync(childViewContext); _diagnosticSource.ViewComponentAfterViewExecute(context, view); } }
protected override object CreateComponent(ViewComponentContext context) { var component = this.container.GetInstance(context.ViewComponentDescriptor.Type); this.viewComponentActivator.Activate(component, context); return component; }
private async Task InvokeCoreAsync( [NotNull] TextWriter writer, [NotNull] ViewComponentDescriptor descriptor, object[] arguments) { var invoker = _invokerFactory.CreateInstance(descriptor, arguments); if (invoker == null) { throw new InvalidOperationException( Resources.FormatViewComponent_IViewComponentFactory_ReturnedNull(descriptor.Type.FullName)); } var context = new ViewComponentContext(descriptor, arguments, _viewContext, writer); await invoker.InvokeAsync(context); }
/// <summary> /// Locates and renders a view specified by <see cref="ViewName"/>. If <see cref="ViewName"/> is <c>null</c>, /// then the view name searched for is<c>"Default"</c>. /// </summary> /// <param name="context">The <see cref="ViewComponentContext"/> for the current component execution.</param> /// <returns>A <see cref="Task"/> which will complete when view rendering is completed.</returns> public async Task ExecuteAsync(ViewComponentContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var viewEngine = ViewEngine ?? ResolveViewEngine(context); var viewContext = context.ViewContext; var viewData = ViewData ?? context.ViewData; var isNullOrEmptyViewName = string.IsNullOrEmpty(ViewName); ViewEngineResult result = null; IEnumerable<string> originalLocations = null; if (!isNullOrEmptyViewName) { // If view name was passed in is already a path, the view engine will handle this. result = viewEngine.GetView(viewContext.ExecutingFilePath, ViewName, isMainPage: false); originalLocations = result.SearchedLocations; } if (result == null || !result.Success) { // This will produce a string like: // // Components/Cart/Default // // The view engine will combine this with other path info to search paths like: // // Views/Shared/Components/Cart/Default.cshtml // Views/Home/Components/Cart/Default.cshtml // Areas/Blog/Views/Shared/Components/Cart/Default.cshtml // // This supports a controller or area providing an override for component views. var viewName = isNullOrEmptyViewName ? DefaultViewName : ViewName; var qualifiedViewName = string.Format( CultureInfo.InvariantCulture, ViewPathFormat, context.ViewComponentDescriptor.ShortName, viewName); result = viewEngine.FindView(viewContext, qualifiedViewName, isMainPage: false); } var view = result.EnsureSuccessful(originalLocations).View; using (view as IDisposable) { if (_diagnosticSource == null) { _diagnosticSource = viewContext.HttpContext.RequestServices.GetRequiredService<DiagnosticSource>(); } _diagnosticSource.ViewComponentBeforeViewExecute(context, view); var childViewContext = new ViewContext( viewContext, view, ViewData ?? context.ViewData, context.Writer); await view.RenderAsync(childViewContext); _diagnosticSource.ViewComponentAfterViewExecute(context, view); } }