diff --git a/Mvc.sln b/Mvc.sln
index 9bd980f531..e6a4c9cd93 100644
--- a/Mvc.sln
+++ b/Mvc.sln
@@ -98,6 +98,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "WebApiCompatShimWebSite", "
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.WebApiCompatShimTest", "test\Microsoft.AspNet.Mvc.WebApiCompatShimTest\Microsoft.AspNet.Mvc.WebApiCompatShimTest.kproj", "{5DE8E4D9-AACD-4B5F-819F-F091383FB996}"
EndProject
+Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ViewComponentWebSite", "test\WebSites\ViewComponentWebSite\ViewComponentWebSite.kproj", "{24B59501-5F37-4129-96E6-F02EC34C7E2C}"
+EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TagHelperSample.Web", "samples\TagHelperSample.Web\TagHelperSample.Web.kproj", "{2223120F-D675-40DA-8CD8-11DC14A0B2C7}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.TagHelpers", "src\Microsoft.AspNet.Mvc.TagHelpers\Microsoft.AspNet.Mvc.TagHelpers.kproj", "{B2347320-308E-4D2B-AEC8-005DFA68B0C9}"
@@ -524,6 +526,16 @@ Global
{5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{5DE8E4D9-AACD-4B5F-819F-F091383FB996}.Release|x86.ActiveCfg = Release|Any CPU
+ {24B59501-5F37-4129-96E6-F02EC34C7E2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {24B59501-5F37-4129-96E6-F02EC34C7E2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {24B59501-5F37-4129-96E6-F02EC34C7E2C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {24B59501-5F37-4129-96E6-F02EC34C7E2C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {24B59501-5F37-4129-96E6-F02EC34C7E2C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {24B59501-5F37-4129-96E6-F02EC34C7E2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {24B59501-5F37-4129-96E6-F02EC34C7E2C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {24B59501-5F37-4129-96E6-F02EC34C7E2C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {24B59501-5F37-4129-96E6-F02EC34C7E2C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {24B59501-5F37-4129-96E6-F02EC34C7E2C}.Release|x86.ActiveCfg = Release|Any CPU
{2223120F-D675-40DA-8CD8-11DC14A0B2C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2223120F-D675-40DA-8CD8-11DC14A0B2C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2223120F-D675-40DA-8CD8-11DC14A0B2C7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -601,6 +613,7 @@ Global
{23D30B8C-04B1-4577-A604-ED27EA1E4A0E} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{B2B7BC91-688E-4C1E-A71F-CE948D958DDF} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{5DE8E4D9-AACD-4B5F-819F-F091383FB996} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
+ {24B59501-5F37-4129-96E6-F02EC34C7E2C} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{2223120F-D675-40DA-8CD8-11DC14A0B2C7} = {DAAE4C74-D06F-4874-A166-33305D2643CE}
{B2347320-308E-4D2B-AEC8-005DFA68B0C9} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{860119ED-3DB1-424D-8D0A-30132A8A7D96} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ViewComponents/IViewComponentResult.cs b/src/Microsoft.AspNet.Mvc.Core/ViewComponents/IViewComponentResult.cs
index 1cc4cdb36c..3244cbbcc5 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ViewComponents/IViewComponentResult.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ViewComponents/IViewComponentResult.cs
@@ -5,10 +5,23 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc
{
+ ///
+ /// Result type of a .
+ ///
public interface IViewComponentResult
{
+ ///
+ /// Executes the result of a using the specified .
+ ///
+ /// The for the current component execution.
void Execute([NotNull] ViewComponentContext context);
+ ///
+ /// Asynchronously executes the result of a using the specified
+ /// .
+ ///
+ /// The for the current component execution.
+ /// A that represents the asynchronous execution.
Task ExecuteAsync([NotNull] ViewComponentContext context);
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ViewComponents/ViewViewComponentResult.cs b/src/Microsoft.AspNet.Mvc.Core/ViewComponents/ViewViewComponentResult.cs
index 5cb32e5ec6..dc587b091a 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ViewComponents/ViewViewComponentResult.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ViewComponents/ViewViewComponentResult.cs
@@ -9,6 +9,9 @@ using Microsoft.AspNet.Mvc.Rendering;
namespace Microsoft.AspNet.Mvc
{
+ ///
+ /// A that renders a partial view when executed.
+ ///
public class ViewViewComponentResult : IViewComponentResult
{
// {0} is the component name, {1} is the view name.
@@ -27,11 +30,20 @@ namespace Microsoft.AspNet.Mvc
public ViewDataDictionary ViewData { get; private set; }
+ ///
+ /// Locates and renders a view specified by .
+ ///
+ /// The for the current component execution.
+ ///
+ /// This method synchronously calls and blocks on .
+ ///
public void Execute([NotNull] ViewComponentContext context)
{
- throw new NotImplementedException("There's no support for syncronous views right now.");
+ var task = ExecuteAsync(context);
+ TaskHelper.WaitAndThrowIfFaulted(task);
}
+ ///
public async Task ExecuteAsync([NotNull] ViewComponentContext context)
{
string qualifiedViewName;
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ViewComponents/ViewViewComponentResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ViewComponents/ViewViewComponentResultTest.cs
index a3da98501a..f62f864cdc 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/ViewComponents/ViewViewComponentResultTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ViewComponents/ViewViewComponentResultTest.cs
@@ -16,6 +16,77 @@ namespace Microsoft.AspNet.Mvc
{
public class ViewViewComponentResultTest
{
+ [Fact]
+ public void Execute_RendersPartialViews()
+ {
+ // Arrange
+ var view = new Mock();
+ view.Setup(v => v.RenderAsync(It.IsAny()))
+ .Returns(Task.FromResult(result: true))
+ .Verifiable();
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine.Setup(e => e.FindPartialView(It.IsAny(), It.IsAny()))
+ .Returns(ViewEngineResult.Found("some-view", view.Object))
+ .Verifiable();
+ var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider());
+ var result = new ViewViewComponentResult(viewEngine.Object, "some-view", viewData);
+ var viewComponentContext = GetViewComponentContext(view.Object, viewData);
+
+ // Act
+ result.Execute(viewComponentContext);
+
+ // Assert
+ viewEngine.Verify();
+ view.Verify();
+ }
+
+ [Fact]
+ public void Execute_ThrowsIfPartialViewCannotBeFound()
+ {
+ // Arrange
+ var expected = string.Join(Environment.NewLine,
+ "The view 'Components/Object/some-view' was not found. The following locations were searched:",
+ "location1",
+ "location2.");
+ var view = Mock.Of();
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine.Setup(e => e.FindPartialView(It.IsAny(), It.IsAny()))
+ .Returns(ViewEngineResult.NotFound("some-view", new[] { "location1", "location2" }))
+ .Verifiable();
+ var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider());
+ var result = new ViewViewComponentResult(viewEngine.Object, "some-view", viewData);
+ var viewComponentContext = GetViewComponentContext(view, viewData);
+
+ // Act and Assert
+ var ex = Assert.Throws(() => result.Execute(viewComponentContext));
+ Assert.Equal(expected, ex.Message);
+ }
+
+ [Fact]
+ public void Execute_DoesNotWrapThrownExceptionsInAggregateExceptions()
+ {
+ // Arrange
+ var expected = new IndexOutOfRangeException();
+ var view = new Mock();
+ view.Setup(v => v.RenderAsync(It.IsAny()))
+ .Throws(expected)
+ .Verifiable();
+ var viewEngine = new Mock(MockBehavior.Strict);
+ viewEngine.Setup(e => e.FindPartialView(It.IsAny(), It.IsAny()))
+ .Returns(ViewEngineResult.Found("some-view", view.Object))
+ .Verifiable();
+ var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider());
+ var result = new ViewViewComponentResult(viewEngine.Object, "some-view", viewData);
+ var viewComponentContext = GetViewComponentContext(view.Object, viewData);
+
+ // Act
+ var actual = Record.Exception(() => result.Execute(viewComponentContext));
+
+ // Assert
+ Assert.Same(expected, actual);
+ view.Verify();
+ }
+
[Fact]
public async Task ExecuteAsync_RendersPartialViews()
{
diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/ViewComponentTests.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/ViewComponentTests.cs
new file mode 100644
index 0000000000..cc98dc60d9
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/ViewComponentTests.cs
@@ -0,0 +1,55 @@
+// Copyright (c) Microsoft Open Technologies, Inc. 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.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.AspNet.Builder;
+using Microsoft.AspNet.TestHost;
+using ViewComponentWebSite;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.FunctionalTests
+{
+ public class ViewComponentTests
+ {
+ private readonly IServiceProvider _provider = TestHelper.CreateServices("ViewComponentWebSite");
+ private readonly Action _app = new Startup().Configure;
+
+ public static IEnumerable