Introducing UrlActionContext and UrlRouteContext, and updating IUrlHelper accordingly

This commit is contained in:
Youngjune Hong 2015-02-02 13:49:28 -08:00
parent ac6a1a6a80
commit c7d09d7ad7
17 changed files with 429 additions and 119 deletions

View File

@ -9,17 +9,12 @@ namespace Microsoft.AspNet.Mvc
public interface IUrlHelper public interface IUrlHelper
{ {
/// <summary> /// <summary>
/// Generates a fully qualified or absolute URL for an action method by using the specified action name, /// Generates a fully qualified or absolute URL specified by <see cref="Mvc.UrlActionContext"/> for an action
/// controller name, route values, protocol to use, host name and fragment. /// method, which contains action name, controller name, route values, protocol to use, host name, and fragment.
/// </summary> /// </summary>
/// <param name="action">The name of the action method.</param> /// <param name="actionContext">The context object for the generated URLs for an action method.</param>
/// <param name="controller">The name of the controller.</param>
/// <param name="values">An object that contains the parameters for a route.</param>
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
/// <param name="host">The host name for the URL.</param>
/// <param name="fragment">The fragment for the URL.</param>
/// <returns>The fully qualified or absolute URL to an action method.</returns> /// <returns>The fully qualified or absolute URL to an action method.</returns>
string Action(string action, string controller, object values, string protocol, string host, string fragment); string Action([NotNull] UrlActionContext actionContext);
/// <summary> /// <summary>
/// Converts a virtual (relative) path to an application absolute path. /// Converts a virtual (relative) path to an application absolute path.
@ -54,15 +49,11 @@ namespace Microsoft.AspNet.Mvc
bool IsLocalUrl(string url); bool IsLocalUrl(string url);
/// <summary> /// <summary>
/// Generates a fully qualified or absolute URL for the specified route values by /// Generates a fully qualified or absolute URL specified by <see cref="Mvc.UrlRouteContext"/>, which
/// using the specified route name, protocol to use, host name and fragment. /// contains the route name, the route values, protocol to use, host name and fragment.
/// </summary> /// </summary>
/// <param name="routeName">The name of the route that is used to generate URL.</param> /// <param name="routeContext">The context object for the generated URLs for a route.</param>
/// <param name="values">An object that contains the parameters for a route.</param>
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
/// <param name="host">The host name for the URL.</param>
/// <param name="fragment">The fragment for the URL.</param>
/// <returns>The fully qualified or absolute URL.</returns> /// <returns>The fully qualified or absolute URL.</returns>
string RouteUrl(string routeName, object values, string protocol, string host, string fragment); string RouteUrl([NotNull] UrlRouteContext routeContext);
} }
} }

View File

