Routing DI Changes I:

Moving out Default Handler and IInlineConstraintResolver from RouteCollection.
	These are moved to a new interface IRouteBuilder, (instead of an IInlineConstraintResolver, it takes in an IServiceProvider).
	This means all RouteCollectionExtensions are moved to RouteBuilderExtensions.
This commit is contained in:
harshgMSFT 2014-05-28 17:43:18 -07:00
parent 874ef7bc76
commit 1d3e41560c
14 changed files with 274 additions and 169 deletions

View File

@ -0,0 +1,32 @@
using System;
using Microsoft.AspNet.Routing;
namespace RoutingSample.Web
{
public static class RouteBuilderExtensions
{
public static IRouteBuilder AddPrefixRoute(this IRouteBuilder routeBuilder,
string prefix)
{
if (routeBuilder.DefaultHandler == null)
{
throw new InvalidOperationException("DefaultHandler must be set.");
}
if (routeBuilder.ServiceProvider == null)
{
throw new InvalidOperationException("ServiceProvider must be set.");
}
return AddPrefixRoute(routeBuilder, prefix, routeBuilder.DefaultHandler);
}
public static IRouteBuilder AddPrefixRoute(this IRouteBuilder routeBuilder,
string prefix,
IRouter handler)
{
routeBuilder.Routes.Add(new PrefixRoute(handler, prefix));
return routeBuilder;
}
}
}

View File

@ -1,24 +0,0 @@
using System;
using Microsoft.AspNet.Routing;
namespace RoutingSample.Web
{
public static class RouteCollectionExtensions
{
public static IRouteCollection AddPrefixRoute(this IRouteCollection routes, string prefix)
{
if (routes.DefaultHandler == null)
{
throw new ArgumentException("DefaultHandler must be set.");
}
return AddPrefixRoute(routes, prefix, routes.DefaultHandler);
}
public static IRouteCollection AddPrefixRoute(this IRouteCollection routes, string prefix, IRouter handler)
{
routes.Add(new PrefixRoute(handler, prefix));
return routes;
}
}
}

View File

@ -28,7 +28,7 @@
<Compile Include="DelegateRouteEndpoint.cs" />
<Compile Include="DictionaryExtensions.cs" />
<Compile Include="PrefixRoute.cs" />
<Compile Include="RouteCollectionExtensions.cs" />
<Compile Include="RouteCollectionBuilderExtensions.cs" />
<Compile Include="Startup.cs" />
</ItemGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />

View File

@ -1,7 +1,9 @@
using System;
using System.Text.RegularExpressions;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Routing.Constraints;
using Microsoft.Framework.DependencyInjection;
namespace RoutingSample.Web
{
@ -9,32 +11,46 @@ namespace RoutingSample.Web
{
public void Configure(IBuilder builder)
{
var routes = new RouteCollection();
builder.UseRouter(routes);
var collectionBuilder = new RouteBuilder();
var endpoint1 = new DelegateRouteEndpoint(async (context) =>
await context.HttpContext.Response.WriteAsync(
"match1, route values -" + context.Values.Print()));
await context
.HttpContext
.Response
.WriteAsync(
"match1, route values -" + context.Values.Print()));
var endpoint2 = new DelegateRouteEndpoint(async (context) =>
await context.HttpContext.Response.WriteAsync("Hello, World!"));
await context
.HttpContext
.Response
.WriteAsync("Hello, World!"));
routes.DefaultHandler = endpoint1;
routes.AddPrefixRoute("api/store");
collectionBuilder.DefaultHandler = endpoint1;
collectionBuilder.ServiceProvider = builder.ApplicationServices;
routes.MapRoute("defaultRoute", "api/constraint/{controller}", null, new { controller = "my.*" });
routes.MapRoute("regexStringRoute",
"api/rconstraint/{controller}",
new { foo = "Bar" },
new { controller = new RegexConstraint("^(my.*)$") });
routes.MapRoute("regexRoute",
"api/r2constraint/{controller}",
new { foo = "Bar2" },
new { controller = new RegexConstraint(new Regex("^(my.*)$")) });
collectionBuilder.AddPrefixRoute("api/store");
routes.MapRoute("parameterConstraintRoute", "api/{controller}/{*extra}", new { controller = "Store" });
collectionBuilder.MapRoute("defaultRoute",
"api/constraint/{controller}",
null,
new { controller = "my.*" });
collectionBuilder.MapRoute("regexStringRoute",
"api/rconstraint/{controller}",
new { foo = "Bar" },
new { controller = new RegexConstraint("^(my.*)$") });
collectionBuilder.MapRoute("regexRoute",
"api/r2constraint/{controller}",
new { foo = "Bar2" },
new { controller = new RegexConstraint(new Regex("^(my.*)$")) });
routes.AddPrefixRoute("hello/world", endpoint2);
routes.AddPrefixRoute("", endpoint2);
collectionBuilder.MapRoute("parameterConstraintRoute",
"api/{controller}/{*extra}",
new { controller = "Store" });
collectionBuilder.AddPrefixRoute("hello/world", endpoint2);
collectionBuilder.AddPrefixRoute("", endpoint2);
builder.UseRouter(collectionBuilder.Build());
}
}
}

