Simplify parameter transformer usage

This commit is contained in:
Ryan Nowak 2018-11-20 11:21:46 -08:00
parent a04dd4877c
commit c9887e027a
10 changed files with 44 additions and 31 deletions

View File

@ -50,6 +50,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
ActionMethod = other.ActionMethod;
ActionName = other.ActionName;
RouteParameterTransformer = other.RouteParameterTransformer;
// Not making a deep copy of the controller, this action still belongs to the same controller.
Controller = other.Controller;
@ -93,6 +94,18 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
public IList<ParameterModel> Parameters { get; }
/// <summary>
/// Gets or sets an <see cref="IOutboundParameterTransformer"/> that will be used to transform
/// built-in route parameters such as <c>action</c>, <c>controller</c>, and <c>area</c> as well as
/// additional parameters specified by <see cref="RouteValues"/> into static segments in the route template.
/// </summary>
/// <remarks>
/// <para>
/// This feature only applies when using endpoint routing.
/// </para>
/// </remarks>
public IOutboundParameterTransformer RouteParameterTransformer { get; set; }
/// <summary>
/// Gets a collection of route values that must be present in the
/// <see cref="RouteData.Values"/> for the corresponding action to be selected.

View File

@ -159,20 +159,17 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
routeValues.TryAdd(kvp.Key, kvp.Value);
}
action.Properties.TryGetValue(typeof(IOutboundParameterTransformer), out var obj);
var transformer = obj as IOutboundParameterTransformer;
selector.AttributeRouteModel.Template = AttributeRouteModel.ReplaceTokens(
selector.AttributeRouteModel.Template,
routeValues,
transformer);
action.RouteParameterTransformer);
if (selector.AttributeRouteModel.Name != null)
{
selector.AttributeRouteModel.Name = AttributeRouteModel.ReplaceTokens(
selector.AttributeRouteModel.Name,
routeValues,
transformer);
action.RouteParameterTransformer);
}
}
catch (InvalidOperationException ex)

View File

@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
{
if (ShouldApply(action))
{
action.Properties[typeof(IOutboundParameterTransformer)] = _parameterTransformer;
action.RouteParameterTransformer = _parameterTransformer;
}
}

View File

@ -55,6 +55,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
RelativePath = other.RelativePath;
ViewEnginePath = other.ViewEnginePath;
AreaName = other.AreaName;
RouteParameterTransformer = other.RouteParameterTransformer;
Properties = new Dictionary<object, object>(other.Properties);
Selectors = new List<SelectorModel>(other.Selectors.Select(m => new SelectorModel(m)));
@ -113,5 +114,17 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
/// </para>
/// </remarks>
public IDictionary<string, string> RouteValues { get; }
/// <summary>
/// Gets or sets an <see cref="IOutboundParameterTransformer"/> that will be used to transform
/// built-in route parameters such as <c>action</c>, <c>controller</c>, and <c>area</c> as well as
/// additional parameters specified by <see cref="RouteValues"/> into static segments in the route template.
/// </summary>
/// <remarks>
/// <para>
/// This feature only applies when using endpoint routing.
/// </para>
/// </remarks>
public IOutboundParameterTransformer RouteParameterTransformer { get; set; }
}
}

View File

@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
{
if (ShouldApply(model))
{
model.Properties[typeof(IOutboundParameterTransformer)] = _parameterTransformer;
model.RouteParameterTransformer = _parameterTransformer;
}
}

View File

@ -113,11 +113,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
private static string TransformPageRoute(PageRouteModel model, SelectorModel selectorModel)
{
model.Properties.TryGetValue(typeof(IOutboundParameterTransformer), out var transformer);
var pageRouteTransformer = transformer as IOutboundParameterTransformer;
// Transformer not set on page route
if (pageRouteTransformer == null)
if (model.RouteParameterTransformer == null)
{
return selectorModel.AttributeRouteModel.Template;
}
@ -134,7 +131,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
var segments = pageRouteMetadata.PageRoute.Split('/');
for (var i = 0; i < segments.Length; i++)
{
segments[i] = pageRouteTransformer.TransformOutbound(segments[i]);
segments[i] = model.RouteParameterTransformer.TransformOutbound(segments[i]);
}
var transformedPageRoute = string.Join("/", segments);

View File

@ -7,6 +7,8 @@ using System.Reflection;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Routing;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.ApplicationModels
@ -75,6 +77,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
(typeof(TestController).GetTypeInfo(),
new List<object>());
action.Filters.Add(new MyFilterAttribute());
action.RouteParameterTransformer = Mock.Of<IOutboundParameterTransformer>();
action.RouteValues.Add("key", "value");
action.Properties.Add(new KeyValuePair<object, object>("test key", "test value"));

View File

@ -3,11 +3,10 @@
using System;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Routing;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Test.ApplicationModels
namespace Microsoft.AspNetCore.Mvc.ApplicationModels
{
public class RouteTokenTransformerConventionTest
{
@ -28,8 +27,7 @@ namespace Microsoft.AspNetCore.Mvc.Test.ApplicationModels
convention.Apply(model);
// Assert
Assert.True(model.Properties.TryGetValue(typeof(IOutboundParameterTransformer), out var routeTokenTransformer));
Assert.Equal(transformer, routeTokenTransformer);
Assert.Same(transformer, model.RouteParameterTransformer);
}
[Fact]
@ -49,7 +47,7 @@ namespace Microsoft.AspNetCore.Mvc.Test.ApplicationModels
convention.Apply(model);
// Assert
Assert.False(model.Properties.TryGetValue(typeof(IOutboundParameterTransformer), out _));
Assert.Null(model.RouteParameterTransformer);
}
private MethodInfo GetMethodInfo()

View File

@ -24,8 +24,7 @@ namespace Microsoft.AspNetCore.Mvc.Test.ApplicationModels
convention.Apply(model);
// Assert
Assert.True(model.Properties.TryGetValue(typeof(IOutboundParameterTransformer), out var routeTokenTransformer));
Assert.Equal(transformer, routeTokenTransformer);
Assert.Same(transformer, model.RouteParameterTransformer);
}
[Fact]
@ -41,7 +40,7 @@ namespace Microsoft.AspNetCore.Mvc.Test.ApplicationModels
convention.Apply(model);
// Assert
Assert.False(model.Properties.TryGetValue(typeof(IOutboundParameterTransformer), out _));
Assert.Null(model.RouteParameterTransformer);
}
private class TestParameterTransformer : IOutboundParameterTransformer

View File

@ -8,12 +8,12 @@ using Microsoft.AspNetCore.Routing;
namespace RoutingWebSite
{
public class ControllerRouteTokenTransformerConvention : IApplicationModelConvention
public class ControllerRouteTokenTransformerConvention : RouteTokenTransformerConvention
{
private readonly Type _controllerType;
private readonly IOutboundParameterTransformer _parameterTransformer;
public ControllerRouteTokenTransformerConvention(Type controllerType, IOutboundParameterTransformer parameterTransformer)
: base(parameterTransformer)
{
if (parameterTransformer == null)
{
@ -21,18 +21,11 @@ namespace RoutingWebSite
}
_controllerType = controllerType;
_parameterTransformer = parameterTransformer;
}
public void Apply(ApplicationModel application)
protected override bool ShouldApply(ActionModel action)
{
foreach (var controller in application.Controllers.Where(c => c.ControllerType == _controllerType))
{
foreach (var action in controller.Actions)
{
action.Properties[typeof(IOutboundParameterTransformer)] = _parameterTransformer;
}
}
return action.Controller.ControllerType == _controllerType;
}
}
}