@ -193,7 +193,12 @@ namespace Microsoft.AspNet.Mvc
protected virtual string GetUrl([NotNull] ClientModelValidationContext context) protected virtual string GetUrl([NotNull] ClientModelValidationContext context)
{ {
var urlHelper = context.RequestServices.GetRequiredService<IUrlHelper>(); var urlHelper = context.RequestServices.GetRequiredService<IUrlHelper>();
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) if (url == null)
{ {
throw new InvalidOperationException(Resources.RemoteAttribute_NoUrlFound); throw new InvalidOperationException(Resources.RemoteAttribute_NoUrlFound);

View File

@ -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
{
/// <summary>
/// Context object to be used for the URLs that <see cref="Mvc.IUrlHelper.Action(UrlActionContext)"/> generates.
/// </summary>
public class UrlActionContext
{
/// <summary>
/// The name of the action method that <see cref="Mvc.UrlHelper.Action(UrlActionContext)" uses to generate URLs.
/// </summary>
public string Action
{
get;
set;
}
/// <summary>
/// The name of the controller that <see cref="Mvc.UrlHelper.Action(UrlActionContext)" uses to generate URLs.
/// </summary>
public string Controller
{
get;
set;
}
/// <summary>
/// The object that contains the route parameters that <see cref="Mvc.IUrlHelper.Action(UrlActionContext)"/>
/// uses to generate URLs.
/// </summary>
public object Values
{
get;
set;
}
/// <summary>
/// The protocol for the URLs that <see cref="Mvc.UrlHelper.Action(UrlActionContext)" generates
/// such as "http" or "https"
/// </summary>
public string Protocol
{
get;
set;
}
/// <summary>
/// The host name for the URLs that <see cref="Mvc.UrlHelper.Action(UrlActionContext)" generates.
/// </summary>
public string Host
{
get;
set;
}
/// <summary>
/// The fragment for the URLs that <see cref="Mvc.UrlHelper.Action(UrlActionContext)" generates.
/// </summary>
public string Fragment
{
get;
set;
}
}
}

View File

@ -40,24 +40,18 @@ namespace Microsoft.AspNet.Mvc
} }
/// <inheritdoc /> /// <inheritdoc />
public virtual string Action( public virtual string Action(UrlActionContext actionContext)
string action,
string controller,
object values,
string protocol,
string host,
string fragment)
{ {
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); var path = GeneratePathFromRoute(valuesDictionary);
@ -66,7 +60,7 @@ namespace Microsoft.AspNet.Mvc
return null; return null;
} }
return GenerateUrl(protocol, host, path, fragment); return GenerateUrl(actionContext.Protocol, actionContext.Host, path, actionContext.Fragment);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -76,17 +70,17 @@ namespace Microsoft.AspNet.Mvc
} }
/// <inheritdoc /> /// <inheritdoc />
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) if (path == null)
{ {
return null; return null;
} }
return GenerateUrl(protocol, host, path, fragment); return GenerateUrl(routeContext.Protocol, routeContext.Host, path, routeContext.Fragment);
} }
private string GeneratePathFromRoute(IDictionary<string, object> values) private string GeneratePathFromRoute(IDictionary<string, object> values)

View File