View File

@ -0,0 +1,19 @@
// 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.
using System;
using System.Collections.Generic;
namespace Microsoft.AspNet.Routing
{
public interface IRouteBuilder
{
IRouter DefaultHandler { get; }
IServiceProvider ServiceProvider { get; }
IList<IRouter> Routes { get; }
IRouter Build();
}
}

View File

@ -5,10 +5,6 @@ namespace Microsoft.AspNet.Routing
{
public interface IRouteCollection : IRouter
{
IRouter DefaultHandler { get; set; }
IInlineConstraintResolver InlineConstraintResolver { get; set; }
void Add(IRouter router);
}
}

View File

@ -29,13 +29,15 @@
<Compile Include="IInlineConstraintResolver.cs" />
<Compile Include="INamedRouter.cs" />
<Compile Include="InlineRouteParameterParser.cs" />
<Compile Include="IRouteCollectionBuilder.cs" />
<Compile Include="IRouteCollection.cs" />
<Compile Include="IRouteConstraint.cs" />
<Compile Include="IRouter.cs" />
<Compile Include="NotNullAttribute.cs" />
<Compile Include="Properties\Resources.Designer.cs" />
<Compile Include="RouteCollection.cs" />
<Compile Include="RouteCollectionExtensions.cs" />
<Compile Include="RouteCollectionBuilder.cs" />
<Compile Include="RouteCollectionBuilderExtensions.cs" />
<Compile Include="RouteConstraintBuilder.cs" />
<Compile Include="RouteConstraintMatcher.cs" />
<Compile Include="RouteContext.cs" />

View File

@ -0,0 +1,38 @@
// 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.
using System;
using System.Collections.Generic;
namespace Microsoft.AspNet.Routing
{
public class RouteBuilder : IRouteBuilder
{
public RouteBuilder()
{
Routes = new List<IRouter>();
}
public IRouter DefaultHandler { get; set; }
public IServiceProvider ServiceProvider { get; set; }
public IList<IRouter> Routes
{
get;
private set;
}
public IRouter Build()
{
var routeCollection = new RouteCollection();
foreach (var route in Routes)
{
routeCollection.Add(route);
}
return routeCollection;
}
}
}

View File

@ -0,0 +1,109 @@
// 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.
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Routing.Template;
using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Routing
{
public static class RouteBuilderExtensions
{
public static IRouteBuilder MapRoute(this IRouteBuilder routeCollectionBuilder,
string name,
string template)
{
MapRoute(routeCollectionBuilder, name, template, defaults: null);
return routeCollectionBuilder;
}
public static IRouteBuilder MapRoute(this IRouteBuilder routeCollectionBuilder,
string name,
string template,
object defaults)
{
MapRoute(routeCollectionBuilder, name, template, new RouteValueDictionary(defaults));
return routeCollectionBuilder;
}
public static IRouteBuilder MapRoute(this IRouteBuilder routeCollectionBuilder,
string name,
string template,
IDictionary<string, object> defaults)
{
if (routeCollectionBuilder.DefaultHandler == null)
{
throw new InvalidOperationException(Resources.DefaultHandler_MustBeSet);
}
var inlineConstraintResolver = routeCollectionBuilder
.ServiceProvider
.GetService<IInlineConstraintResolver>();
routeCollectionBuilder.Routes.Add(new TemplateRoute(routeCollectionBuilder.DefaultHandler,
name,
template,
defaults,
constraints: null,
inlineConstraintResolver: inlineConstraintResolver));
return routeCollectionBuilder;
}
public static IRouteBuilder MapRoute(this IRouteBuilder routeCollectionBuilder,
string name,
string template,
object defaults,
object constraints)
{
MapRoute(routeCollectionBuilder,
name,
template,
new RouteValueDictionary(defaults),
new RouteValueDictionary(constraints));
return routeCollectionBuilder;
}
public static IRouteBuilder MapRoute(this IRouteBuilder routeCollectionBuilder,
string name,
string template,
object defaults,
IDictionary<string, object> constraints)
{
MapRoute(routeCollectionBuilder, name, template, new RouteValueDictionary(defaults), constraints);
return routeCollectionBuilder;
}
public static IRouteBuilder MapRoute(this IRouteBuilder routeCollectionBuilder,
string name,
string template,
IDictionary<string, object> defaults, object constraints)
{
MapRoute(routeCollectionBuilder, name, template, defaults, new RouteValueDictionary(constraints));
return routeCollectionBuilder;
}
public static IRouteBuilder MapRoute(this IRouteBuilder routeCollectionBuilder,
string name,
string template,
IDictionary<string, object> defaults,
IDictionary<string, object> constraints)
{
if (routeCollectionBuilder.DefaultHandler == null)
{
throw new InvalidOperationException(Resources.DefaultHandler_MustBeSet);
}
var inlineConstraintResolver = routeCollectionBuilder
.ServiceProvider
.GetService<IInlineConstraintResolver>();
routeCollectionBuilder.Routes.Add(new TemplateRoute(routeCollectionBuilder.DefaultHandler,
name,
template,
defaults,
constraints,
inlineConstraintResolver));
return routeCollectionBuilder;
}
}
}

