This is a companion change to make the RouteValueDictionary type more
promient. Using the concrete type here allows to avoid allocations in a
lot of common scenarios.
This commit is contained in:
Ryan Nowak 2015-11-24 15:51:06 -08:00
parent 6e299d695f
commit 4bcf236450
8 changed files with 54 additions and 34 deletions

View File

@ -2,11 +2,10 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Internal;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
@ -33,7 +32,7 @@ namespace Microsoft.AspNet.Mvc
{ {
ActionName = actionName; ActionName = actionName;
ControllerName = controllerName; ControllerName = controllerName;
RouteValues = PropertyHelper.ObjectToDictionary(routeValues); RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues);
StatusCode = StatusCodes.Status201Created; StatusCode = StatusCodes.Status201Created;
} }
@ -55,7 +54,7 @@ namespace Microsoft.AspNet.Mvc
/// <summary> /// <summary>
/// Gets or sets the route data to use for generating the URL. /// Gets or sets the route data to use for generating the URL.
/// </summary> /// </summary>
public IDictionary<string, object> RouteValues { get; set; } public RouteValueDictionary RouteValues { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public override void OnFormatting(ActionContext context) public override void OnFormatting(ActionContext context)

View File

@ -2,11 +2,10 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Internal;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
@ -41,7 +40,7 @@ namespace Microsoft.AspNet.Mvc
: base(value) : base(value)
{ {
RouteName = routeName; RouteName = routeName;
RouteValues = PropertyHelper.ObjectToDictionary(routeValues); RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues);
StatusCode = StatusCodes.Status201Created; StatusCode = StatusCodes.Status201Created;
} }
@ -58,7 +57,7 @@ namespace Microsoft.AspNet.Mvc
/// <summary> /// <summary>
/// Gets or sets the route data to use for generating the URL. /// Gets or sets the route data to use for generating the URL.
/// </summary> /// </summary>
public IDictionary<string, object> RouteValues { get; set; } public RouteValueDictionary RouteValues { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public override void OnFormatting(ActionContext context) public override void OnFormatting(ActionContext context)

View File

@ -2,10 +2,10 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.Logging; using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Mvc.ViewFeatures; using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -16,7 +16,7 @@ namespace Microsoft.AspNet.Mvc
public RedirectToActionResult( public RedirectToActionResult(
string actionName, string actionName,
string controllerName, string controllerName,
IDictionary<string, object> routeValues) object routeValues)
: this(actionName, controllerName, routeValues, permanent: false) : this(actionName, controllerName, routeValues, permanent: false)
{ {
} }
@ -24,25 +24,38 @@ namespace Microsoft.AspNet.Mvc
public RedirectToActionResult( public RedirectToActionResult(
string actionName, string actionName,
string controllerName, string controllerName,
IDictionary<string, object> routeValues, object routeValues,
bool permanent) bool permanent)
{ {
ActionName = actionName; ActionName = actionName;
ControllerName = controllerName; ControllerName = controllerName;
RouteValues = routeValues; RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues);
Permanent = permanent; Permanent = permanent;
} }
/// <summary>
/// Gets or sets the <see cref="IUrlHelper" /> used to generate URLs.
/// </summary>
public IUrlHelper UrlHelper { get; set; } public IUrlHelper UrlHelper { get; set; }
/// <summary>
/// Gets or sets the name of the action to use for generating the URL.
/// </summary>
public string ActionName { get; set; } public string ActionName { get; set; }
/// <summary>
/// Gets or sets the name of the controller to use for generating the URL.
/// </summary>
public string ControllerName { get; set; } public string ControllerName { get; set; }
public IDictionary<string, object> RouteValues { get; set; } /// <summary>
/// Gets or sets the route data to use for generating the URL.
/// </summary>
public RouteValueDictionary RouteValues { get; set; }
public bool Permanent { get; set; } public bool Permanent { get; set; }
/// <inheritdoc />
public override void ExecuteResult(ActionContext context) public override void ExecuteResult(ActionContext context)
{ {
if (context == null) if (context == null)

View File

@ -2,12 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc.Core; using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.Logging; using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Mvc.ViewFeatures; using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
@ -32,18 +31,28 @@ namespace Microsoft.AspNet.Mvc
bool permanent) bool permanent)
{ {
RouteName = routeName; RouteName = routeName;
RouteValues = PropertyHelper.ObjectToDictionary(routeValues); RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues);
Permanent = permanent; Permanent = permanent;
} }
/// <summary>
/// Gets or sets the <see cref="IUrlHelper" /> used to generate URLs.
/// </summary>
public IUrlHelper UrlHelper { get; set; } public IUrlHelper UrlHelper { get; set; }
/// <summary>
/// Gets or sets the name of the route to use for generating the URL.
/// </summary>
public string RouteName { get; set; } public string RouteName { get; set; }
public IDictionary<string, object> RouteValues { get; set; } /// <summary>
/// Gets or sets the route data to use for generating the URL.
/// </summary>
public RouteValueDictionary RouteValues { get; set; }
public bool Permanent { get; set; } public bool Permanent { get; set; }
/// <inheritdoc />
public override void ExecuteResult(ActionContext context) public override void ExecuteResult(ActionContext context)
{ {
if (context == null) if (context == null)

View File

@ -30,7 +30,7 @@ namespace Microsoft.AspNet.Mvc.Routing
_actionContextAccessor = actionContextAccessor; _actionContextAccessor = actionContextAccessor;
} }
protected IDictionary<string, object> AmbientValues => ActionContext.RouteData.Values; protected RouteValueDictionary AmbientValues => ActionContext.RouteData.Values;
protected ActionContext ActionContext => _actionContextAccessor.ActionContext; protected ActionContext ActionContext => _actionContextAccessor.ActionContext;
@ -46,7 +46,7 @@ namespace Microsoft.AspNet.Mvc.Routing
throw new ArgumentNullException(nameof(actionContext)); throw new ArgumentNullException(nameof(actionContext));
} }
var valuesDictionary = PropertyHelper.ObjectToDictionary(actionContext.Values); var valuesDictionary = new RouteValueDictionary(actionContext.Values);
if (actionContext.Action == null) if (actionContext.Action == null)
{ {
@ -106,7 +106,7 @@ namespace Microsoft.AspNet.Mvc.Routing
throw new ArgumentNullException(nameof(routeContext)); throw new ArgumentNullException(nameof(routeContext));
} }
var valuesDictionary = PropertyHelper.ObjectToDictionary(routeContext.Values); var valuesDictionary = new RouteValueDictionary(routeContext.Values);
var path = GeneratePathFromRoute(routeContext.RouteName, valuesDictionary); var path = GeneratePathFromRoute(routeContext.RouteName, valuesDictionary);
if (path == null) if (path == null)
@ -117,7 +117,7 @@ namespace Microsoft.AspNet.Mvc.Routing
return GenerateUrl(routeContext.Protocol, routeContext.Host, path, routeContext.Fragment); return GenerateUrl(routeContext.Protocol, routeContext.Host, path, routeContext.Fragment);
} }
private string GeneratePathFromRoute(IDictionary<string, object> values) private string GeneratePathFromRoute(RouteValueDictionary values)
{ {
return GeneratePathFromRoute(routeName: null, values: values); return GeneratePathFromRoute(routeName: null, values: values);
} }
@ -129,7 +129,7 @@ namespace Microsoft.AspNet.Mvc.Routing
/// <param name="routeName">The name of the route that is used to generate the URL.</param> /// <param name="routeName">The name of the route that is used to generate the URL.</param>
/// <param name="values">A dictionary that contains the parameters for a route.</param> /// <param name="values">A dictionary that contains the parameters for a route.</param>
/// <returns>The absolute path of the URL.</returns> /// <returns>The absolute path of the URL.</returns>
protected virtual string GeneratePathFromRoute(string routeName, IDictionary<string, object> values) protected virtual string GeneratePathFromRoute(string routeName, RouteValueDictionary values)
{ {
var context = new VirtualPathContext(HttpContext, AmbientValues, values, routeName); var context = new VirtualPathContext(HttpContext, AmbientValues, values, routeName);
var pathData = Router.GetVirtualPath(context); var pathData = Router.GetVirtualPath(context);

View File

@ -706,7 +706,7 @@ namespace Microsoft.AspNet.Mvc
string controllerName, string controllerName,
object routeValues) object routeValues)
{ {
return new RedirectToActionResult(actionName, controllerName, PropertyHelper.ObjectToDictionary(routeValues)) return new RedirectToActionResult(actionName, controllerName, routeValues)
{ {
UrlHelper = Url, UrlHelper = Url,
}; };
@ -768,7 +768,7 @@ namespace Microsoft.AspNet.Mvc
return new RedirectToActionResult( return new RedirectToActionResult(
actionName, actionName,
controllerName, controllerName,
PropertyHelper.ObjectToDictionary(routeValues), routeValues,
permanent: true) permanent: true)
{ {
UrlHelper = Url, UrlHelper = Url,
@ -1101,7 +1101,7 @@ namespace Microsoft.AspNet.Mvc
/// </summary> /// </summary>
/// <param name="actionName">The name of the action to use for generating the URL.</param> /// <param name="actionName">The name of the action to use for generating the URL.</param>
/// <param name="value">The content value to format in the entity body.</param> /// <param name="value">The content value to format in the entity body.</param>
/// <returns>The created <see cref="CreatedAtRouteResult"/> for the response.</returns> /// <returns>The created <see cref="CreatedAtActionResult"/> for the response.</returns>
[NonAction] [NonAction]
public virtual CreatedAtActionResult CreatedAtAction(string actionName, object value) public virtual CreatedAtActionResult CreatedAtAction(string actionName, object value)
{ {
@ -1114,7 +1114,7 @@ namespace Microsoft.AspNet.Mvc
/// <param name="actionName">The name of the action to use for generating the URL.</param> /// <param name="actionName">The name of the action to use for generating the URL.</param>
/// <param name="routeValues">The route data to use for generating the URL.</param> /// <param name="routeValues">The route data to use for generating the URL.</param>
/// <param name="value">The content value to format in the entity body.</param> /// <param name="value">The content value to format in the entity body.</param>
/// <returns>The created <see cref="CreatedAtRouteResult"/> for the response.</returns> /// <returns>The created <see cref="CreatedAtActionResult"/> for the response.</returns>
[NonAction] [NonAction]
public virtual CreatedAtActionResult CreatedAtAction(string actionName, object routeValues, object value) public virtual CreatedAtActionResult CreatedAtAction(string actionName, object routeValues, object value)
{ {
@ -1128,7 +1128,7 @@ namespace Microsoft.AspNet.Mvc
/// <param name="controllerName">The name of the controller to use for generating the URL.</param> /// <param name="controllerName">The name of the controller to use for generating the URL.</param>
/// <param name="routeValues">The route data to use for generating the URL.</param> /// <param name="routeValues">The route data to use for generating the URL.</param>
/// <param name="value">The content value to format in the entity body.</param> /// <param name="value">The content value to format in the entity body.</param>
/// <returns>The created <see cref="CreatedAtRouteResult"/> for the response.</returns> /// <returns>The created <see cref="CreatedAtActionResult"/> for the response.</returns>
[NonAction] [NonAction]
public virtual CreatedAtActionResult CreatedAtAction( public virtual CreatedAtActionResult CreatedAtAction(
string actionName, string actionName,

View File

@ -1192,13 +1192,13 @@ namespace Microsoft.AspNet.Mvc.Test
yield return new object[] yield return new object[]
{ {
null, null,
Enumerable.Empty<KeyValuePair<string, object>>() null,
}; };
yield return new object[] yield return new object[]
{ {
new Dictionary<string, object> { { "hello", "world" } }, new Dictionary<string, object> { { "hello", "world" } },
new[] { new KeyValuePair<string, object>("hello", "world") } new RouteValueDictionary() { { "hello", "world" } },
}; };
var expected2 = new Dictionary<string, object> var expected2 = new Dictionary<string, object>
@ -1210,7 +1210,7 @@ namespace Microsoft.AspNet.Mvc.Test
yield return new object[] yield return new object[]
{ {
new RouteValueDictionary(expected2), new RouteValueDictionary(expected2),
expected2 new RouteValueDictionary(expected2),
}; };
} }
} }

View File

@ -345,7 +345,7 @@ namespace Microsoft.AspNet.Mvc
createdAtRouteResult = Assert.IsType<CreatedAtRouteResult>(result); createdAtRouteResult = Assert.IsType<CreatedAtRouteResult>(result);
Assert.Null(createdAtRouteResult.RouteName); Assert.Null(createdAtRouteResult.RouteName);
Assert.Empty(createdAtRouteResult.RouteValues); Assert.Null(createdAtRouteResult.RouteValues);
Assert.Null(createdAtRouteResult.Value); Assert.Null(createdAtRouteResult.Value);
} }
@ -385,7 +385,7 @@ namespace Microsoft.AspNet.Mvc
Assert.Null(createdAtActionResult.ActionName); Assert.Null(createdAtActionResult.ActionName);
Assert.Null(createdAtActionResult.ControllerName); Assert.Null(createdAtActionResult.ControllerName);
Assert.Null(createdAtActionResult.Value); Assert.Null(createdAtActionResult.Value);
Assert.Empty(createdAtActionResult.RouteValues); Assert.Null(createdAtActionResult.RouteValues);
} }
[Fact] [Fact]
@ -418,7 +418,7 @@ namespace Microsoft.AspNet.Mvc
redirectToRouteResult = Assert.IsType<RedirectToRouteResult>(result); redirectToRouteResult = Assert.IsType<RedirectToRouteResult>(result);
Assert.Null(redirectToRouteResult.RouteName); Assert.Null(redirectToRouteResult.RouteName);
Assert.Empty(redirectToRouteResult.RouteValues); Assert.Null(redirectToRouteResult.RouteValues);
} }
[Fact] [Fact]
@ -454,7 +454,7 @@ namespace Microsoft.AspNet.Mvc
redirectToActionResult = Assert.IsType<RedirectToActionResult>(result); redirectToActionResult = Assert.IsType<RedirectToActionResult>(result);
Assert.Null(redirectToActionResult.ControllerName); Assert.Null(redirectToActionResult.ControllerName);
Assert.Null(redirectToActionResult.ActionName); Assert.Null(redirectToActionResult.ActionName);
Assert.Empty(redirectToActionResult.RouteValues); Assert.Null(redirectToActionResult.RouteValues);
} }
[Fact] [Fact]