Reacting to Routing changes

This commit is contained in:
Pranav K 2015-12-16 11:49:20 -08:00
parent e8ab079b06
commit 7c40759e32
13 changed files with 79 additions and 63 deletions

View File

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Abstractions;
using Microsoft.AspNet.Mvc.Core;
@ -20,6 +21,7 @@ namespace Microsoft.AspNet.Mvc.Routing
private readonly IRouter _target;
private readonly IActionDescriptorsCollectionProvider _actionDescriptorsCollectionProvider;
private readonly IInlineConstraintResolver _constraintResolver;
private readonly UrlEncoder _urlEncoder;
private readonly ILoggerFactory _loggerFactory;
private TreeRouter _router;
@ -28,6 +30,7 @@ namespace Microsoft.AspNet.Mvc.Routing
IRouter target,
IActionDescriptorsCollectionProvider actionDescriptorsCollectionProvider,
IInlineConstraintResolver constraintResolver,
UrlEncoder urlEncoder,
ILoggerFactory loggerFactory)
{
if (target == null)
@ -45,6 +48,11 @@ namespace Microsoft.AspNet.Mvc.Routing
throw new ArgumentNullException(nameof(constraintResolver));
}
if (urlEncoder == null)
{
throw new ArgumentNullException(nameof(urlEncoder));
}
if (loggerFactory == null)
{
throw new ArgumentNullException(nameof(loggerFactory));
@ -53,6 +61,7 @@ namespace Microsoft.AspNet.Mvc.Routing
_target = target;
_actionDescriptorsCollectionProvider = actionDescriptorsCollectionProvider;
_constraintResolver = constraintResolver;
_urlEncoder = urlEncoder;
_loggerFactory = loggerFactory;
}
@ -95,7 +104,7 @@ namespace Microsoft.AspNet.Mvc.Routing
{
routeBuilder.Add(new TreeRouteLinkGenerationEntry()
{
Binder = new TemplateBinder(routeInfo.ParsedTemplate, routeInfo.Defaults),
Binder = new TemplateBinder(routeInfo.ParsedTemplate, _urlEncoder, routeInfo.Defaults),
Defaults = routeInfo.Defaults,
Constraints = routeInfo.Constraints,
Order = routeInfo.Order,

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Text.Encodings.Web;
using Microsoft.AspNet.Mvc.Infrastructure;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection;
@ -31,9 +32,15 @@ namespace Microsoft.AspNet.Mvc.Routing
var actionDescriptorProvider = services.GetRequiredService<IActionDescriptorsCollectionProvider>();
var inlineConstraintResolver = services.GetRequiredService<IInlineConstraintResolver>();
var urlEncoder = services.GetRequiredService<UrlEncoder>();
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
return new AttributeRoute(target, actionDescriptorProvider, inlineConstraintResolver, loggerFactory);
return new AttributeRoute(
target,
actionDescriptorProvider,
inlineConstraintResolver,
urlEncoder,
loggerFactory);
}
}
}

View File

