diff --git a/Mvc.sln b/Mvc.sln index 889dce206f..212b9a95ad 100644 --- a/Mvc.sln +++ b/Mvc.sln @@ -49,6 +49,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "RoutingWebSite", "test\WebS EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.Test", "test\Microsoft.AspNet.Mvc.Test\Microsoft.AspNet.Mvc.Test.kproj", "{5F945B82-FE5F-425C-956C-8BC2F2020254}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "CompositeViewEngine", "test\WebSites\CompositeViewEngine\CompositeViewEngine.kproj", "{A853B2BA-4449-4908-A416-5A3C027FC22B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -249,6 +251,16 @@ Global {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|Mixed Platforms.Build.0 = Release|Any CPU {5F945B82-FE5F-425C-956C-8BC2F2020254}.Release|x86.ActiveCfg = Release|Any CPU + {A853B2BA-4449-4908-A416-5A3C027FC22B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A853B2BA-4449-4908-A416-5A3C027FC22B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A853B2BA-4449-4908-A416-5A3C027FC22B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A853B2BA-4449-4908-A416-5A3C027FC22B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A853B2BA-4449-4908-A416-5A3C027FC22B}.Debug|x86.ActiveCfg = Debug|Any CPU + {A853B2BA-4449-4908-A416-5A3C027FC22B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A853B2BA-4449-4908-A416-5A3C027FC22B}.Release|Any CPU.Build.0 = Release|Any CPU + {A853B2BA-4449-4908-A416-5A3C027FC22B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A853B2BA-4449-4908-A416-5A3C027FC22B}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A853B2BA-4449-4908-A416-5A3C027FC22B}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -274,5 +286,6 @@ Global {680D75ED-601F-4D86-B01B-1072D0C31B8C} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} {42CDBF4A-E238-4C0F-A416-44588363EB4C} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} {5F945B82-FE5F-425C-956C-8BC2F2020254} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1} + {A853B2BA-4449-4908-A416-5A3C027FC22B} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C} EndGlobalSection EndGlobal diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/CompositeViewEngineTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/CompositeViewEngineTest.cs index 868912a513..05e3570173 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/CompositeViewEngineTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/CompositeViewEngineTest.cs @@ -10,6 +10,67 @@ namespace Microsoft.AspNet.Mvc.Rendering { public class CompositeViewEngineTest { + [Fact] + public void FindView_ReturnsNotFoundResult_WhenNoViewEnginesAreRegistered() + { + // Arrange + var viewName = "test-view"; + var provider = new Mock(); + provider.SetupGet(p => p.ViewEngines) + .Returns(new IViewEngine[0]); + var compositeViewEngine = new CompositeViewEngine(provider.Object); + + // Act + var result = compositeViewEngine.FindView(new Dictionary(), viewName); + + // Assert + Assert.False(result.Success); + Assert.Empty(result.SearchedLocations); + } + + [Fact] + public void FindView_ReturnsNotFoundResult_WhenExactlyOneViewEngineIsRegisteredWhichReturnsNotFoundResult() + { + // Arrange + var viewName = "test-view"; + var provider = new Mock(); + var engine = new Mock(); + engine.Setup(e => e.FindView(It.IsAny>(), It.IsAny())) + .Returns(ViewEngineResult.NotFound(viewName, new[] { "controller/test-view" })); + provider.SetupGet(p => p.ViewEngines) + .Returns(new[] { engine.Object }); + var compositeViewEngine = new CompositeViewEngine(provider.Object); + + // Act + var result = compositeViewEngine.FindView(new Dictionary(), viewName); + + // Assert + Assert.False(result.Success); + Assert.Equal(new[] { "controller/test-view" }, result.SearchedLocations); + } + + [Fact] + public void FindView_ReturnsView_WhenExactlyOneViewEngineIsRegisteredWhichReturnsAFoundResult() + { + // Arrange + var viewName = "test-view"; + var provider = new Mock(); + var engine = new Mock(); + var view = Mock.Of(); + engine.Setup(e => e.FindView(It.IsAny>(), It.IsAny())) + .Returns(ViewEngineResult.Found(viewName, view)); + provider.SetupGet(p => p.ViewEngines) + .Returns(new[] { engine.Object }); + var compositeViewEngine = new CompositeViewEngine(provider.Object); + + // Act + var result = compositeViewEngine.FindView(new Dictionary(), viewName); + + // Assert + Assert.True(result.Success); + Assert.Same(view, result.View); + } + [Fact] public void FindView_ReturnsViewFromFirstViewEngineWithFoundResult() { @@ -69,6 +130,67 @@ namespace Microsoft.AspNet.Mvc.Rendering Assert.Equal(new[] { "1", "2", "3", "4", "5" }, result.SearchedLocations); } + [Fact] + public void FindPartialView_ReturnsNotFoundResult_WhenNoViewEnginesAreRegistered() + { + // Arrange + var viewName = "my-partial-view"; + var provider = new Mock(); + provider.SetupGet(p => p.ViewEngines) + .Returns(new IViewEngine[0]); + var compositeViewEngine = new CompositeViewEngine(provider.Object); + + // Act + var result = compositeViewEngine.FindPartialView(new Dictionary(), viewName); + + // Assert + Assert.False(result.Success); + Assert.Empty(result.SearchedLocations); + } + + [Fact] + public void FindPartialView_ReturnsNotFoundResult_WhenExactlyOneViewEngineIsRegisteredWhichReturnsNotFoundResult() + { + // Arrange + var viewName = "partial-view"; + var provider = new Mock(); + var engine = new Mock(); + engine.Setup(e => e.FindPartialView(It.IsAny>(), It.IsAny())) + .Returns(ViewEngineResult.NotFound(viewName, new[] { "shared/partial-view" })); + provider.SetupGet(p => p.ViewEngines) + .Returns(new[] { engine.Object }); + var compositeViewEngine = new CompositeViewEngine(provider.Object); + + // Act + var result = compositeViewEngine.FindPartialView(new Dictionary(), viewName); + + // Assert + Assert.False(result.Success); + Assert.Equal(new[] { "shared/partial-view" }, result.SearchedLocations); + } + + [Fact] + public void FindPartialView_ReturnsView_WhenExactlyOneViewEngineIsRegisteredWhichReturnsAFoundResult() + { + // Arrange + var viewName = "test-view"; + var provider = new Mock(); + var engine = new Mock(); + var view = Mock.Of(); + engine.Setup(e => e.FindPartialView(It.IsAny>(), It.IsAny())) + .Returns(ViewEngineResult.Found(viewName, view)); + provider.SetupGet(p => p.ViewEngines) + .Returns(new[] { engine.Object }); + var compositeViewEngine = new CompositeViewEngine(provider.Object); + + // Act + var result = compositeViewEngine.FindPartialView(new Dictionary(), viewName); + + // Assert + Assert.True(result.Success); + Assert.Same(view, result.View); + } + [Fact] public void FindPartialView_ReturnsViewFromFirstViewEngineWithFoundResult() { diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/CompositeViewEngineTests.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/CompositeViewEngineTests.cs new file mode 100644 index 0000000000..ea46c4b553 --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/CompositeViewEngineTests.cs @@ -0,0 +1,52 @@ +// 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.Threading.Tasks; +using Microsoft.AspNet.Builder; +using Microsoft.AspNet.TestHost; +using Xunit; + +namespace Microsoft.AspNet.Mvc.FunctionalTests +{ + public class CompositeViewEngineTests + { + private readonly IServiceProvider _services; + private readonly Action _app = new CompositeViewEngine.Startup().Configure; + + public CompositeViewEngineTests() + { + _services = TestHelper.CreateServices("CompositeViewEngine"); + } + + [Fact] + public async Task CompositeViewEngine_FindsPartialViewsAcrossAllEngines() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.Handler; + + // Act + var response = await client.GetAsync("http://localhost/"); + + // Assert + var body = await response.ReadBodyAsStringAsync(); + Assert.Equal("Hello world", body.Trim()); + } + + [Fact] + public async Task CompositeViewEngine_FindsViewsAcrossAllEngines() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.Handler; + + // Act + var response = await client.GetAsync("http://localhost/Home/TestView"); + + // Assert + var body = await response.ReadBodyAsStringAsync(); + Assert.Equal("Content from test view", body.Trim()); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/Microsoft.AspNet.Mvc.FunctionalTests.kproj b/test/Microsoft.AspNet.Mvc.FunctionalTests/Microsoft.AspNet.Mvc.FunctionalTests.kproj index 7479f566f7..ee527ae290 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/Microsoft.AspNet.Mvc.FunctionalTests.kproj +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/Microsoft.AspNet.Mvc.FunctionalTests.kproj @@ -31,6 +31,7 @@ + diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/project.json b/test/Microsoft.AspNet.Mvc.FunctionalTests/project.json index 4f78736822..a89f78b9d3 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/project.json +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/project.json @@ -5,6 +5,7 @@ "dependencies": { "ActivatorWebSite": "", "BasicWebSite": "", + "CompositeViewEngine": "", "InlineConstraintsWebSite": "", "Microsoft.AspNet.TestHost": "1.0.0-*", "Microsoft.AspNet.Mvc.TestConfiguration": "", diff --git a/test/WebSites/CompositeViewEngine/CompositeViewEngine.kproj b/test/WebSites/CompositeViewEngine/CompositeViewEngine.kproj new file mode 100644 index 0000000000..e28ebebef3 --- /dev/null +++ b/test/WebSites/CompositeViewEngine/CompositeViewEngine.kproj @@ -0,0 +1,37 @@ + + + + 12.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + a853b2ba-4449-4908-a416-5a3c027fc22b + Library + + + ConsoleDebugger + + + WebDebugger + + + + + + + 2.0 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/WebSites/CompositeViewEngine/HomeController.cs b/test/WebSites/CompositeViewEngine/HomeController.cs new file mode 100644 index 0000000000..d79da054db --- /dev/null +++ b/test/WebSites/CompositeViewEngine/HomeController.cs @@ -0,0 +1,20 @@ +// 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 Microsoft.AspNet.Mvc; + +namespace CompositeViewEngine +{ + public class HomeController + { + public ViewResult Index() + { + return new ViewResult(); + } + + public ViewResult TestView() + { + return new ViewResult { ViewName = "test-view" }; + } + } +} \ No newline at end of file diff --git a/test/WebSites/CompositeViewEngine/Startup.cs b/test/WebSites/CompositeViewEngine/Startup.cs new file mode 100644 index 0000000000..65223ba53a --- /dev/null +++ b/test/WebSites/CompositeViewEngine/Startup.cs @@ -0,0 +1,31 @@ +// 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 Microsoft.AspNet.Builder; +using Microsoft.AspNet.Mvc; +using Microsoft.Framework.DependencyInjection; + +namespace CompositeViewEngine +{ + public class Startup + { + public void Configure(IBuilder app) + { + var configuration = app.GetTestConfiguration(); + + // Set up application services + app.UseServices(services => + { + // Add a view engine as the first one in the list. + services.AddMvc(configuration) + .SetupOptions(options => + { + options.ViewEngines.Insert(0, typeof(TestViewEngine)); + }); + }); + + // Add MVC to the request pipeline + app.UseMvc(); + } + } +} diff --git a/test/WebSites/CompositeViewEngine/TestPartialView.cs b/test/WebSites/CompositeViewEngine/TestPartialView.cs new file mode 100644 index 0000000000..2a82cc966e --- /dev/null +++ b/test/WebSites/CompositeViewEngine/TestPartialView.cs @@ -0,0 +1,17 @@ +// 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.Threading.Tasks; +using Microsoft.AspNet.Mvc; +using Microsoft.AspNet.Mvc.Rendering; + +namespace CompositeViewEngine +{ + public class TestPartialView : IView + { + public async Task RenderAsync(ViewContext context) + { + await context.Writer.WriteLineAsync("world"); + } + } +} \ No newline at end of file diff --git a/test/WebSites/CompositeViewEngine/TestView.cs b/test/WebSites/CompositeViewEngine/TestView.cs new file mode 100644 index 0000000000..6a191a299f --- /dev/null +++ b/test/WebSites/CompositeViewEngine/TestView.cs @@ -0,0 +1,17 @@ +// 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.Threading.Tasks; +using Microsoft.AspNet.Mvc; +using Microsoft.AspNet.Mvc.Rendering; + +namespace CompositeViewEngine +{ + public class TestView : IView + { + public async Task RenderAsync(ViewContext context) + { + await context.Writer.WriteLineAsync("Content from test view"); + } + } +} \ No newline at end of file diff --git a/test/WebSites/CompositeViewEngine/TestViewEngine.cs b/test/WebSites/CompositeViewEngine/TestViewEngine.cs new file mode 100644 index 0000000000..ce7a88ddae --- /dev/null +++ b/test/WebSites/CompositeViewEngine/TestViewEngine.cs @@ -0,0 +1,30 @@ +// 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 Microsoft.AspNet.Mvc.Rendering; + +namespace CompositeViewEngine +{ + public class TestViewEngine : IViewEngine + { + public ViewEngineResult FindPartialView(IDictionary context, string partialViewName) + { + if (string.Equals(partialViewName, "partial-test-view", StringComparison.Ordinal)) + { + return ViewEngineResult.Found(partialViewName, new TestPartialView()); + } + return ViewEngineResult.NotFound(partialViewName, new[] { partialViewName }); + } + + public ViewEngineResult FindView(IDictionary context, string viewName) + { + if (string.Equals(viewName, "test-view")) + { + return ViewEngineResult.Found(viewName, new TestView()); + } + return ViewEngineResult.NotFound(viewName, new[] { viewName }); + } + } +} \ No newline at end of file diff --git a/test/WebSites/CompositeViewEngine/Views/Home/Index.cshtml b/test/WebSites/CompositeViewEngine/Views/Home/Index.cshtml new file mode 100644 index 0000000000..7b7a2e971d --- /dev/null +++ b/test/WebSites/CompositeViewEngine/Views/Home/Index.cshtml @@ -0,0 +1 @@ +Hello @await Html.PartialAsync("partial-test-view") \ No newline at end of file diff --git a/test/WebSites/CompositeViewEngine/project.json b/test/WebSites/CompositeViewEngine/project.json new file mode 100644 index 0000000000..8c1ff28de3 --- /dev/null +++ b/test/WebSites/CompositeViewEngine/project.json @@ -0,0 +1,12 @@ +{ + "dependencies": { + "Microsoft.AspNet.Mvc": "", + "Microsoft.AspNet.Server.IIS": "1.0.0-*", + "Microsoft.AspNet.Mvc.TestConfiguration": "", + "Microsoft.Framework.ConfigurationModel": "" + }, + "configurations": { + "net45": { }, + "k10": { } + } +}