@ -5,6 +5,10 @@ namespace Microsoft.AspNet.Mvc
{ {
public static class UrlHelperExtensions public static class UrlHelperExtensions
{ {
/// <summary>
/// Generates a fully qualified or absolute URL for an action method.
/// </summary>
/// <returns>The fully qualified or absolute URL to an action method.</returns>
public static string Action([NotNull] this IUrlHelper helper) public static string Action([NotNull] this IUrlHelper helper)
{ {
return helper.Action( return helper.Action(
@ -16,26 +20,62 @@ namespace Microsoft.AspNet.Mvc
fragment: null); fragment: null);
} }
/// <summary>
/// Generates a fully qualified or absolute URL for an action method by using the specified action name.
/// </summary>
/// <param name="action">The name of the action method.</param>
/// <returns>The fully qualified or absolute URL to an action method.</returns>
public static string Action([NotNull] this IUrlHelper helper, string action) public static string Action([NotNull] this IUrlHelper helper, string action)
{ {
return helper.Action(action, controller: null, values: null, protocol: null, host: null, fragment: null); return helper.Action(action, controller: null, values: null, protocol: null, host: null, fragment: null);
} }
/// <summary>
/// Generates a fully qualified or absolute URL for an action method by using the specified action name,
/// and route values.
/// </summary>
/// <param name="action">The name of the action method.</param>
/// <param name="values">An object that contains route values.</param>
/// <returns>The fully qualified or absolute URL to an action method.</returns>
public static string Action([NotNull] this IUrlHelper helper, string action, object values) 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); return helper.Action(action, controller: null, values: values, protocol: null, host: null, fragment: null);
} }
/// <summary>
/// Generates a fully qualified or absolute URL for an action method by using the specified action name,
/// and controller name.
/// </summary>
/// <param name="action">The name of the action method.</param>
/// <param name="controller">The name of the controller.</param>
/// <returns>The fully qualified or absolute URL to an action method.</returns>
public static string Action([NotNull] this IUrlHelper helper, string action, string controller) 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); return helper.Action(action, controller, values: null, protocol: null, host: null, fragment: null);
} }
/// <summary>
/// Generates a fully qualified or absolute URL for an action method by using the specified action name,
/// controller name, and route values.
/// </summary>
/// <param name="action">The name of the action method.</param>
/// <param name="controller">The name of the controller.</param>
/// <param name="values">An object that contains route values.</param>
/// <returns>The fully qualified or absolute URL to an action method.</returns>
public static string Action([NotNull] this IUrlHelper helper, string action, string controller, object values) 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); return helper.Action(action, controller, values, protocol: null, host: null, fragment: null);
} }
/// <summary>
/// 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.
/// </summary>
/// <param name="action">The name of the action method.</param>
/// <param name="controller">The name of the controller.</param>
/// <param name="values">An object that contains route values.</param>
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
/// <returns>The fully qualified or absolute URL to an action method.</returns>
public static string Action( public static string Action(
[NotNull] this IUrlHelper helper, [NotNull] this IUrlHelper helper,
string action, string action,
@ -46,6 +86,16 @@ namespace Microsoft.AspNet.Mvc
return helper.Action(action, controller, values, protocol, host: null, fragment: null); return helper.Action(action, controller, values, protocol, host: null, fragment: null);
} }
/// <summary>
/// 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.
/// </summary>
/// <param name="action">The name of the action method.</param>
/// <param name="controller">The name of the controller.</param>
/// <param name="values">An object that contains route values.</param>
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
/// <param name="host">The host name for the URL.</param>
/// <returns>The fully qualified or absolute URL to an action method.</returns>
public static string Action( public static string Action(
[NotNull] this IUrlHelper helper, [NotNull] this IUrlHelper helper,
string action, string action,
@ -57,21 +107,77 @@ namespace Microsoft.AspNet.Mvc
return helper.Action(action, controller, values, protocol, host, fragment: null); return helper.Action(action, controller, values, protocol, host, fragment: null);
} }
/// <summary>
/// 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.
/// </summary>
/// <param name="action">The name of the action method.</param>
/// <param name="controller">The name of the controller.</param>
/// <param name="values">An object that contains route values.</param>
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
/// <param name="host">The host name for the URL.</param>
/// <param name="fragment">The fragment for the URL.</param>
/// <returns>The fully qualified or absolute URL to an action method.</returns>
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
});
}
/// <summary>
/// Generates a fully qualified or absolute URL for the specified route values.
/// </summary>
/// <param name="values">An object that contains route values.</param>
/// <returns>The fully qualified or absolute URL.</returns>
public static string RouteUrl([NotNull] this IUrlHelper helper, object values) public static string RouteUrl([NotNull] this IUrlHelper helper, object values)
{ {
return helper.RouteUrl(routeName: null, values: values, protocol: null, host: null, fragment: null); return helper.RouteUrl(routeName: null, values: values, protocol: null, host: null, fragment: null);
} }
/// <summary>
/// Generates a fully qualified or absolute URL for the specified route name.
/// </summary>
/// <param name="routeName">The name of the route that is used to generate URL.</param>
/// <returns>The fully qualified or absolute URL.</returns>
public static string RouteUrl([NotNull] this IUrlHelper helper, string routeName) public static string RouteUrl([NotNull] this IUrlHelper helper, string routeName)
{ {
return helper.RouteUrl(routeName, values: null, protocol: null, host: null, fragment: null); return helper.RouteUrl(routeName, values: null, protocol: null, host: null, fragment: null);
} }
/// <summary>
/// Generates a fully qualified or absolute URL for the specified route values by
/// using the specified route name.
/// </summary>
/// <param name="routeName">The name of the route that is used to generate URL.</param>
/// <param name="values">An object that contains route values.</param>
/// <returns>The fully qualified or absolute URL.</returns>
public static string RouteUrl([NotNull] this IUrlHelper helper, string routeName, object values) public static string RouteUrl([NotNull] this IUrlHelper helper, string routeName, object values)
{ {
return helper.RouteUrl(routeName, values, protocol: null, host: null, fragment: null); return helper.RouteUrl(routeName, values, protocol: null, host: null, fragment: null);
} }
/// <summary>
/// Generates a fully qualified or absolute URL for the specified route values by
/// using the specified route name, and protocol to use.
/// </summary>
/// <param name="routeName">The name of the route that is used to generate URL.</param>
/// <param name="values">An object that contains route values.</param>
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
/// <returns>The fully qualified or absolute URL.</returns>
public static string RouteUrl( public static string RouteUrl(
[NotNull] this IUrlHelper helper, [NotNull] this IUrlHelper helper,
string routeName, string routeName,
@ -81,6 +187,15 @@ namespace Microsoft.AspNet.Mvc
return helper.RouteUrl(routeName, values, protocol, host: null, fragment: null); return helper.RouteUrl(routeName, values, protocol, host: null, fragment: null);
} }
/// <summary>
/// Generates a fully qualified or absolute URL for the specified route values by
/// using the specified route name, protocol to use, and host name.
/// </summary>
/// <param name="routeName">The name of the route that is used to generate URL.</param>
/// <param name="values">An object that contains route values.</param>
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
/// <param name="host">The host name for the URL.</param>
/// <returns>The fully qualified or absolute URL.</returns>
public static string RouteUrl( public static string RouteUrl(
[NotNull] this IUrlHelper helper, [NotNull] this IUrlHelper helper,
string routeName, string routeName,
@ -90,5 +205,33 @@ namespace Microsoft.AspNet.Mvc
{ {
return helper.RouteUrl(routeName, values, protocol, host, fragment: null); return helper.RouteUrl(routeName, values, protocol, host, fragment: null);
} }
/// <summary>
/// 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.
/// </summary>
/// <param name="routeName">The name of the route that is used to generate URL.</param>
/// <param name="values">An object that contains route values.</param>
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
/// <param name="host">The host name for the URL.</param>
/// <param name="fragment">The fragment for the URL.</param>
/// <returns>The fully qualified or absolute URL.</returns>
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
});
}
} }
} }

