private static ViewComponentContext GetViewComponentContext(IView view, Stream stream) { var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor()); var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider()); var viewContext = new ViewContext( actionContext, view, viewData, new TempDataDictionary(actionContext.HttpContext, new SessionStateTempDataProvider()), TextWriter.Null, new HtmlHelperOptions()); var writer = new StreamWriter(stream) { AutoFlush = true }; var viewComponentDescriptor = new ViewComponentDescriptor() { TypeInfo = typeof(object).GetTypeInfo(), }; var viewComponentContext = new ViewComponentContext( viewComponentDescriptor, new Dictionary<string, object>(), new HtmlTestEncoder(), viewContext, writer); return viewComponentContext; }
public void ViewDataModelSetter_DoesNotThrow_IfValueIncompatibleWithSourceDeclaredType( object model, Type expectedType) { // Arrange var httpContext = new DefaultHttpContext(); var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var viewData = new ViewDataDictionary <int>(new EmptyModelMetadataProvider()); var viewContext = new ViewContext( actionContext, NullView.Instance, viewData, new TempDataDictionary(httpContext, new SessionStateTempDataProvider()), TextWriter.Null, new HtmlHelperOptions()); var viewComponentDescriptor = new ViewComponentDescriptor(); var viewComponentContext = new ViewComponentContext( viewComponentDescriptor, new Dictionary <string, object>(), new HtmlTestEncoder(), viewContext, TextWriter.Null); // Act (does not throw) // Non-ints can be assigned despite type restrictions in the source ViewDataDictionary. viewComponentContext.ViewData.Model = model; // Assert Assert.Equal(expectedType, viewComponentContext.ViewData.ModelMetadata.ModelType); }
public void Create_ThrowsIfControllerCannotBeActivated(Type type) { // Arrange var actionDescriptor = new ViewComponentDescriptor { TypeInfo = type.GetTypeInfo() }; var context = new ViewComponentContext { ViewComponentDescriptor = actionDescriptor, ViewContext = new ViewContext { HttpContext = new DefaultHttpContext() { RequestServices = Mock.Of <IServiceProvider>() }, } }; var activator = new DefaultViewComponentActivator(new TypeActivatorCache()); // Act and Assert var exception = Assert.Throws <InvalidOperationException>(() => activator.Create(context)); Assert.Equal( $"The type '{type.FullName}' cannot be activated by '{typeof(DefaultViewComponentActivator).FullName}' " + "because it is either a value type, an interface, an abstract class or an open generic type.", exception.Message); }
public async Task ExecuteAsync_ViewComponentResult_AllowsNullViewDataAndTempData() { // Arrange var descriptor = new ViewComponentDescriptor() { FullName = "Full.Name.Text", ShortName = "Text", TypeInfo = typeof(TextViewComponent).GetTypeInfo(), MethodInfo = typeof(TextViewComponent).GetMethod(nameof(TextViewComponent.Invoke)), }; var actionContext = CreateActionContext(descriptor); var viewComponentResult = new ViewComponentResult { Arguments = new { name = "World!" }, ViewData = null, TempData = null, ViewComponentName = "Text" }; // Act await viewComponentResult.ExecuteResultAsync(actionContext); // No assert, just confirm it didn't throw }
private async Task <IHtmlContent> InvokeCoreAsync( ViewComponentDescriptor descriptor, object arguments) { var viewBuffer = new ViewBuffer(_viewBufferScope, descriptor.FullName, ViewBuffer.ViewComponentPageSize); using (var writer = new ViewBufferTextWriter(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(viewBuffer); } }
internal IDictionary <string, object?> GetArgumentDictionary(ViewComponentDescriptor descriptor, object?arguments) { if (arguments != null) { if (descriptor.Parameters.Count == 1 && descriptor.Parameters[0].ParameterType.IsAssignableFrom(arguments.GetType())) { return(new Dictionary <string, object?>(capacity: 1, comparer: StringComparer.OrdinalIgnoreCase) { { descriptor.Parameters[0].Name !, arguments } });
private static ViewComponentDescriptor CreateDescriptor(TypeInfo typeInfo) { var candidate = new ViewComponentDescriptor { FullName = ViewComponentConventions.GetComponentFullName(typeInfo), ShortName = ViewComponentConventions.GetComponentName(typeInfo), TypeInfo = typeInfo, MethodInfo = FindMethod(typeInfo.AsType()) }; return(candidate); }
private static ViewComponentDescriptor CreateDescriptor(TypeInfo typeInfo) { var candidate = new ViewComponentDescriptor { FullName = ViewComponentConventions.GetComponentFullName(typeInfo), ShortName = ViewComponentConventions.GetComponentName(typeInfo), TypeInfo = typeInfo, MethodInfo = FindMethod(typeInfo.AsType()) }; return candidate; }
/// <summary> /// Creates a new <see cref="ViewComponentContext"/>. /// </summary> /// <param name="viewComponentDescriptor"> /// The <see cref="ViewComponentContext"/> for the view component being invoked. /// </param> /// <param name="arguments">The view component arguments.</param> /// <param name="htmlEncoder">The <see cref="HtmlEncoder"/> to use.</param> /// <param name="viewContext">The <see cref="ViewContext"/>.</param> /// <param name="writer">The <see cref="TextWriter"/> for writing output.</param> public ViewComponentContext( ViewComponentDescriptor viewComponentDescriptor, IDictionary<string, object> arguments, HtmlEncoder htmlEncoder, ViewContext viewContext, TextWriter writer) { if (viewComponentDescriptor == null) { throw new ArgumentNullException(nameof(viewComponentDescriptor)); } if (arguments == null) { throw new ArgumentNullException(nameof(arguments)); } if (htmlEncoder == null) { throw new ArgumentNullException(nameof(htmlEncoder)); } if (viewContext == null) { throw new ArgumentNullException(nameof(viewContext)); } if (writer == null) { throw new ArgumentNullException(nameof(writer)); } ViewComponentDescriptor = viewComponentDescriptor; Arguments = arguments; HtmlEncoder = htmlEncoder; // We want to create a defensive copy of the VDD here so that changes done in the VC // aren't visible in the calling view. ViewContext = new ViewContext( viewContext, viewContext.View, new ViewDataDictionary<object>(viewContext.ViewData), writer); }
public ViewComponentContext( ViewComponentDescriptor viewComponentDescriptor, IDictionary <string, object?> arguments, HtmlEncoder htmlEncoder, ViewContext viewContext, TextWriter writer) { if (viewComponentDescriptor == null) { throw new ArgumentNullException(nameof(viewComponentDescriptor)); } if (arguments == null) { throw new ArgumentNullException(nameof(arguments)); } if (htmlEncoder == null) { throw new ArgumentNullException(nameof(htmlEncoder)); } if (viewContext == null) { throw new ArgumentNullException(nameof(viewContext)); } if (writer == null) { throw new ArgumentNullException(nameof(writer)); } ViewComponentDescriptor = viewComponentDescriptor; Arguments = arguments; HtmlEncoder = htmlEncoder; // We want to create a defensive copy of the VDD here so that changes done in the VC // aren't visible in the calling view. ViewContext = new ViewContext( viewContext, viewContext.View, new ViewDataDictionary <object>(viewContext.ViewData), writer); }
public void Constructor_PerformsDefensiveCopies() { // Arrange var httpContext = new DefaultHttpContext(); var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider()); var tempData = new TempDataDictionary(httpContext, new SessionStateTempDataProvider()); var viewContext = new ViewContext( actionContext, NullView.Instance, viewData, tempData, TextWriter.Null, new HtmlHelperOptions()); var viewComponentDescriptor = new ViewComponentDescriptor(); // Act var viewComponentContext = new ViewComponentContext( viewComponentDescriptor, new Dictionary <string, object>(), new HtmlTestEncoder(), viewContext, TextWriter.Null); // Assert // New ViewContext but initial View and TextWriter copied over. Assert.NotSame(viewContext, viewComponentContext.ViewContext); Assert.Same(tempData, viewComponentContext.TempData); Assert.Same(viewContext.View, viewComponentContext.ViewContext.View); Assert.Same(viewContext.Writer, viewComponentContext.ViewContext.Writer); // Double-check the convenience properties. Assert.Same(viewComponentContext.ViewContext.ViewData, viewComponentContext.ViewData); Assert.Same(viewComponentContext.ViewContext.TempData, viewComponentContext.TempData); Assert.Same(viewComponentContext.ViewContext.Writer, viewComponentContext.Writer); // New VDD instance but initial ModelMetadata copied over. Assert.NotSame(viewData, viewComponentContext.ViewData); Assert.Same(viewData.ModelMetadata, viewComponentContext.ViewData.ModelMetadata); }
public async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { var result = await InvokeAsync(Count); var writer = new StringWriter(); var viewComponentDescriptor = new ViewComponentDescriptor() { TypeInfo = typeof(TagCloudViewComponentTagHelper).GetTypeInfo(), ShortName = "TagCloudViewComponentTagHelper", FullName = "TagCloudViewComponentTagHelper", }; await result.ExecuteAsync(new ViewComponentContext( viewComponentDescriptor, new Dictionary<string, object>(), _htmlEncoder, ViewContext, writer)); output.TagName = null; output.Content.AppendHtml(writer.ToString()); }
public void Constructor_PerformsDefensiveCopies() { // Arrange var httpContext = new DefaultHttpContext(); var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider()); var viewContext = new ViewContext( actionContext, NullView.Instance, viewData, new TempDataDictionary(httpContext, new SessionStateTempDataProvider()), TextWriter.Null, new HtmlHelperOptions()); var viewComponentDescriptor = new ViewComponentDescriptor(); // Act var viewComponentContext = new ViewComponentContext( viewComponentDescriptor, new Dictionary<string, object>(), new HtmlTestEncoder(), viewContext, TextWriter.Null); // Assert // New ViewContext but initial View and TextWriter copied over. Assert.NotSame(viewContext, viewComponentContext.ViewContext); Assert.Same(viewContext.View, viewComponentContext.ViewContext.View); Assert.Same(viewContext.Writer, viewComponentContext.ViewContext.Writer); // Double-check the convenience properties. Assert.Same(viewComponentContext.ViewContext.ViewData, viewComponentContext.ViewData); Assert.Same(viewComponentContext.ViewContext.Writer, viewComponentContext.Writer); // New VDD instance but initial ModelMetadata copied over. Assert.NotSame(viewData, viewComponentContext.ViewData); Assert.Same(viewData.ModelMetadata, viewComponentContext.ViewData.ModelMetadata); }
public ViewComponentContext() { ViewComponentDescriptor = new ViewComponentDescriptor(); ViewContext = new ViewContext(); }
public async Task ViewComponentResult_SetsContentTypeHeader_OverrideResponseContentType() { // Arrange var descriptor = new ViewComponentDescriptor() { FullName = "Full.Name.Text", ShortName = "Text", TypeInfo = typeof(TextViewComponent).GetTypeInfo(), MethodInfo = typeof(TextViewComponent).GetMethod(nameof(TextViewComponent.Invoke)), }; var actionContext = CreateActionContext(descriptor); var expectedContentType = "text/html; charset=utf-8"; actionContext.HttpContext.Response.ContentType = "application/x-will-be-overridden"; var viewComponentResult = new ViewComponentResult() { Arguments = new { name = "World!" }, ViewComponentName = "Text", ContentType = new MediaTypeHeaderValue("text/html") { Encoding = Encoding.UTF8 }.ToString(), TempData = _tempDataDictionary, }; // Act await viewComponentResult.ExecuteResultAsync(actionContext); // Assert Assert.Equal(expectedContentType, actionContext.HttpContext.Response.ContentType); }
public async Task ViewComponentResult_NoContentTypeSet_PreservesResponseContentType( string responseContentType, string expectedContentType) { // Arrange var descriptor = new ViewComponentDescriptor() { FullName = "Full.Name.Text", ShortName = "Text", TypeInfo = typeof(TextViewComponent).GetTypeInfo(), MethodInfo = typeof(TextViewComponent).GetMethod(nameof(TextViewComponent.Invoke)), }; var actionContext = CreateActionContext(descriptor); actionContext.HttpContext.Response.ContentType = expectedContentType; var viewComponentResult = new ViewComponentResult() { Arguments = new { name = "World!" }, ViewComponentName = "Text", TempData = _tempDataDictionary, }; // Act await viewComponentResult.ExecuteResultAsync(actionContext); // Assert Assert.Equal(expectedContentType, actionContext.HttpContext.Response.ContentType); }
/// <summary> /// Creates a new <see cref="ViewComponentContext"/>. /// </summary> /// <remarks> /// The default constructor is provided for unit test purposes only. /// </remarks> public ViewComponentContext() { ViewComponentDescriptor = new ViewComponentDescriptor(); ViewContext = new ViewContext(); }
public async Task ViewComponentResult_SetsContentTypeHeader( string contentType, string expectedContentType) { // Arrange var descriptor = new ViewComponentDescriptor() { FullName = "Full.Name.Text", ShortName = "Text", TypeInfo = typeof(TextViewComponent).GetTypeInfo(), MethodInfo = typeof(TextViewComponent).GetMethod(nameof(TextViewComponent.Invoke)), }; var actionContext = CreateActionContext(descriptor); var contentTypeBeforeViewResultExecution = contentType?.ToString(); var viewComponentResult = new ViewComponentResult() { Arguments = new { name = "World!" }, ViewComponentName = "Text", ContentType = contentType, TempData = _tempDataDictionary, }; // Act await viewComponentResult.ExecuteResultAsync(actionContext); // Assert var resultContentType = actionContext.HttpContext.Response.ContentType; MediaTypeAssert.Equal(expectedContentType, resultContentType); // Check if the original instance provided by the user has not changed. // Since we do not have access to the new instance created within the view executor, // check if at least the content is the same. var contentTypeAfterViewResultExecution = contentType?.ToString(); MediaTypeAssert.Equal(contentTypeBeforeViewResultExecution, contentTypeAfterViewResultExecution); }
public async Task ExecuteResultAsync_SetsStatusCode() { // Arrange var descriptor = new ViewComponentDescriptor() { FullName = "Full.Name.Text", ShortName = "Text", TypeInfo = typeof(TextViewComponent).GetTypeInfo(), MethodInfo = typeof(TextViewComponent).GetMethod(nameof(TextViewComponent.Invoke)) }; var actionContext = CreateActionContext(descriptor); var viewComponentResult = new ViewComponentResult() { Arguments = new { name = "World!" }, ViewComponentType = typeof(TextViewComponent), StatusCode = 404, TempData = _tempDataDictionary, }; // Act await viewComponentResult.ExecuteResultAsync(actionContext); // Assert Assert.Equal(404, actionContext.HttpContext.Response.StatusCode); }
public async Task ExecuteResultAsync_ExecutesViewComponent_ByType() { // Arrange var descriptor = new ViewComponentDescriptor() { FullName = "Full.Name.Text", ShortName = "Text", TypeInfo = typeof(TextViewComponent).GetTypeInfo(), MethodInfo = typeof(TextViewComponent).GetMethod(nameof(TextViewComponent.Invoke)), }; var actionContext = CreateActionContext(descriptor); var viewComponentResult = new ViewComponentResult() { Arguments = new { name = "World!" }, ViewComponentType = typeof(TextViewComponent), TempData = _tempDataDictionary, }; // Act await viewComponentResult.ExecuteResultAsync(actionContext); // Assert var body = ReadBody(actionContext.HttpContext.Response); Assert.Equal("Hello, World!", body); }
public async Task ExecuteResultAsync_ExecutesViewComponent_AndWritesDiagnosticSource() { // Arrange var descriptor = new ViewComponentDescriptor() { FullName = "Full.Name.Text", ShortName = "Text", TypeInfo = typeof(TextViewComponent).GetTypeInfo(), MethodInfo = typeof(TextViewComponent).GetMethod(nameof(TextViewComponent.Invoke)), }; var adapter = new TestDiagnosticListener(); var actionContext = CreateActionContext(adapter, descriptor); var viewComponentResult = new ViewComponentResult() { Arguments = new { name = "World!" }, ViewComponentName = "Text", TempData = _tempDataDictionary, }; // Act await viewComponentResult.ExecuteResultAsync(actionContext); // Assert var body = ReadBody(actionContext.HttpContext.Response); Assert.Equal("Hello, World!", body); Assert.NotNull(adapter.BeforeViewComponent?.ActionDescriptor); Assert.NotNull(adapter.BeforeViewComponent?.ViewComponentContext); Assert.NotNull(adapter.BeforeViewComponent?.ViewComponent); Assert.NotNull(adapter.AfterViewComponent?.ActionDescriptor); Assert.NotNull(adapter.AfterViewComponent?.ViewComponentContext); Assert.NotNull(adapter.AfterViewComponent?.ViewComponentResult); Assert.NotNull(adapter.AfterViewComponent?.ViewComponent); }
private static ViewComponentContext GetViewComponentContext( IView view, ViewDataDictionary viewData, object diagnosticListener = null) { var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore"); if (diagnosticListener == null) { diagnosticListener = new TestDiagnosticListener(); } diagnosticSource.SubscribeWithAdapter(diagnosticListener); var serviceProvider = new Mock<IServiceProvider>(); serviceProvider.Setup(s => s.GetService(typeof(DiagnosticSource))).Returns(diagnosticSource); var httpContext = new DefaultHttpContext(); httpContext.RequestServices = serviceProvider.Object; var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var viewContext = new ViewContext( actionContext, view, viewData, new TempDataDictionary(httpContext, new SessionStateTempDataProvider()), TextWriter.Null, new HtmlHelperOptions()); var viewComponentDescriptor = new ViewComponentDescriptor() { ShortName = "Invoke", TypeInfo = typeof(object).GetTypeInfo(), MethodInfo = typeof(object).GetTypeInfo().DeclaredMethods.First() }; var viewComponentContext = new ViewComponentContext( viewComponentDescriptor, new Dictionary<string, object>(), new HtmlTestEncoder(), viewContext, TextWriter.Null); return viewComponentContext; }
public void ViewDataModelSetter_DoesNotThrow_IfValueIncompatibleWithSourceDeclaredType( object model, Type expectedType) { // Arrange var httpContext = new DefaultHttpContext(); var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var viewData = new ViewDataDictionary<int>(new EmptyModelMetadataProvider()); var viewContext = new ViewContext( actionContext, NullView.Instance, viewData, new TempDataDictionary(httpContext, new SessionStateTempDataProvider()), TextWriter.Null, new HtmlHelperOptions()); var viewComponentDescriptor = new ViewComponentDescriptor(); var viewComponentContext = new ViewComponentContext( viewComponentDescriptor, new Dictionary<string, object>(), new HtmlTestEncoder(), viewContext, TextWriter.Null); // Act (does not throw) // Non-ints can be assigned despite type restrictions in the source ViewDataDictionary. viewComponentContext.ViewData.Model = model; // Assert Assert.Equal(expectedType, viewComponentContext.ViewData.ModelMetadata.ModelType); }