View File

@ -24,10 +24,6 @@ namespace Microsoft.AspNet.Routing
get { return _routes.Count; }
}
public IRouter DefaultHandler { get; set; }
public IInlineConstraintResolver InlineConstraintResolver { get; set; }
public void Add([NotNull] IRouter router)
{
var namedRouter = router as INamedRouter;

View File

@ -1,87 +0,0 @@
// 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.
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Routing.Template;
namespace Microsoft.AspNet.Routing
{
public static class RouteCollectionExtensions
{
public static IRouteCollection MapRoute(this IRouteCollection routes, string name, string template)
{
MapRoute(routes, name, template, defaults: null);
return routes;
}
public static IRouteCollection MapRoute(this IRouteCollection routes, string name, string template,
object defaults)
{
MapRoute(routes, name, template, new RouteValueDictionary(defaults));
return routes;
}
public static IRouteCollection MapRoute(this IRouteCollection routes, string name, string template,
IDictionary<string, object> defaults)
{
if (routes.DefaultHandler == null)
{
throw new InvalidOperationException(Resources.DefaultHandler_MustBeSet);
}
routes.Add(new TemplateRoute(routes.DefaultHandler,
name,
template,
defaults,
constraints: null,
inlineConstraintResolver: routes.InlineConstraintResolver));
return routes;
}
public static IRouteCollection MapRoute(this IRouteCollection routes, string name, string template,
object defaults, object constraints)
{
MapRoute(routes,
name,
template,
new RouteValueDictionary(defaults),
new RouteValueDictionary(constraints));
return routes;
}
public static IRouteCollection MapRoute(this IRouteCollection routes, string name, string template,
object defaults, IDictionary<string, object> constraints)
{
MapRoute(routes, name, template, new RouteValueDictionary(defaults), constraints);
return routes;
}
public static IRouteCollection MapRoute(this IRouteCollection routes, string name, string template,
IDictionary<string, object> defaults, object constraints)
{
MapRoute(routes, name, template, defaults, new RouteValueDictionary(constraints));
return routes;
}
public static IRouteCollection MapRoute(this IRouteCollection routes,
string name,
string template,
IDictionary<string, object> defaults,
IDictionary<string, object> constraints)
{
if (routes.DefaultHandler == null)
{
throw new InvalidOperationException(Resources.DefaultHandler_MustBeSet);
}
routes.Add(new TemplateRoute(routes.DefaultHandler,
name,
template,
defaults,
constraints,
routes.InlineConstraintResolver));
return routes;
}
}
}

View File

@ -209,4 +209,4 @@ namespace Microsoft.AspNet.Routing.Template
}
}
}
}
}

View File

