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;
        }
예제 #2
0
        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);
        }
예제 #4
0
        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
        }
예제 #5
0
        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;
        }
예제 #9
0
        /// <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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        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());
        }
예제 #13
0
        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);
        }
예제 #14
0
 public ViewComponentContext()
 {
     ViewComponentDescriptor = new ViewComponentDescriptor();
     ViewContext             = new ViewContext();
 }
예제 #15
0
        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);
        }
예제 #16
0
        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);
        }
예제 #17
0
 /// <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();
 }
예제 #18
0
        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);
        }
예제 #19
0
        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);
        }
예제 #20
0
        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);
        }
예제 #21
0
        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);
        }
예제 #22
0
        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;
        }
예제 #23
0
        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);
        }