View File

@ -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
{
/// <summary>
/// Context object to be used for the URLs that <see cref="Mvc.IUrlHelper.RouteUrl(UrlRouteContext)"/> generates.
/// </summary>
public class UrlRouteContext
{
/// <summary>
/// The name of the route that <see cref="Mvc.IUrlHelper.RouteUrl(UrlRouteContext)" uses to generate URLs.
/// </summary>
public string RouteName
{
get;
set;
}
/// <summary>
/// The object that contains the route values for the generated URLs.
/// </summary>
public object Values
{
get;
set;
}
/// <summary>
/// The protocol for the URLs that <see cref="Mvc.IUrlHelper.RouteUrl(UrlRouteContext)" generates
/// such as "http" or "https"
/// </summary>
public string Protocol
{
get;
set;
}
/// <summary>
/// The host name for the URLs that <see cref="Mvc.IUrlHelper.RouteUrl(UrlRouteContext)" generates.
/// </summary>
public string Host
{
get;
set;
}
/// <summary>
/// The fragment for the URLs that <see cref="Mvc.IUrlHelper.RouteUrl(UrlRouteContext)" generates.
/// </summary>
public string Fragment
{
get;
set;
}
}
}

View File

@ -106,8 +106,7 @@ namespace Microsoft.AspNet.Mvc
private static IUrlHelper GetMockUrlHelper(string returnValue) private static IUrlHelper GetMockUrlHelper(string returnValue)
{ {
var urlHelper = new Mock<IUrlHelper>(); var urlHelper = new Mock<IUrlHelper>();
urlHelper.Setup(o => o.Action(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<object>(), urlHelper.Setup(o => o.Action(It.IsAny<UrlActionContext>())).Returns(returnValue);
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(returnValue);
return urlHelper.Object; return urlHelper.Object;
} }

View File

@ -115,8 +115,7 @@ namespace Microsoft.AspNet.Mvc
private static IUrlHelper GetMockUrlHelper(string returnValue) private static IUrlHelper GetMockUrlHelper(string returnValue)
{ {
var urlHelper = new Mock<IUrlHelper>(); var urlHelper = new Mock<IUrlHelper>();
urlHelper.Setup(o => o.RouteUrl(It.IsAny<string>(), It.IsAny<object>(), It.IsAny<string>(), urlHelper.Setup(o => o.RouteUrl(It.IsAny<UrlRouteContext>())).Returns(returnValue);
It.IsAny<string>(), It.IsAny<string>())).Returns(returnValue);
return urlHelper.Object; return urlHelper.Object;
} }

View File

@ -69,8 +69,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
private static IUrlHelper GetMockUrlHelper(string returnValue) private static IUrlHelper GetMockUrlHelper(string returnValue)
{ {
var urlHelper = new Mock<IUrlHelper>(); var urlHelper = new Mock<IUrlHelper>();
urlHelper.Setup(o => o.Action(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<object>(), urlHelper.Setup(o => o.Action(It.IsAny<UrlActionContext>())).Returns(returnValue);
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(returnValue);
return urlHelper.Object; return urlHelper.Object;
} }

View File

@ -89,8 +89,7 @@ namespace Microsoft.AspNet.Mvc.Core
private static IUrlHelper GetMockUrlHelper(string returnValue) private static IUrlHelper GetMockUrlHelper(string returnValue)
{ {
var urlHelper = new Mock<IUrlHelper>(); var urlHelper = new Mock<IUrlHelper>();
urlHelper.Setup(o => o.RouteUrl(It.IsAny<string>(), It.IsAny<object>(), It.IsAny<string>(), urlHelper.Setup(o => o.RouteUrl(It.IsAny<UrlRouteContext>())).Returns(returnValue);
It.IsAny<string>(), It.IsAny<string>())).Returns(returnValue);
return urlHelper.Object; return urlHelper.Object;
} }
} }

View File

@ -596,13 +596,7 @@ namespace Microsoft.AspNet.Mvc
public object RouteValues { get; private set; } public object RouteValues { get; private set; }
public string Action( public string Action(UrlActionContext actionContext)
string action,
string controller,
object values,
string protocol,
string host,
string fragment)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -617,14 +611,14 @@ namespace Microsoft.AspNet.Mvc
throw new NotImplementedException(); 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.Equal(_routeName, routeContext.RouteName);
Assert.Null(protocol); Assert.Null(routeContext.Protocol);
Assert.Null(host); Assert.Null(routeContext.Host);
Assert.Null(fragment); Assert.Null(routeContext.Fragment);
RouteValues = values; RouteValues = routeContext.Values;
return _url; return _url;
} }

