diff --git a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHostOptions.cs b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHostOptions.cs index 3e9b26e68d..b95000e62f 100644 --- a/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHostOptions.cs +++ b/src/Microsoft.AspNet.Mvc.Razor.Host/MvcRazorHostOptions.cs @@ -18,6 +18,7 @@ namespace Microsoft.AspNet.Mvc.Razor { new InjectDescriptor("Microsoft.AspNet.Mvc.Rendering.IHtmlHelper", "Html"), new InjectDescriptor("Microsoft.AspNet.Mvc.IViewComponentHelper", "Component"), + new InjectDescriptor("Microsoft.AspNet.Mvc.IUrlHelper", "Url"), }; } diff --git a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs index a18a792994..73490d4744 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/RazorPage.cs @@ -10,6 +10,7 @@ using System.Security.Principal; using System.Threading.Tasks; using Microsoft.AspNet.Http; using Microsoft.AspNet.Mvc.Rendering; +using Microsoft.Framework.DependencyInjection; namespace Microsoft.AspNet.Mvc.Razor { @@ -18,6 +19,7 @@ namespace Microsoft.AspNet.Mvc.Razor /// public abstract class RazorPage : IRazorPage { + private IUrlHelper _urlHelper; private readonly HashSet _renderedSections = new HashSet(StringComparer.OrdinalIgnoreCase); private bool _renderedBody; @@ -26,9 +28,6 @@ namespace Microsoft.AspNet.Mvc.Razor SectionWriters = new Dictionary(StringComparer.OrdinalIgnoreCase); } - [Activate] - public IUrlHelper Url { get; set; } - public HttpContext Context { get @@ -231,7 +230,12 @@ namespace Microsoft.AspNet.Mvc.Razor public virtual string Href([NotNull] string contentPath) { - return Url.Content(contentPath); + if (_urlHelper == null) + { + _urlHelper = Context.RequestServices.GetService(); + } + + return _urlHelper.Content(contentPath); } private void WritePositionTaggedLiteral(TextWriter writer, string value, int position) diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/ActivatorTests.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/ActivatorTests.cs index 20505e8314..6193cbfbf9 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/ActivatorTests.cs +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/ActivatorTests.cs @@ -67,7 +67,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests { var server = TestServer.Create(_provider, _app); var client = server.Handler; - var expected = " world!"; + var expected = @" world! /View/ConsumeServicesFromBaseType"; // Act var result = await client.GetAsync("http://localhost/View/ConsumeDefaultProperties"); @@ -97,9 +97,8 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests { var server = TestServer.Create(_provider, _app); var client = server.Handler; - var expected = -@"/content/scripts/test.js -/View/ConsumeDefaultProperties"; + var expected = +@"/content/scripts/test.js"; // Act var result = await client.GetAsync("http://localhost/View/ConsumeServicesFromBaseType"); diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Inject.cs b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Inject.cs index 297e8e9565..af51698d3c 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Inject.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Inject.cs @@ -33,6 +33,8 @@ using MyNamespace public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper Html { get; private set; } [Microsoft.AspNet.Mvc.ActivateAttribute] public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } + [Microsoft.AspNet.Mvc.ActivateAttribute] + public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } #line hidden diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/InjectWithModel.cs b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/InjectWithModel.cs index f01a3aefb6..81df5c49e7 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/InjectWithModel.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/InjectWithModel.cs @@ -39,6 +39,8 @@ { get; private set; } [Microsoft.AspNet.Mvc.ActivateAttribute] public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } + [Microsoft.AspNet.Mvc.ActivateAttribute] + public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } #line hidden diff --git a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Model.cs b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Model.cs index e5e11623f7..523b36e68f 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Model.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Host.Test/TestFiles/Output/Model.cs @@ -25,6 +25,8 @@ public Microsoft.AspNet.Mvc.Rendering.IHtmlHelper Html { get; private set; } [Microsoft.AspNet.Mvc.ActivateAttribute] public Microsoft.AspNet.Mvc.IViewComponentHelper Component { get; private set; } + [Microsoft.AspNet.Mvc.ActivateAttribute] + public Microsoft.AspNet.Mvc.IUrlHelper Url { get; private set; } #line hidden diff --git a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs index 081df63fe2..6a871c8833 100644 --- a/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs +++ b/test/Microsoft.AspNet.Mvc.Razor.Test/RazorPageTest.cs @@ -155,7 +155,6 @@ namespace Microsoft.AspNet.Mvc.Razor Assert.Equal(true, actual); } - [Fact] public async Task RenderSection_ThrowsIfSectionIsRenderedMoreThanOnce() { @@ -265,6 +264,34 @@ Layout end Assert.Equal(expected, actual); } + [Fact] + public async Task Href_ReadsUrlHelperFromServiceCollection() + { + // Arrange + var expected = "urlhelper-url"; + var helper = new Mock(); + helper.Setup(h => h.Content("url")) + .Returns(expected) + .Verifiable(); + var page = CreatePage(v => + { + v.Write(v.Href("url")); + }); + var services = new Mock(); + services.Setup(s => s.GetService(typeof(IUrlHelper))) + .Returns(helper.Object); + Mock.Get(page.Context).Setup(c => c.RequestServices) + .Returns(services.Object); + + // Act + await page.ExecuteAsync(); + + // Assert + var actual = ((StringWriter)page.Output).ToString(); + Assert.Equal(expected, actual); + helper.Verify(); + } + private static TestableRazorPage CreatePage(Action executeAction) { var view = new Mock { CallBase = true }; diff --git a/test/WebSites/ActivatorWebSite/Views/View/ConsumeDefaultProperties.cshtml b/test/WebSites/ActivatorWebSite/Views/View/ConsumeDefaultProperties.cshtml index c7a5a66e68..c441e7975c 100644 --- a/test/WebSites/ActivatorWebSite/Views/View/ConsumeDefaultProperties.cshtml +++ b/test/WebSites/ActivatorWebSite/Views/View/ConsumeDefaultProperties.cshtml @@ -1 +1 @@ -@Html.Label("Hello") @Component.Invoke("Test", "world") \ No newline at end of file +@Html.Label("Hello") @Component.Invoke("Test", "world") @Url.Action("ConsumeServicesFromBaseType") \ No newline at end of file diff --git a/test/WebSites/ActivatorWebSite/Views/View/ConsumeServicesFromBaseType.cshtml b/test/WebSites/ActivatorWebSite/Views/View/ConsumeServicesFromBaseType.cshtml index 7a8298dacc..bb44de7e7a 100644 --- a/test/WebSites/ActivatorWebSite/Views/View/ConsumeServicesFromBaseType.cshtml +++ b/test/WebSites/ActivatorWebSite/Views/View/ConsumeServicesFromBaseType.cshtml @@ -1,2 +1 @@ @Href("~/content/scripts/test.js") -@Url.Action("ConsumeDefaultProperties") \ No newline at end of file