@ -12,6 +12,7 @@ using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Routing.Tree;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.WebEncoders.Testing;
using Moq;
using Xunit;
@ -70,6 +71,7 @@ namespace Microsoft.AspNet.Mvc.Routing
handler.Object,
actionDescriptorsProvider.Object,
Mock.Of<IInlineConstraintResolver>(),
new UrlTestEncoder(),
NullLoggerFactory.Instance);
var requestServices = new Mock<IServiceProvider>(MockBehavior.Strict);

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Text.Encodings.Web;
#if DNXCORE50
using System.Reflection;
#endif
@ -13,9 +14,11 @@ using Microsoft.AspNet.Mvc.Controllers;
using Microsoft.AspNet.Mvc.Infrastructure;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Routing.Tree;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.OptionsModel;
using Microsoft.Extensions.WebEncoders.Testing;
using Moq;
using Xunit;
@ -184,25 +187,17 @@ namespace Microsoft.AspNet.Mvc.Routing
.Setup(a => a.ActionDescriptors)
.Returns(collection);
var services = new Mock<IServiceProvider>();
services
.Setup(s => s.GetService(typeof(IActionDescriptorsCollectionProvider)))
.Returns(actionDescriptorProvider.Object);
var routeOptions = new Mock<IOptions<RouteOptions>>();
routeOptions
.SetupGet(o => o.Value)
.Returns(new RouteOptions());
services
.Setup(s => s.GetService(typeof(IInlineConstraintResolver)))
.Returns(new DefaultInlineConstraintResolver(routeOptions.Object));
services
.Setup(s => s.GetService(typeof(ILoggerFactory)))
.Returns(NullLoggerFactory.Instance);
return services.Object;
return new ServiceCollection()
.AddSingleton(actionDescriptorProvider.Object)
.AddSingleton<IInlineConstraintResolver>(new DefaultInlineConstraintResolver(routeOptions.Object))
.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance)
.AddSingleton<UrlEncoder>(new UrlTestEncoder())
.BuildServiceProvider();
}
private class DisplayNameActionDescriptor : ActionDescriptor

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
@ -14,6 +15,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.OptionsModel;
using Microsoft.Extensions.WebEncoders.Testing;
using Moq;
using Xunit;
@ -951,6 +953,7 @@ namespace Microsoft.AspNet.Mvc.Routing
var services = new ServiceCollection();
services.AddLogging();
services.AddRouting();
services.AddSingleton<UrlEncoder>(UrlEncoder.Default);
return services.BuildServiceProvider();
}
@ -980,13 +983,15 @@ namespace Microsoft.AspNet.Mvc.Routing
.Returns<VirtualPathContext>(context => null);
routeBuilder.DefaultHandler = target.Object;
routeBuilder.MapRoute(string.Empty,
"{controller}/{action}/{id}",
new RouteValueDictionary(new { id = "defaultid" }));
routeBuilder.MapRoute(
string.Empty,
"{controller}/{action}/{id}",
new RouteValueDictionary(new { id = "defaultid" }));
routeBuilder.MapRoute("namedroute",
"named/{controller}/{action}/{id}",
new RouteValueDictionary(new { id = "defaultid" }));
routeBuilder.MapRoute(
"namedroute",
"named/{controller}/{action}/{id}",
new RouteValueDictionary(new { id = "defaultid" }));
var mockHttpRoute = new Mock<IRouter>();
mockHttpRoute

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
@ -14,18 +13,6 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
{
public static string RetrieveAntiforgeryToken(string htmlContent, string actionUrl)
{
return RetrieveAntiforgeryTokens(
htmlContent,
attribute => attribute.Value.EndsWith(actionUrl, StringComparison.OrdinalIgnoreCase) ||
attribute.Value.EndsWith($"HtmlEncode[[{ actionUrl }]]", StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();
}
public static IEnumerable<string> RetrieveAntiforgeryTokens(
string htmlContent,
Func<XAttribute, bool> predicate = null)
{
predicate = predicate ?? (_ => true);
htmlContent = "<Root>" + htmlContent + "</Root>";
var reader = new StringReader(htmlContent);
var htmlDocument = XDocument.Load(reader);
@ -34,8 +21,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
{
foreach (var attribute in form.Attributes())
{
if (string.Equals(attribute.Name.LocalName, "action", StringComparison.OrdinalIgnoreCase)
&& predicate(attribute))
if (string.Equals(attribute.Name.LocalName, "action", StringComparison.OrdinalIgnoreCase))
{
foreach (var input in form.Descendants("input"))
{
@ -45,12 +31,14 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
(input.Attribute("name").Value == "__RequestVerificationToken" ||
input.Attribute("name").Value == "HtmlEncode[[__RequestVerificationToken]]"))
{
yield return input.Attributes("value").First().Value;
return input.Attributes("value").First().Value;
}
}
}
}
}
throw new Exception($"Antiforgery token could not be located in {htmlContent}.");
}
public static CookieMetadata RetrieveAntiforgeryCookie(HttpResponseMessage response)

View File

@ -491,7 +491,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
"GetProductByManufacturingDate",
"dateTime",
"2014-10-11T13:45:30",
"/products/GetProductByManufacturingDate/2014-10-11T13%3a45%3a30"
"/products/GetProductByManufacturingDate/2014-10-11T13%3A45%3A30"
};
// Conventional Route, id:guid? constraint

View File

@ -1,6 +1,6 @@
<html>
<body>
<form action="HtmlEncode[[/HtmlGeneration_Home/EditWarehouse]]" method="HtmlEncode[[post]]">
<form action="HtmlEncode[[/UrlEncode[[HtmlGeneration_Home]]/UrlEncode[[EditWarehouse]]]]" method="HtmlEncode[[post]]">
<div>
HtmlEncode[[City_1]]
<input type="HtmlEncode[[text]]" data-val="HtmlEncode[[true]]" data-val-minlength="HtmlEncode[[The field City must be a string or array type with a minimum length of '2'.]]" data-val-minlength-min="HtmlEncode[[2]]" id="HtmlEncode[[City]]" name="HtmlEncode[[City]]" value="HtmlEncode[[City_1]]" />

View File

@ -1,10 +1,10 @@
<html>
<body>
<div>
<a title="&lt;the title>" href="HtmlEncode[[/HtmlGeneration_Product]]">Product Index</a>
<a title="&lt;the title>" href="HtmlEncode[[/UrlEncode[[HtmlGeneration_Product]]]]">Product Index</a>
</div>
<div>
<a title="&quot;the&quot; title" href="HtmlEncode[[/HtmlGeneration_Product/List]]">Product List</a>
<a title="&quot;the&quot; title" href="HtmlEncode[[/UrlEncode[[HtmlGeneration_Product]]/UrlEncode[[List]]]]">Product List</a>
</div>
<div>
<a id="HtmlGenerationWebSite_Index">HtmlGenerationWebSite Index</a>
@ -13,10 +13,10 @@
<a href="HtmlEncode[[/]]">Default Controller</a>
</div>
<div>
<a href="HtmlEncode[[/Product/Index#fragment]]">Product Index Fragment</a>
<a href="HtmlEncode[[/UrlEncode[[Product]]/UrlEncode[[Index]]#fragment]]">Product Index Fragment</a>
</div>
<div>
<a href="HtmlEncode[[/HtmlGeneration_Product/Submit#fragment]]">Product Submit Fragment</a>
<a href="HtmlEncode[[/UrlEncode[[HtmlGeneration_Product]]/UrlEncode[[Submit]]#fragment]]">Product Submit Fragment</a>
</div>
<div>
<a id="HtmlGenerationWebSite_IndexFragment" href="HtmlEncode[[/#fragment]]">
@ -29,7 +29,7 @@
</a>
</div>
<div>
<a href="HtmlEncode[[unkonwn://localhost/HtmlGeneration_Product/List]]">
<a href="HtmlEncode[[unkonwn://localhost/UrlEncode[[HtmlGeneration_Product]]/UrlEncode[[List]]]]">
Unknown Protocol Product List
</a>
</div>
@ -39,32 +39,32 @@
</a>
</div>
<div>
<a href="HtmlEncode[[/Customer/Customer#fragment]]">Customer Area Customer Index</a>
<a href="HtmlEncode[[/UrlEncode[[Customer]]/UrlEncode[[Customer]]#fragment]]">Customer Area Customer Index</a>
</div>
<div>
<a href="/Order/List">Href Order List</a>
</div>
<div>
<a href="HtmlEncode[[/NonExistentController]]">Non-existent Controller</a>
<a href="HtmlEncode[[/UrlEncode[[NonExistentController]]]]">Non-existent Controller</a>
</div>
<div>
<a href="HtmlEncode[[/NonExistentController#fragment]]">
<a href="HtmlEncode[[/UrlEncode[[NonExistentController]]#fragment]]">
Non-existent Controller Fragment
</a>
</div>
<div>
<a href="HtmlEncode[[/Order/NonExistentAction]]">Non-existent Action</a>
<a href="HtmlEncode[[/UrlEncode[[Order]]/UrlEncode[[NonExistentAction]]]]">Non-existent Action</a>
</div>
<div>
<a id="Id" href="HtmlEncode[[http://somewhere/]]">Some Where</a>
</div>
<div>
<a href="HtmlEncode[[unknown://localhost/NoControll#fragment]]">
<a href="HtmlEncode[[unknown://localhost/UrlEncode[[NoControll]]#fragment]]">
Unknown Protocol Non-existent Controller Fragment
</a>
</div>
<div>
<a href="HtmlEncode[[/Product/Submit?area=NonExistentArea&id=1#fragment]]">Product Route Non-existent Area Parameter</a>
<a href="HtmlEncode[[/UrlEncode[[Product]]/UrlEncode[[Submit]]?area=NonExistentArea&id=1#fragment]]">Product Route Non-existent Area Parameter</a>
</div>
<div>
<a href="">Non-existent Area</a>

View File

@ -4,7 +4,7 @@
<title></title>
</head>
<body>
<form action="HtmlEncode[[/HtmlGeneration_Order/Submit]]" method="HtmlEncode[[post]]">
<form action="HtmlEncode[[/UrlEncode[[HtmlGeneration_Order]]/UrlEncode[[Submit]]]]" method="HtmlEncode[[post]]">
<div>
<label class="order" for="HtmlEncode[[Shipping]]">HtmlEncode[[Shipping]]</label>
<input type="HtmlEncode[[text]]" size="50" id="HtmlEncode[[Shipping]]" name="HtmlEncode[[Shipping]]" value="HtmlEncode[[Your shipping method is UPSP]]" />

View File

@ -1,10 +1,10 @@
<html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<form action="HtmlEncode[[/HtmlGeneration_Order/Submit]]" method="HtmlEncode[[post]]">
<form action="HtmlEncode[[/UrlEncode[[HtmlGeneration_Order]]/UrlEncode[[Submit]]]]" method="HtmlEncode[[post]]">
<div>
<label class="HtmlEncode[[order]]" for="HtmlEncode[[Shipping]]">HtmlEncode[[Shipping]]</label>
<input id="HtmlEncode[[Shipping]]" name="HtmlEncode[[Shipping]]" size="HtmlEncode[[50]]" type="HtmlEncode[[text]]" value="HtmlEncode[[Your shipping method is UPSP]]" />

View File

@ -4,7 +4,7 @@
<title></title>
</head>
<body>
<form method="get" action="HtmlEncode[[/HtmlGeneration_Home/ProductSubmit]]">
<form method="get" action="HtmlEncode[[/UrlEncode[[HtmlGeneration_Home]]/UrlEncode[[ProductSubmit]]]]">
<div>
<label class="product" for="HtmlEncode[[HomePage]]">HtmlEncode[[HomePage]]</label>
<input type="HtmlEncode[[url]]" size="50" id="HtmlEncode[[HomePage]]" name="HtmlEncode[[HomePage]]" value="HtmlEncode[[http://www.contoso.com/]]" />

View File

@ -2,10 +2,10 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Text.Encodings.Web;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Abstractions;
using Microsoft.AspNet.Mvc.Infrastructure;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
using Microsoft.AspNet.Mvc.Routing;
@ -14,6 +14,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.OptionsModel;
using Microsoft.Extensions.WebEncoders.Testing;
using Moq;
using Xunit;
@ -314,7 +315,7 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal(2, rule.ValidationParameters.Count);
Assert.Equal("*.Length", rule.ValidationParameters["additionalfields"]);
Assert.Equal("/Controller/Action", rule.ValidationParameters["url"]);
Assert.Equal("/UrlEncode[[Controller]]/UrlEncode[[Action]]", rule.ValidationParameters["url"]);
}
// Test area is current in this case.
@ -332,7 +333,9 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal(2, rule.ValidationParameters.Count);
Assert.Equal("*.Length", rule.ValidationParameters["additionalfields"]);
Assert.Equal("/Test/Controller/Action", rule.ValidationParameters["url"]);
Assert.Equal(
"/UrlEncode[[Test]]/UrlEncode[[Controller]]/UrlEncode[[Action]]",
rule.ValidationParameters["url"]);
}
// Explicit reference to the (current) root area.
@ -351,7 +354,7 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal(2, rule.ValidationParameters.Count);
Assert.Equal("*.Length", rule.ValidationParameters["additionalfields"]);
Assert.Equal("/Controller/Action", rule.ValidationParameters["url"]);
Assert.Equal("/UrlEncode[[Controller]]/UrlEncode[[Action]]", rule.ValidationParameters["url"]);
}
// Test area is current in this case.
@ -370,7 +373,7 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal(2, rule.ValidationParameters.Count);
Assert.Equal("*.Length", rule.ValidationParameters["additionalfields"]);
Assert.Equal("/Controller/Action", rule.ValidationParameters["url"]);
Assert.Equal("/UrlEncode[[Controller]]/UrlEncode[[Action]]", rule.ValidationParameters["url"]);
}
// Root area is current in this case.
@ -388,7 +391,9 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal(2, rule.ValidationParameters.Count);
Assert.Equal("*.Length", rule.ValidationParameters["additionalfields"]);
Assert.Equal("/Test/Controller/Action", rule.ValidationParameters["url"]);
Assert.Equal(
"/UrlEncode[[Test]]/UrlEncode[[Controller]]/UrlEncode[[Action]]",
rule.ValidationParameters["url"]);
}
// Explicit reference to the current (Test) area.
@ -406,7 +411,9 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal(2, rule.ValidationParameters.Count);
Assert.Equal("*.Length", rule.ValidationParameters["additionalfields"]);
Assert.Equal("/Test/Controller/Action", rule.ValidationParameters["url"]);
Assert.Equal(
"/UrlEncode[[Test]]/UrlEncode[[Controller]]/UrlEncode[[Action]]",
rule.ValidationParameters["url"]);
}
// Test area is current in this case.
@ -424,7 +431,9 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal(2, rule.ValidationParameters.Count);
Assert.Equal("*.Length", rule.ValidationParameters["additionalfields"]);
Assert.Equal("/AnotherArea/Controller/Action", rule.ValidationParameters["url"]);
Assert.Equal(
"/UrlEncode[[AnotherArea]]/UrlEncode[[Controller]]/UrlEncode[[Action]]",
rule.ValidationParameters["url"]);
}
private static ClientModelValidationContext GetValidationContext(IUrlHelper urlHelper)
@ -558,6 +567,7 @@ namespace Microsoft.AspNet.Mvc
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
serviceCollection.AddSingleton<UrlEncoder>(new UrlTestEncoder());
var routeOptions = new RouteOptions();
var accessor = new Mock<IOptions<RouteOptions>>();