@ -1,7 +1,8 @@
{
"version": "0.1-alpha-*",
"dependencies": {
"Microsoft.AspNet.Http": "0.1-alpha-*"
"Microsoft.AspNet.Http": "0.1-alpha-*",
"Microsoft.Framework.DependencyInjection" : "0.1-alpha-*"
},
"configurations": {
"net45": {},

View File

@ -9,6 +9,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Routing.Constraints;
using Microsoft.AspNet.Testing;
using Microsoft.Framework.DependencyInjection;
using Moq;
using Xunit;
@ -391,11 +392,10 @@ namespace Microsoft.AspNet.Routing.Template.Tests
public void RegisteringRouteWithInvalidConstraints_Throws()
{
// Arrange
var collection = new RouteCollection();
collection.DefaultHandler = new Mock<IRouter>().Object;
var routeBuilder = CreateRouteBuilder();
// Assert
ExceptionAssert.Throws<InvalidOperationException>(() => collection.MapRoute("mockName",
ExceptionAssert.Throws<InvalidOperationException>(() => routeBuilder.MapRoute("mockName",
"{controller}/{action}",
defaults: null,
constraints: new { controller = "a.*", action = new Object() }),
@ -408,17 +408,16 @@ namespace Microsoft.AspNet.Routing.Template.Tests
public void RegisteringRouteWithTwoConstraints()
{
// Arrange
var collection = new RouteCollection();
collection.DefaultHandler = new Mock<IRouter>().Object;
var routeBuilder = CreateRouteBuilder();
var mockConstraint = new Mock<IRouteConstraint>().Object;
collection.MapRoute("mockName",
routeBuilder.MapRoute("mockName",
"{controller}/{action}",
defaults: null,
constraints: new { controller = "a.*", action = mockConstraint });
var constraints = ((TemplateRoute)collection[0]).Constraints;
var constraints = ((TemplateRoute)routeBuilder.Routes[0]).Constraints;
// Assert
Assert.Equal(2, constraints.Count);
@ -430,18 +429,16 @@ namespace Microsoft.AspNet.Routing.Template.Tests
public void RegisteringRouteWithOneInlineConstraintAndOneUsingConstraintArgument()
{
// Arrange
var collection = new RouteCollection();
collection.DefaultHandler = new Mock<IRouter>().Object;
collection.InlineConstraintResolver = new DefaultInlineConstraintResolver();
var routeBuilder = CreateRouteBuilder();
collection.MapRoute("mockName",
// Act
routeBuilder.MapRoute("mockName",
"{controller}/{action}/{id:int}",
defaults: null,
constraints: new { id = "1*" });
var constraints = ((TemplateRoute)collection[0]).Constraints;
// Assert
var constraints = ((TemplateRoute)routeBuilder.Routes[0]).Constraints;
Assert.Equal(1, constraints.Count);
var constraint = (CompositeRouteConstraint)constraints["id"];
Assert.IsType<CompositeRouteConstraint>(constraint);
@ -453,18 +450,16 @@ namespace Microsoft.AspNet.Routing.Template.Tests
public void RegisteringRoute_WithOneInlineConstraint_AddsItToConstraintCollection()
{
// Arrange
var collection = new RouteCollection();
collection.DefaultHandler = new Mock<IRouter>().Object;
collection.InlineConstraintResolver = new DefaultInlineConstraintResolver();
var routeBuilder = CreateRouteBuilder();
collection.MapRoute("mockName",
// Act
routeBuilder.MapRoute("mockName",
"{controller}/{action}/{id:int}",
defaults: null,
constraints: null);
var constraints = ((TemplateRoute)collection[0]).Constraints;
// Assert
var constraints = ((TemplateRoute)routeBuilder.Routes[0]).Constraints;
Assert.Equal(1, constraints.Count);
Assert.IsType<IntRouteConstraint>(constraints["id"]);
}
@ -473,13 +468,12 @@ namespace Microsoft.AspNet.Routing.Template.Tests
public void RegisteringRouteWithRouteName_WithNullDefaults_AddsTheRoute()
{
// Arrange
var collection = new RouteCollection();
collection.DefaultHandler = new Mock<IRouter>().Object;
var routeBuilder = CreateRouteBuilder();
collection.MapRoute(name: "RouteName", template: "{controller}/{action}", defaults: null);
routeBuilder.MapRoute(name: "RouteName", template: "{controller}/{action}", defaults: null);
// Act
var name = ((TemplateRoute)collection[0]).Name;
var name = ((TemplateRoute)routeBuilder.Routes[0]).Name;
// Assert
Assert.Equal("RouteName", name);
@ -489,16 +483,15 @@ namespace Microsoft.AspNet.Routing.Template.Tests
public void RegisteringRouteWithRouteName_WithNullDefaultsAndConstraints_AddsTheRoute()
{
// Arrange
var collection = new RouteCollection();
collection.DefaultHandler = new Mock<IRouter>().Object;
var routeBuilder = CreateRouteBuilder();
collection.MapRoute(name: "RouteName",
routeBuilder.MapRoute(name: "RouteName",
template: "{controller}/{action}",
defaults: null,
constraints: null);
// Act
var name = ((TemplateRoute)collection[0]).Name;
var name = ((TemplateRoute)routeBuilder.Routes[0]).Name;
// Assert
Assert.Equal("RouteName", name);
@ -506,6 +499,20 @@ namespace Microsoft.AspNet.Routing.Template.Tests
#endregion
private static IRouteBuilder CreateRouteBuilder()
{
var routeBuilder = new RouteBuilder();
routeBuilder.DefaultHandler = new Mock<IRouter>().Object;
var serviceProviderMock = new Mock<IServiceProvider>();
serviceProviderMock.Setup(o => o.GetService(typeof(IInlineConstraintResolver)))
.Returns(new DefaultInlineConstraintResolver());
routeBuilder.ServiceProvider = serviceProviderMock.Object;
return routeBuilder;
}
private static TemplateRoute CreateRoute(string template, bool accept = true)
{
return new TemplateRoute(CreateTarget(accept), template, new DefaultInlineConstraintResolver());