From c7d09d7ad743e3af9bea608bbcf139c290205068 Mon Sep 17 00:00:00 2001 From: Youngjune Hong Date: Mon, 2 Feb 2015 13:49:28 -0800 Subject: [PATCH] Introducing UrlActionContext and UrlRouteContext, and updating IUrlHelper accordingly --- src/Microsoft.AspNet.Mvc.Core/IUrlHelper.cs | 25 +-- .../RemoteAttribute.cs | 7 +- .../UrlActionContext.cs | 67 ++++++++ src/Microsoft.AspNet.Mvc.Core/UrlHelper.cs | 28 ++-- .../UrlHelperExtensions.cs | 143 ++++++++++++++++++ .../UrlRouteContext.cs | 57 +++++++ .../CreatedAtActionResultTests.cs | 3 +- .../CreatedAtRouteResultTests.cs | 3 +- .../RedirectToActionResultTest.cs | 3 +- .../RedirectToRouteResultTest.cs | 3 +- .../RemoteAttributeTest.cs | 20 +-- .../Rendering/HtmlHelperFormTest.cs | 24 ++- .../Rendering/HtmlHelperLinkGenerationTest.cs | 43 ++---- .../UrlHelperTest.cs | 97 +++++++++++- .../AnchorTagHelperTest.cs | 9 +- .../FormTagHelperTest.cs | 8 +- .../UrlHelperWebSite/CustomUrlHelper.cs | 8 +- 17 files changed, 429 insertions(+), 119 deletions(-) create mode 100644 src/Microsoft.AspNet.Mvc.Core/UrlActionContext.cs create mode 100644 src/Microsoft.AspNet.Mvc.Core/UrlRouteContext.cs diff --git a/src/Microsoft.AspNet.Mvc.Core/IUrlHelper.cs b/src/Microsoft.AspNet.Mvc.Core/IUrlHelper.cs index 9c466cdfbe..81f2251bff 100644 --- a/src/Microsoft.AspNet.Mvc.Core/IUrlHelper.cs +++ b/src/Microsoft.AspNet.Mvc.Core/IUrlHelper.cs @@ -9,17 +9,12 @@ namespace Microsoft.AspNet.Mvc public interface IUrlHelper { /// - /// Generates a fully qualified or absolute URL for an action method by using the specified action name, - /// controller name, route values, protocol to use, host name and fragment. + /// Generates a fully qualified or absolute URL specified by for an action + /// method, which contains action name, controller name, route values, protocol to use, host name, and fragment. /// - /// The name of the action method. - /// The name of the controller. - /// An object that contains the parameters for a route. - /// The protocol for the URL, such as "http" or "https". - /// The host name for the URL. - /// The fragment for the URL. + /// The context object for the generated URLs for an action method. /// The fully qualified or absolute URL to an action method. - string Action(string action, string controller, object values, string protocol, string host, string fragment); + string Action([NotNull] UrlActionContext actionContext); /// /// Converts a virtual (relative) path to an application absolute path. @@ -54,15 +49,11 @@ namespace Microsoft.AspNet.Mvc bool IsLocalUrl(string url); /// - /// Generates a fully qualified or absolute URL for the specified route values by - /// using the specified route name, protocol to use, host name and fragment. + /// Generates a fully qualified or absolute URL specified by , which + /// contains the route name, the route values, protocol to use, host name and fragment. /// - /// The name of the route that is used to generate URL. - /// An object that contains the parameters for a route. - /// The protocol for the URL, such as "http" or "https". - /// The host name for the URL. - /// The fragment for the URL. + /// The context object for the generated URLs for a route. /// The fully qualified or absolute URL. - string RouteUrl(string routeName, object values, string protocol, string host, string fragment); + string RouteUrl([NotNull] UrlRouteContext routeContext); } } diff --git a/src/Microsoft.AspNet.Mvc.Core/RemoteAttribute.cs b/src/Microsoft.AspNet.Mvc.Core/RemoteAttribute.cs index e8daaf395e..d56364a03c 100644 --- a/src/Microsoft.AspNet.Mvc.Core/RemoteAttribute.cs +++ b/src/Microsoft.AspNet.Mvc.Core/RemoteAttribute.cs @@ -193,7 +193,12 @@ namespace Microsoft.AspNet.Mvc protected virtual string GetUrl([NotNull] ClientModelValidationContext context) { var urlHelper = context.RequestServices.GetRequiredService(); - var url = urlHelper.RouteUrl(RouteName, values: RouteData, protocol: null, host: null, fragment: null); + var url = urlHelper.RouteUrl(new UrlRouteContext() + { + RouteName = this.RouteName, + Values = RouteData, + }); + if (url == null) { throw new InvalidOperationException(Resources.RemoteAttribute_NoUrlFound); diff --git a/src/Microsoft.AspNet.Mvc.Core/UrlActionContext.cs b/src/Microsoft.AspNet.Mvc.Core/UrlActionContext.cs new file mode 100644 index 0000000000..db255f4bbc --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Core/UrlActionContext.cs @@ -0,0 +1,67 @@ +// 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. + +namespace Microsoft.AspNet.Mvc +{ + /// + /// Context object to be used for the URLs that generates. + /// + public class UrlActionContext + { + /// + /// The name of the action method that + public string Action + { + get; + set; + } + + /// + /// The name of the controller that + public string Controller + { + get; + set; + } + + /// + /// The object that contains the route parameters that + /// uses to generate URLs. + /// + public object Values + { + get; + set; + } + + /// + /// The protocol for the URLs that + public string Protocol + { + get; + set; + } + + /// + /// The host name for the URLs that + public string Host + { + get; + set; + } + + /// + /// The fragment for the URLs that + public string Fragment + { + get; + set; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/UrlHelper.cs b/src/Microsoft.AspNet.Mvc.Core/UrlHelper.cs index e463fcea99..607c8d7cba 100644 --- a/src/Microsoft.AspNet.Mvc.Core/UrlHelper.cs +++ b/src/Microsoft.AspNet.Mvc.Core/UrlHelper.cs @@ -40,24 +40,18 @@ namespace Microsoft.AspNet.Mvc } /// - public virtual string Action( - string action, - string controller, - object values, - string protocol, - string host, - string fragment) + public virtual string Action(UrlActionContext actionContext) { - var valuesDictionary = TypeHelper.ObjectToDictionary(values); + var valuesDictionary = TypeHelper.ObjectToDictionary(actionContext.Values); - if (action != null) + if (actionContext.Action != null) { - valuesDictionary["action"] = action; + valuesDictionary["action"] = actionContext.Action; } - if (controller != null) + if (actionContext.Controller != null) { - valuesDictionary["controller"] = controller; + valuesDictionary["controller"] = actionContext.Controller; } var path = GeneratePathFromRoute(valuesDictionary); @@ -66,7 +60,7 @@ namespace Microsoft.AspNet.Mvc return null; } - return GenerateUrl(protocol, host, path, fragment); + return GenerateUrl(actionContext.Protocol, actionContext.Host, path, actionContext.Fragment); } /// @@ -76,17 +70,17 @@ namespace Microsoft.AspNet.Mvc } /// - public virtual string RouteUrl(string routeName, object values, string protocol, string host, string fragment) + public virtual string RouteUrl(UrlRouteContext routeContext) { - var valuesDictionary = TypeHelper.ObjectToDictionary(values); + var valuesDictionary = TypeHelper.ObjectToDictionary(routeContext.Values); - var path = GeneratePathFromRoute(routeName, valuesDictionary); + var path = GeneratePathFromRoute(routeContext.RouteName, valuesDictionary); if (path == null) { return null; } - return GenerateUrl(protocol, host, path, fragment); + return GenerateUrl(routeContext.Protocol, routeContext.Host, path, routeContext.Fragment); } private string GeneratePathFromRoute(IDictionary values) diff --git a/src/Microsoft.AspNet.Mvc.Core/UrlHelperExtensions.cs b/src/Microsoft.AspNet.Mvc.Core/UrlHelperExtensions.cs index 44e12ddbac..d07aea6756 100644 --- a/src/Microsoft.AspNet.Mvc.Core/UrlHelperExtensions.cs +++ b/src/Microsoft.AspNet.Mvc.Core/UrlHelperExtensions.cs @@ -5,6 +5,10 @@ namespace Microsoft.AspNet.Mvc { public static class UrlHelperExtensions { + /// + /// Generates a fully qualified or absolute URL for an action method. + /// + /// The fully qualified or absolute URL to an action method. public static string Action([NotNull] this IUrlHelper helper) { return helper.Action( @@ -16,26 +20,62 @@ namespace Microsoft.AspNet.Mvc fragment: null); } + /// + /// Generates a fully qualified or absolute URL for an action method by using the specified action name. + /// + /// The name of the action method. + /// The fully qualified or absolute URL to an action method. public static string Action([NotNull] this IUrlHelper helper, string action) { return helper.Action(action, controller: null, values: null, protocol: null, host: null, fragment: null); } + /// + /// Generates a fully qualified or absolute URL for an action method by using the specified action name, + /// and route values. + /// + /// The name of the action method. + /// An object that contains route values. + /// The fully qualified or absolute URL to an action method. public static string Action([NotNull] this IUrlHelper helper, string action, object values) { return helper.Action(action, controller: null, values: values, protocol: null, host: null, fragment: null); } + /// + /// Generates a fully qualified or absolute URL for an action method by using the specified action name, + /// and controller name. + /// + /// The name of the action method. + /// The name of the controller. + /// The fully qualified or absolute URL to an action method. public static string Action([NotNull] this IUrlHelper helper, string action, string controller) { return helper.Action(action, controller, values: null, protocol: null, host: null, fragment: null); } + /// + /// Generates a fully qualified or absolute URL for an action method by using the specified action name, + /// controller name, and route values. + /// + /// The name of the action method. + /// The name of the controller. + /// An object that contains route values. + /// The fully qualified or absolute URL to an action method. public static string Action([NotNull] this IUrlHelper helper, string action, string controller, object values) { return helper.Action(action, controller, values, protocol: null, host: null, fragment: null); } + /// + /// Generates a fully qualified or absolute URL for an action method by using the specified action name, + /// controller name, route values, and protocol to use. + /// + /// The name of the action method. + /// The name of the controller. + /// An object that contains route values. + /// The protocol for the URL, such as "http" or "https". + /// The fully qualified or absolute URL to an action method. public static string Action( [NotNull] this IUrlHelper helper, string action, @@ -46,6 +86,16 @@ namespace Microsoft.AspNet.Mvc return helper.Action(action, controller, values, protocol, host: null, fragment: null); } + /// + /// Generates a fully qualified or absolute URL for an action method by using the specified action name, + /// controller name, route values, protocol to use, and host name. + /// + /// The name of the action method. + /// The name of the controller. + /// An object that contains route values. + /// The protocol for the URL, such as "http" or "https". + /// The host name for the URL. + /// The fully qualified or absolute URL to an action method. public static string Action( [NotNull] this IUrlHelper helper, string action, @@ -57,21 +107,77 @@ namespace Microsoft.AspNet.Mvc return helper.Action(action, controller, values, protocol, host, fragment: null); } + /// + /// Generates a fully qualified or absolute URL for an action method by using the specified action name, + /// controller name, route values, protocol to use, host name and fragment. + /// + /// The name of the action method. + /// The name of the controller. + /// An object that contains route values. + /// The protocol for the URL, such as "http" or "https". + /// The host name for the URL. + /// The fragment for the URL. + /// The fully qualified or absolute URL to an action method. + public static string Action( + [NotNull] this IUrlHelper helper, + string action, + string controller, + object values, + string protocol, + string host, + string fragment) + { + return helper.Action(new UrlActionContext() + { + Action = action, + Controller = controller, + Host = host, + Values = values, + Protocol = protocol, + Fragment = fragment + }); + } + + /// + /// Generates a fully qualified or absolute URL for the specified route values. + /// + /// An object that contains route values. + /// The fully qualified or absolute URL. public static string RouteUrl([NotNull] this IUrlHelper helper, object values) { return helper.RouteUrl(routeName: null, values: values, protocol: null, host: null, fragment: null); } + /// + /// Generates a fully qualified or absolute URL for the specified route name. + /// + /// The name of the route that is used to generate URL. + /// The fully qualified or absolute URL. public static string RouteUrl([NotNull] this IUrlHelper helper, string routeName) { return helper.RouteUrl(routeName, values: null, protocol: null, host: null, fragment: null); } + /// + /// Generates a fully qualified or absolute URL for the specified route values by + /// using the specified route name. + /// + /// The name of the route that is used to generate URL. + /// An object that contains route values. + /// The fully qualified or absolute URL. public static string RouteUrl([NotNull] this IUrlHelper helper, string routeName, object values) { return helper.RouteUrl(routeName, values, protocol: null, host: null, fragment: null); } + /// + /// Generates a fully qualified or absolute URL for the specified route values by + /// using the specified route name, and protocol to use. + /// + /// The name of the route that is used to generate URL. + /// An object that contains route values. + /// The protocol for the URL, such as "http" or "https". + /// The fully qualified or absolute URL. public static string RouteUrl( [NotNull] this IUrlHelper helper, string routeName, @@ -81,6 +187,15 @@ namespace Microsoft.AspNet.Mvc return helper.RouteUrl(routeName, values, protocol, host: null, fragment: null); } + /// + /// Generates a fully qualified or absolute URL for the specified route values by + /// using the specified route name, protocol to use, and host name. + /// + /// The name of the route that is used to generate URL. + /// An object that contains route values. + /// The protocol for the URL, such as "http" or "https". + /// The host name for the URL. + /// The fully qualified or absolute URL. public static string RouteUrl( [NotNull] this IUrlHelper helper, string routeName, @@ -90,5 +205,33 @@ namespace Microsoft.AspNet.Mvc { return helper.RouteUrl(routeName, values, protocol, host, fragment: null); } + + /// + /// Generates a fully qualified or absolute URL for the specified route values by + /// using the specified route name, protocol to use, host name and fragment. + /// + /// The name of the route that is used to generate URL. + /// An object that contains route values. + /// The protocol for the URL, such as "http" or "https". + /// The host name for the URL. + /// The fragment for the URL. + /// The fully qualified or absolute URL. + public static string RouteUrl( + [NotNull] this IUrlHelper helper, + string routeName, + object values, + string protocol, + string host, + string fragment) + { + return helper.RouteUrl(new UrlRouteContext() + { + RouteName = routeName, + Values = values, + Protocol = protocol, + Host = host, + Fragment = fragment + }); + } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/UrlRouteContext.cs b/src/Microsoft.AspNet.Mvc.Core/UrlRouteContext.cs new file mode 100644 index 0000000000..7838fa11a6 --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Core/UrlRouteContext.cs @@ -0,0 +1,57 @@ +// 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. + +namespace Microsoft.AspNet.Mvc +{ + /// + /// Context object to be used for the URLs that generates. + /// + public class UrlRouteContext + { + /// + /// The name of the route that + public string RouteName + { + get; + set; + } + + /// + /// The object that contains the route values for the generated URLs. + /// + public object Values + { + get; + set; + } + + /// + /// The protocol for the URLs that + public string Protocol + { + get; + set; + } + + /// + /// The host name for the URLs that + public string Host + { + get; + set; + } + + /// + /// The fragment for the URLs that + public string Fragment + { + get; + set; + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/CreatedAtActionResultTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/CreatedAtActionResultTests.cs index 04d81201b9..0214712d41 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/CreatedAtActionResultTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/CreatedAtActionResultTests.cs @@ -106,8 +106,7 @@ namespace Microsoft.AspNet.Mvc private static IUrlHelper GetMockUrlHelper(string returnValue) { var urlHelper = new Mock(); - urlHelper.Setup(o => o.Action(It.IsAny(), It.IsAny(), It.IsAny(), - It.IsAny(), It.IsAny(), It.IsAny())).Returns(returnValue); + urlHelper.Setup(o => o.Action(It.IsAny())).Returns(returnValue); return urlHelper.Object; } diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/CreatedAtRouteResultTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/CreatedAtRouteResultTests.cs index 4dd6801701..320bfc0503 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/CreatedAtRouteResultTests.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/CreatedAtRouteResultTests.cs @@ -115,8 +115,7 @@ namespace Microsoft.AspNet.Mvc private static IUrlHelper GetMockUrlHelper(string returnValue) { var urlHelper = new Mock(); - urlHelper.Setup(o => o.RouteUrl(It.IsAny(), It.IsAny(), It.IsAny(), - It.IsAny(), It.IsAny())).Returns(returnValue); + urlHelper.Setup(o => o.RouteUrl(It.IsAny())).Returns(returnValue); return urlHelper.Object; } diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/RedirectToActionResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/RedirectToActionResultTest.cs index 903566da9d..6b1d6b7c66 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/RedirectToActionResultTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/RedirectToActionResultTest.cs @@ -69,8 +69,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults private static IUrlHelper GetMockUrlHelper(string returnValue) { var urlHelper = new Mock(); - urlHelper.Setup(o => o.Action(It.IsAny(), It.IsAny(), It.IsAny(), - It.IsAny(), It.IsAny(), It.IsAny())).Returns(returnValue); + urlHelper.Setup(o => o.Action(It.IsAny())).Returns(returnValue); return urlHelper.Object; } diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/RedirectToRouteResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/RedirectToRouteResultTest.cs index 02d08e06e3..bf21fa6155 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/RedirectToRouteResultTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ActionResults/RedirectToRouteResultTest.cs @@ -89,8 +89,7 @@ namespace Microsoft.AspNet.Mvc.Core private static IUrlHelper GetMockUrlHelper(string returnValue) { var urlHelper = new Mock(); - urlHelper.Setup(o => o.RouteUrl(It.IsAny(), It.IsAny(), It.IsAny(), - It.IsAny(), It.IsAny())).Returns(returnValue); + urlHelper.Setup(o => o.RouteUrl(It.IsAny())).Returns(returnValue); return urlHelper.Object; } } diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/RemoteAttributeTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/RemoteAttributeTest.cs index bedeb19e64..d5c914fe99 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/RemoteAttributeTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/RemoteAttributeTest.cs @@ -596,13 +596,7 @@ namespace Microsoft.AspNet.Mvc public object RouteValues { get; private set; } - public string Action( - string action, - string controller, - object values, - string protocol, - string host, - string fragment) + public string Action(UrlActionContext actionContext) { throw new NotImplementedException(); } @@ -617,14 +611,14 @@ namespace Microsoft.AspNet.Mvc throw new NotImplementedException(); } - public string RouteUrl(string routeName, object values, string protocol, string host, string fragment) + public string RouteUrl(UrlRouteContext routeContext) { - Assert.Equal(_routeName, routeName); - Assert.Null(protocol); - Assert.Null(host); - Assert.Null(fragment); + Assert.Equal(_routeName, routeContext.RouteName); + Assert.Null(routeContext.Protocol); + Assert.Null(routeContext.Host); + Assert.Null(routeContext.Fragment); - RouteValues = values; + RouteValues = routeContext.Values; return _url; } diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperFormTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperFormTest.cs index 59cbee6b56..bcd595fd1f 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperFormTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperFormTest.cs @@ -177,13 +177,11 @@ namespace Microsoft.AspNet.Mvc.Rendering var urlHelper = new Mock(MockBehavior.Strict); urlHelper - .Setup(realHelper => realHelper.Action( - actionName, - controllerName, - routeValues, - null, // protocol - null, // host - null)) // fragment + .Setup(realHelper => realHelper.Action(It.Is((context) => + string.Equals(context.Action, actionName) && + string.Equals(context.Controller, controllerName) && + context.Values == routeValues + ))) .Returns(expectedAction) .Verifiable(); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(urlHelper.Object); @@ -221,12 +219,12 @@ namespace Microsoft.AspNet.Mvc.Rendering var urlHelper = new Mock(MockBehavior.Strict); urlHelper - .Setup(realHelper => realHelper.RouteUrl( - routeName, - routeValues, - null, // protocol - null, // host - null)) // fragment + .Setup(realHelper => realHelper.RouteUrl(It.Is(context => + string.Equals(context.RouteName, routeName) && + context.Values == routeValues && + context.Protocol == null && + context.Host == null && + context.Fragment == null))) .Returns(expectedAction) .Verifiable(); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(urlHelper.Object); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperLinkGenerationTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperLinkGenerationTest.cs index 09472e6d74..a85830c629 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperLinkGenerationTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Rendering/HtmlHelperLinkGenerationTest.cs @@ -55,23 +55,15 @@ namespace Microsoft.AspNet.Mvc.Rendering GetHtmlAttributesAsString(htmlAttributes)); var urlHelper = new Mock(); - urlHelper.Setup( - h => h.Action( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .Returns( - (actn, cntrlr, rvalues, prtcl, hname, frgmt) => - string.Format("{0}{1}{2}{3}{4}{5}", - prtcl, - hname, - cntrlr, - actn, - GetRouteValuesAsString(rvalues), - frgmt)); + urlHelper.Setup(h => h.Action(It.IsAny())) + .Returns((actionContext) => + string.Format("{0}{1}{2}{3}{4}{5}", + actionContext.Protocol, + actionContext.Host, + actionContext.Controller, + actionContext.Action, + GetRouteValuesAsString(actionContext.Values), + actionContext.Fragment)); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(urlHelper.Object); @@ -129,19 +121,12 @@ namespace Microsoft.AspNet.Mvc.Rendering var urlHelper = new Mock(); urlHelper .Setup( - h => h.RouteUrl( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .Returns( - (rname, rvalues, prtcl, hname, frgmt) => + h => h.RouteUrl(It.IsAny())).Returns((context) => string.Format("{0}{1}{2}{3}", - prtcl, - hname, - GetRouteValuesAsString(rvalues), - frgmt)); + context.Protocol, + context.Host, + GetRouteValuesAsString(context.Values), + context.Fragment)); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(urlHelper.Object); diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/UrlHelperTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/UrlHelperTest.cs index 84a4a4cd77..f8baba2bf9 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/UrlHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/UrlHelperTest.cs @@ -59,8 +59,8 @@ namespace Microsoft.AspNet.Mvc Assert.Equal(expectedPath, path); } - // UrlHelper.IsLocalUrl depends on the UrlUtility.IsLocalUrl method. - // To avoid duplicate tests, all the tests exercising IsLocalUrl verify + // UrlHelper.IsLocalUrl depends on the UrlUtility.IsLocalUrl method. + // To avoid duplicate tests, all the tests exercising IsLocalUrl verify // both of UrlHelper.IsLocalUrl and UrlUtility.IsLocalUrl [Theory] [InlineData(null)] @@ -543,6 +543,56 @@ namespace Microsoft.AspNet.Mvc Assert.Equal("/app/named/home2/newaction/someid", url); } + [Fact] + public void RouteUrlWithUrlRouteContext_ReturnsExpectedResult() + { + // Arrange + var urlHelper = CreateUrlHelperWithRouteCollection("/app"); + + var routeContext = new UrlRouteContext() + { + RouteName = "namedroute", + Values = new + { + Action = "newaction", + Controller = "home2", + id = "someid" + }, + Fragment = "somefragment", + Host = "remotetown", + Protocol = "ftp" + }; + + // Act + var url = urlHelper.RouteUrl(routeContext); + + // Assert + Assert.Equal("ftp://remotetown/app/named/home2/newaction/someid#somefragment", url); + } + + [Fact] + public void RouteUrlWithAllParameters_ReturnsExpectedResult() + { + // Arrange + var urlHelper = CreateUrlHelperWithRouteCollection("/app"); + + // Act + var url = urlHelper.RouteUrl( + routeName: "namedroute", + values: new + { + Action = "newaction", + Controller = "home2", + id = "someid" + }, + fragment: "somefragment", + host: "remotetown", + protocol: "https"); + + // Assert + Assert.Equal("https://remotetown/app/named/home2/newaction/someid#somefragment", url); + } + [Fact] public void UrlAction_RouteValuesAsDictionary_CaseSensitive() { @@ -616,6 +666,49 @@ namespace Microsoft.AspNet.Mvc Assert.Equal("/app/named/home/contact/suppliedid", url); } + [Fact] + public void UrlActionWithUrlActionContext_ReturnsExpectedResult() + { + // Arrange + var urlHelper = CreateUrlHelperWithRouteCollection("/app"); + + var actionContext = new UrlActionContext() + { + Action = "contact", + Controller = "home3", + Values = new { id = "idone" }, + Protocol = "ftp", + Host = "remotelyhost", + Fragment = "somefragment" + }; + + // Act + var url = urlHelper.Action(actionContext); + + // Assert + Assert.Equal("ftp://remotelyhost/app/home3/contact/idone#somefragment", url); + } + + [Fact] + public void UrlActionWithAllParameters_ReturnsExpectedResult() + { + // Arrange + var urlHelper = CreateUrlHelperWithRouteCollection("/app"); + + // Act + var url = urlHelper.Action( + controller: "home3", + action: "contact", + values: null, + protocol: "https", + host: "remotelyhost", + fragment: "somefragment" + ); + + // Assert + Assert.Equal("https://remotelyhost/app/home3/contact#somefragment", url); + } + private static HttpContext CreateHttpContext(string appRoot, ILoggerFactory factory = null) { if (factory == null) diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/AnchorTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/AnchorTagHelperTest.cs index e38d39037d..816ebce022 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/AnchorTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/AnchorTagHelperTest.cs @@ -47,14 +47,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers var urlHelper = new Mock(); urlHelper - .Setup(mock => mock.Action( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .Returns("home/index"); + .Setup(mock => mock.Action(It.IsAny())).Returns("home/index"); var htmlGenerator = new TestableHtmlGenerator(metadataProvider, urlHelper.Object); var viewContext = TestableHtmlGenerator.GetViewContext(model: null, diff --git a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs index 7fc7153888..6004a4c440 100644 --- a/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.TagHelpers.Test/FormTagHelperTest.cs @@ -47,13 +47,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers }; var urlHelper = new Mock(); urlHelper - .Setup(mock => mock.Action(It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .Returns("home/index"); + .Setup(mock => mock.Action(It.IsAny())).Returns("home/index"); var htmlGenerator = new TestableHtmlGenerator(metadataProvider, urlHelper.Object); var viewContext = TestableHtmlGenerator.GetViewContext(model: null, diff --git a/test/WebSites/UrlHelperWebSite/CustomUrlHelper.cs b/test/WebSites/UrlHelperWebSite/CustomUrlHelper.cs index 4598e32e49..6a61d28cd1 100644 --- a/test/WebSites/UrlHelperWebSite/CustomUrlHelper.cs +++ b/test/WebSites/UrlHelperWebSite/CustomUrlHelper.cs @@ -46,14 +46,14 @@ namespace UrlHelperWebSite return ConvertToLowercaseUrl(base.Content(contentPath)); } - public override string RouteUrl(string routeName, object values, string protocol, string host, string fragment) + public override string RouteUrl(UrlRouteContext routeContext) { - return ConvertToLowercaseUrl(base.RouteUrl(routeName, values, protocol, host, fragment)); + return ConvertToLowercaseUrl(base.RouteUrl(routeContext)); } - public override string Action(string action, string controller, object values, string protocol, string host, string fragment) + public override string Action(UrlActionContext actionContext) { - return ConvertToLowercaseUrl(base.Action(action, controller, values, protocol, host, fragment)); + return ConvertToLowercaseUrl(base.Action(actionContext)); } private string ConvertToLowercaseUrl(string url)