View File

@ -177,13 +177,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
var urlHelper = new Mock<IUrlHelper>(MockBehavior.Strict); var urlHelper = new Mock<IUrlHelper>(MockBehavior.Strict);
urlHelper urlHelper
.Setup(realHelper => realHelper.Action( .Setup(realHelper => realHelper.Action(It.Is<UrlActionContext>((context) =>
actionName, string.Equals(context.Action, actionName) &&
controllerName, string.Equals(context.Controller, controllerName) &&
routeValues, context.Values == routeValues
null, // protocol )))
null, // host
null)) // fragment
.Returns(expectedAction) .Returns(expectedAction)
.Verifiable(); .Verifiable();
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(urlHelper.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(urlHelper.Object);
@ -221,12 +219,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
var urlHelper = new Mock<IUrlHelper>(MockBehavior.Strict); var urlHelper = new Mock<IUrlHelper>(MockBehavior.Strict);
urlHelper urlHelper
.Setup(realHelper => realHelper.RouteUrl( .Setup(realHelper => realHelper.RouteUrl(It.Is<UrlRouteContext>(context =>
routeName, string.Equals(context.RouteName, routeName) &&
routeValues, context.Values == routeValues &&
null, // protocol context.Protocol == null &&
null, // host context.Host == null &&
null)) // fragment context.Fragment == null)))
.Returns(expectedAction) .Returns(expectedAction)
.Verifiable(); .Verifiable();
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(urlHelper.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(urlHelper.Object);

View File

@ -55,23 +55,15 @@ namespace Microsoft.AspNet.Mvc.Rendering
GetHtmlAttributesAsString(htmlAttributes)); GetHtmlAttributesAsString(htmlAttributes));
var urlHelper = new Mock<IUrlHelper>(); var urlHelper = new Mock<IUrlHelper>();
urlHelper.Setup( urlHelper.Setup(h => h.Action(It.IsAny<UrlActionContext>()))
h => h.Action( .Returns<UrlActionContext>((actionContext) =>
It.IsAny<string>(), string.Format("{0}{1}{2}{3}{4}{5}",
It.IsAny<string>(), actionContext.Protocol,
It.IsAny<object>(), actionContext.Host,
It.IsAny<string>(), actionContext.Controller,
It.IsAny<string>(), actionContext.Action,
It.IsAny<string>())) GetRouteValuesAsString(actionContext.Values),
.Returns<string, string, object, string, string, string>( actionContext.Fragment));
(actn, cntrlr, rvalues, prtcl, hname, frgmt) =>
string.Format("{0}{1}{2}{3}{4}{5}",
prtcl,
hname,
cntrlr,
actn,
GetRouteValuesAsString(rvalues),
frgmt));
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(urlHelper.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(urlHelper.Object);
@ -129,19 +121,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
var urlHelper = new Mock<IUrlHelper>(); var urlHelper = new Mock<IUrlHelper>();
urlHelper urlHelper
.Setup( .Setup(
h => h.RouteUrl( h => h.RouteUrl(It.IsAny<UrlRouteContext>())).Returns<UrlRouteContext>((context) =>
It.IsAny<string>(),
It.IsAny<object>(),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>()))
.Returns<string, object, string, string, string>(
(rname, rvalues, prtcl, hname, frgmt) =>
string.Format("{0}{1}{2}{3}", string.Format("{0}{1}{2}{3}",
prtcl, context.Protocol,
hname, context.Host,
GetRouteValuesAsString(rvalues), GetRouteValuesAsString(context.Values),
frgmt)); context.Fragment));
var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(urlHelper.Object); var htmlHelper = DefaultTemplatesUtilities.GetHtmlHelper(urlHelper.Object);

View File

@ -59,8 +59,8 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal(expectedPath, path); Assert.Equal(expectedPath, path);
} }
// UrlHelper.IsLocalUrl depends on the UrlUtility.IsLocalUrl method. // UrlHelper.IsLocalUrl depends on the UrlUtility.IsLocalUrl method.
// To avoid duplicate tests, all the tests exercising IsLocalUrl verify // To avoid duplicate tests, all the tests exercising IsLocalUrl verify
// both of UrlHelper.IsLocalUrl and UrlUtility.IsLocalUrl // both of UrlHelper.IsLocalUrl and UrlUtility.IsLocalUrl
[Theory] [Theory]
[InlineData(null)] [InlineData(null)]
@ -543,6 +543,56 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal("/app/named/home2/newaction/someid", url); 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] [Fact]
public void UrlAction_RouteValuesAsDictionary_CaseSensitive() public void UrlAction_RouteValuesAsDictionary_CaseSensitive()
{ {
@ -616,6 +666,49 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal("/app/named/home/contact/suppliedid", url); 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) private static HttpContext CreateHttpContext(string appRoot, ILoggerFactory factory = null)
{ {
if (factory == null) if (factory == null)

View File

@ -47,14 +47,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var urlHelper = new Mock<IUrlHelper>(); var urlHelper = new Mock<IUrlHelper>();
urlHelper urlHelper
.Setup(mock => mock.Action( .Setup(mock => mock.Action(It.IsAny<UrlActionContext>())).Returns("home/index");
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<object>(),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>()))
.Returns("home/index");
var htmlGenerator = new TestableHtmlGenerator(metadataProvider, urlHelper.Object); var htmlGenerator = new TestableHtmlGenerator(metadataProvider, urlHelper.Object);
var viewContext = TestableHtmlGenerator.GetViewContext(model: null, var viewContext = TestableHtmlGenerator.GetViewContext(model: null,

View File

@ -47,13 +47,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}; };
var urlHelper = new Mock<IUrlHelper>(); var urlHelper = new Mock<IUrlHelper>();
urlHelper urlHelper
.Setup(mock => mock.Action(It.IsAny<string>(), .Setup(mock => mock.Action(It.IsAny<UrlActionContext>())).Returns("home/index");
It.IsAny<string>(),
It.IsAny<object>(),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>()))
.Returns("home/index");
var htmlGenerator = new TestableHtmlGenerator(metadataProvider, urlHelper.Object); var htmlGenerator = new TestableHtmlGenerator(metadataProvider, urlHelper.Object);
var viewContext = TestableHtmlGenerator.GetViewContext(model: null, var viewContext = TestableHtmlGenerator.GetViewContext(model: null,

View File

@ -46,14 +46,14 @@ namespace UrlHelperWebSite
return ConvertToLowercaseUrl(base.Content(contentPath)); 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) private string ConvertToLowercaseUrl(string url)