Add extension methods for using routing with Middleware
This commit is contained in:
parent
cc501bc025
commit
cb39589864
|
|
@ -10,6 +10,7 @@
|
|||
],
|
||||
"packages": {
|
||||
"Microsoft.AspNet.Routing.Abstractions": { },
|
||||
"Microsoft.AspNet.Routing.Extensions": { },
|
||||
"Microsoft.AspNet.Routing": { }
|
||||
}
|
||||
},
|
||||
|
|
|
|||
30
Routing.sln
30
Routing.sln
|
|
@ -28,6 +28,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Routing.Ab
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.Routing.Abstractions.Tests", "test\Microsoft.AspNet.Mvc.Routing.Abstractions.Tests\Microsoft.AspNet.Mvc.Routing.Abstractions.Tests.xproj", "{741B0B05-CE96-473B-B962-6B0A347DF79A}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Routing.Extensions", "src\Microsoft.AspNet.Routing.Extensions\Microsoft.AspNet.Routing.Extensions.xproj", "{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Routing.Extensions.Tests", "test\Microsoft.AspNet.Routing.Extensions.Tests\Microsoft.AspNet.Routing.Extensions.Tests.xproj", "{FD0151B4-7153-49A8-9D90-62A252420230}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -116,6 +120,30 @@ Global
|
|||
{741B0B05-CE96-473B-B962-6B0A347DF79A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{741B0B05-CE96-473B-B962-6B0A347DF79A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{741B0B05-CE96-473B-B962-6B0A347DF79A}.Release|x86.Build.0 = Release|Any CPU
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -128,5 +156,7 @@ Global
|
|||
{09C2933C-23AC-41B7-994D-E8A5184A629C} = {95359B4B-4C85-4B44-A75B-0621905C4CF6}
|
||||
{ED253B01-24F1-43D1-AA0B-079391E105A9} = {0E966C37-7334-4D96-AAF6-9F49FBD166E3}
|
||||
{741B0B05-CE96-473B-B962-6B0A347DF79A} = {95359B4B-4C85-4B44-A75B-0621905C4CF6}
|
||||
{579C3FD2-DFFA-4B64-BFC3-130C11F3568F} = {0E966C37-7334-4D96-AAF6-9F49FBD166E3}
|
||||
{FD0151B4-7153-49A8-9D90-62A252420230} = {95359B4B-4C85-4B44-A75B-0621905C4CF6}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Routing;
|
||||
|
|
@ -15,7 +17,7 @@ namespace RoutingSample.Web
|
|||
services.AddRouting();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder builder)
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
var endpoint1 = new RouteHandler((c) =>
|
||||
{
|
||||
|
|
@ -24,12 +26,30 @@ namespace RoutingSample.Web
|
|||
|
||||
var endpoint2 = new RouteHandler((c) => c.Response.WriteAsync("Hello, World!"));
|
||||
|
||||
var routeBuilder = new RouteBuilder()
|
||||
var routeBuilder = new RouteBuilder(app)
|
||||
{
|
||||
DefaultHandler = endpoint1,
|
||||
ServiceProvider = builder.ApplicationServices,
|
||||
};
|
||||
|
||||
routeBuilder.MapRoute("api/status/{item}", c => c.Response.WriteAsync($"{c.GetRouteValue("item")} is just fine."));
|
||||
routeBuilder.MapRoute("localized/{lang=en-US}", b =>
|
||||
{
|
||||
b.Use(next => async (c) =>
|
||||
{
|
||||
var culture = new CultureInfo((string)c.GetRouteValue("lang"));
|
||||
#if DNX451
|
||||
Thread.CurrentThread.CurrentCulture = culture;
|
||||
Thread.CurrentThread.CurrentUICulture = culture;
|
||||
#else
|
||||
CultureInfo.CurrentCulture = culture;
|
||||
CultureInfo.CurrentUICulture = culture;
|
||||
#endif
|
||||
await next(c);
|
||||
});
|
||||
|
||||
b.Run(c => c.Response.WriteAsync($"What would you do with {1000000m:C}?"));
|
||||
});
|
||||
|
||||
routeBuilder.AddPrefixRoute("api/store", endpoint1);
|
||||
routeBuilder.AddPrefixRoute("hello/world", endpoint2);
|
||||
|
||||
|
|
@ -38,7 +58,7 @@ namespace RoutingSample.Web
|
|||
|
||||
routeBuilder.AddPrefixRoute("", endpoint2);
|
||||
|
||||
builder.UseRouter(routeBuilder.Build());
|
||||
app.UseRouter(routeBuilder.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
|
||||
"Microsoft.AspNet.Routing": "1.0.0-*"
|
||||
},
|
||||
"commands": {
|
||||
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:5001",
|
||||
"kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": { },
|
||||
"dnxcore50": { }
|
||||
},
|
||||
"webroot": "wwwroot"
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
|
||||
"Microsoft.AspNet.Routing.Extensions": "1.0.0-*"
|
||||
},
|
||||
"commands": {
|
||||
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:5001",
|
||||
"kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:5000"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": { },
|
||||
"dnxcore50": { }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
RoutingSample.Web
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>579c3fd2-dffa-4b64-bfc3-130c11f3568f</ProjectGuid>
|
||||
<RootNamespace>Microsoft.AspNet.Routing.Extensions</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
[assembly: AssemblyMetadata("Serviceable", "True")]
|
||||
[assembly: NeutralResourcesLanguage("en-us")]
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.AspNet.Routing.Constraints;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Builder
|
||||
{
|
||||
public static class RequestDelegateRouteBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> for the given <paramref name="template"/>, and
|
||||
/// <paramref name="handler"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="template">The route template.</param>
|
||||
/// <param name="handler">The <see cref="RequestDelegate"/> route handler.</param>
|
||||
/// <returns>A reference to the <paramref name="builder"/> after this operation has completed.</returns>
|
||||
public static IRouteBuilder MapRoute(this IRouteBuilder builder, string template, RequestDelegate handler)
|
||||
{
|
||||
var route = new Route(
|
||||
new RouteHandler(handler),
|
||||
template,
|
||||
defaults: null,
|
||||
constraints: null,
|
||||
dataTokens: null,
|
||||
inlineConstraintResolver: GetConstraintResolver(builder));
|
||||
|
||||
builder.Routes.Add(route);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> for the given <paramref name="template"/>, and
|
||||
/// <paramref name="action"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="action">The action to apply to the <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <param name="handler">The <see cref="RequestDelegate"/> route handler.</param>
|
||||
/// <returns>A reference to the <paramref name="builder"/> after this operation has completed.</returns>
|
||||
public static IRouteBuilder MapRoute(this IRouteBuilder builder, string template, Action<IApplicationBuilder> action)
|
||||
{
|
||||
var nested = builder.ApplicationBuilder.New();
|
||||
action(nested);
|
||||
return builder.MapRoute(template, nested.Build());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> that only matches HTTP DELETE requests for the given
|
||||
/// <paramref name="template"/>, and <paramref name="handler"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="template">The route template.</param>
|
||||
/// <param name="handler">The <see cref="RequestDelegate"/> route handler.</param>
|
||||
/// <returns>A reference to the <paramref name="builder"/> after this operation has completed.</returns>
|
||||
public static IRouteBuilder MapDelete(this IRouteBuilder builder, string template, RequestDelegate handler)
|
||||
{
|
||||
return builder.MapVerb("DELETE", template, handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> that only matches HTTP DELETE requests for the given
|
||||
/// <paramref name="template"/>, and <paramref name="action"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="template">The route template.</param>
|
||||
/// <param name="action">The action to apply to the <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <returns>A reference to the <paramref name="builder"/> after this operation has completed.</returns>
|
||||
public static IRouteBuilder MapDelete(this IRouteBuilder builder, string template, Action<IApplicationBuilder> action)
|
||||
{
|
||||
return builder.MapVerb("DELETE", template, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> that only matches HTTP DELETE requests for the given
|
||||
/// <paramref name="template"/>, and <paramref name="handler"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="template">The route template.</param>
|
||||
/// <param name="handler">The <see cref="RequestDelegate"/> route handler.</param>
|
||||
/// <returns>A reference to the <paramref name="builder"/> after this operation has completed.</returns>
|
||||
public static IRouteBuilder MapGet(this IRouteBuilder builder, string template, RequestDelegate handler)
|
||||
{
|
||||
return builder.MapVerb("GET", template, handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> that only matches HTTP DELETE requests for the given
|
||||
/// <paramref name="template"/>, and <paramref name="action"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="template">The route template.</param>
|
||||
/// <param name="action">The action to apply to the <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <returns>A reference to the <paramref name="builder"/> after this operation has completed.</returns>
|
||||
public static IRouteBuilder MapGet(this IRouteBuilder builder, string template, Action<IApplicationBuilder> action)
|
||||
{
|
||||
return builder.MapVerb("GET", template, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> that only matches HTTP DELETE requests for the given
|
||||
/// <paramref name="template"/>, and <paramref name="handler"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="template">The route template.</param>
|
||||
/// <param name="handler">The <see cref="RequestDelegate"/> route handler.</param>
|
||||
/// <returns>A reference to the <paramref name="builder"/> after this operation has completed.</returns>
|
||||
public static IRouteBuilder MapPost(this IRouteBuilder builder, string template, RequestDelegate handler)
|
||||
{
|
||||
return builder.MapVerb("POST", template, handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> that only matches HTTP DELETE requests for the given
|
||||
/// <paramref name="template"/>, and <paramref name="action"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="template">The route template.</param>
|
||||
/// <param name="action">The action to apply to the <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <returns>A reference to the <paramref name="builder"/> after this operation has completed.</returns>
|
||||
public static IRouteBuilder MapPost(this IRouteBuilder builder, string template, Action<IApplicationBuilder> action)
|
||||
{
|
||||
return builder.MapVerb("POST", template, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> that only matches HTTP DELETE requests for the given
|
||||
/// <paramref name="template"/>, and <paramref name="handler"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="template">The route template.</param>
|
||||
/// <param name="handler">The <see cref="RequestDelegate"/> route handler.</param>
|
||||
/// <returns>A reference to the <paramref name="builder"/> after this operation has completed.</returns>
|
||||
public static IRouteBuilder MapPut(this IRouteBuilder builder, string template, RequestDelegate handler)
|
||||
{
|
||||
return builder.MapVerb("PUT", template, handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> that only matches HTTP DELETE requests for the given
|
||||
/// <paramref name="template"/>, and <paramref name="action"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="template">The route template.</param>
|
||||
/// <param name="action">The action to apply to the <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <returns>A reference to the <paramref name="builder"/> after this operation has completed.</returns>
|
||||
public static IRouteBuilder MapPut(this IRouteBuilder builder, string template, Action<IApplicationBuilder> action)
|
||||
{
|
||||
return builder.MapVerb("PUT", template, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> that only matches HTTP requests for the given
|
||||
/// <paramref name="verb"/>, <paramref name="template"/>, and <paramref name="handler"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="verb">The HTTP verb allowed by the route.</param>
|
||||
/// <param name="template">The route template.</param>
|
||||
/// <param name="handler">The <see cref="RequestDelegate"/> route handler.</param>
|
||||
/// <returns>A reference to the <paramref name="builder"/> after this operation has completed.</returns>
|
||||
public static IRouteBuilder MapVerb(
|
||||
this IRouteBuilder builder,
|
||||
string verb,
|
||||
string template,
|
||||
RequestDelegate handler)
|
||||
{
|
||||
var route = new Route(
|
||||
new RouteHandler(handler),
|
||||
template,
|
||||
defaults: null,
|
||||
constraints: new RouteValueDictionary(new { httpMethod = new HttpMethodRouteConstraint(verb) }),
|
||||
dataTokens: null,
|
||||
inlineConstraintResolver: GetConstraintResolver(builder));
|
||||
|
||||
builder.Routes.Add(route);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> that only matches HTTP requests for the given
|
||||
/// <paramref name="verb"/>, <paramref name="template"/>, and <paramref name="action"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="verb">The HTTP verb allowed by the route.</param>
|
||||
/// <param name="template">The route template.</param>
|
||||
/// <param name="action">The action to apply to the <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <returns>A reference to the <paramref name="builder"/> after this operation has completed.</returns>
|
||||
public static IRouteBuilder MapVerb(
|
||||
this IRouteBuilder builder,
|
||||
string verb,
|
||||
string template,
|
||||
Action<IApplicationBuilder> action)
|
||||
{
|
||||
var nested = builder.ApplicationBuilder.New();
|
||||
action(nested);
|
||||
return builder.MapVerb(verb, template, nested.Build());
|
||||
}
|
||||
|
||||
private static IInlineConstraintResolver GetConstraintResolver(IRouteBuilder builder)
|
||||
{
|
||||
return builder.ServiceProvider.GetRequiredService<IInlineConstraintResolver>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"description": "ASP.NET 5 extension methods for routing requests to application logic and for generating links.",
|
||||
"version": "1.0.0-*",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/aspnet/routing"
|
||||
},
|
||||
"compilationOptions": {
|
||||
"warningsAsErrors": true,
|
||||
"keyFile": "../../tools/Key.snk"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Routing": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": { },
|
||||
"dotnet5.4": { }
|
||||
}
|
||||
}
|
||||
|
|
@ -11,14 +11,14 @@ namespace Microsoft.AspNet.Routing.Constraints
|
|||
/// <summary>
|
||||
/// Constrains the HTTP method of request or a route.
|
||||
/// </summary>
|
||||
public class HttpRouteMethodConstraint : IRouteConstraint
|
||||
public class HttpMethodRouteConstraint : IRouteConstraint
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="HttpRouteMethodConstraint"/> that accepts the HTTP methods specified
|
||||
/// Creates a new <see cref="HttpMethodRouteConstraint"/> that accepts the HTTP methods specified
|
||||
/// by <paramref name="allowedMethods"/>.
|
||||
/// </summary>
|
||||
/// <param name="allowedMethods">The allowed HTTP methods.</param>
|
||||
public HttpRouteMethodConstraint(params string[] allowedMethods)
|
||||
public HttpMethodRouteConstraint(params string[] allowedMethods)
|
||||
{
|
||||
if (allowedMethods == null)
|
||||
{
|
||||
|
|
@ -69,8 +69,8 @@ namespace Microsoft.AspNet.Routing.Constraints
|
|||
case RouteDirection.UrlGeneration:
|
||||
// We need to see if the user specified the HTTP method explicitly. Consider these two routes:
|
||||
//
|
||||
// a) Route: template = "/{foo}", Constraints = { httpMethod = new HttpRouteMethodConstraint("GET") }
|
||||
// b) Route: template = "/{foo}", Constraints = { httpMethod = new HttpRouteMethodConstraint("POST") }
|
||||
// a) Route: template = "/{foo}", Constraints = { httpMethod = new HttpMethodRouteConstraint("GET") }
|
||||
// b) Route: template = "/{foo}", Constraints = { httpMethod = new HttpMethodRouteConstraint("POST") }
|
||||
//
|
||||
// A user might know ahead of time that a URI he/she is generating might be used with a particular HTTP
|
||||
// method. If a URI will be used for an HTTP POST but we match on (a) while generating the URI, then
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Builder;
|
||||
|
||||
namespace Microsoft.AspNet.Routing
|
||||
{
|
||||
|
|
@ -12,6 +13,11 @@ namespace Microsoft.AspNet.Routing
|
|||
/// </summary>
|
||||
public interface IRouteBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IApplicationBuilder"/>.
|
||||
/// </summary>
|
||||
IApplicationBuilder ApplicationBuilder { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default <see cref="IRouter"/> that is used as a handler if an <see cref="IRouter"/>
|
||||
/// is added to the list of routes but does not specify its own.
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@
|
|||
// 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;
|
||||
using Microsoft.AspNet.Routing.Template;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Builder
|
||||
|
|
@ -12,7 +10,7 @@ namespace Microsoft.AspNet.Builder
|
|||
/// <summary>
|
||||
/// Provides extension methods for <see cref="IRouteBuilder"/> to add routes.
|
||||
/// </summary>
|
||||
public static class RouteBuilderExtensions
|
||||
public static class MapRouteRouteBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a route to the <see cref="IRouteBuilder"/> with the specified name and template.
|
||||
|
|
@ -3,19 +3,35 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Builder;
|
||||
|
||||
namespace Microsoft.AspNet.Routing
|
||||
{
|
||||
public class RouteBuilder : IRouteBuilder
|
||||
{
|
||||
public RouteBuilder()
|
||||
public RouteBuilder(IApplicationBuilder applicationBuilder)
|
||||
: this(applicationBuilder, defaultHandler: null)
|
||||
{
|
||||
}
|
||||
|
||||
public RouteBuilder(IApplicationBuilder applicationBuilder, IRouter defaultHandler)
|
||||
{
|
||||
if (applicationBuilder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(applicationBuilder));
|
||||
}
|
||||
|
||||
ApplicationBuilder = applicationBuilder;
|
||||
ServiceProvider = applicationBuilder.ApplicationServices;
|
||||
|
||||
Routes = new List<IRouter>();
|
||||
}
|
||||
|
||||
public IApplicationBuilder ApplicationBuilder { get; }
|
||||
|
||||
public IRouter DefaultHandler { get; set; }
|
||||
|
||||
public IServiceProvider ServiceProvider { get; set; }
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
|
||||
public IList<IRouter> Routes { get; }
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>fd0151b4-7153-49a8-9d90-62a252420230</ProjectGuid>
|
||||
<RootNamespace>Microsoft.AspNet.Routing.Extensions.Tests</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
// Copyright (c) .NET Foundation. 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.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Builder
|
||||
{
|
||||
// These are really more like integration tests. They verify that these extensions
|
||||
// add routes that behave as advertised.
|
||||
public class RequestDelegateRouteBuilderExtensionsTest
|
||||
{
|
||||
private static readonly RequestDelegate NullHandler = (c) => Task.FromResult(0);
|
||||
|
||||
public static TheoryData<Action<IRouteBuilder>, Action<HttpContext>> MatchingActions
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<Action<IRouteBuilder>, Action<HttpContext>>()
|
||||
{
|
||||
{ b => { b.MapRoute("api/{id}", NullHandler); }, null },
|
||||
{ b => { b.MapRoute("api/{id}", app => { }); }, null },
|
||||
|
||||
{ b => { b.MapDelete("api/{id}", NullHandler); }, c => { c.Request.Method = "DELETE"; } },
|
||||
{ b => { b.MapDelete("api/{id}", app => { }); }, c => { c.Request.Method = "DELETE"; } },
|
||||
{ b => { b.MapGet("api/{id}", NullHandler); }, c => { c.Request.Method = "GET"; } },
|
||||
{ b => { b.MapGet("api/{id}", app => { }); }, c => { c.Request.Method = "GET"; } },
|
||||
{ b => { b.MapPost("api/{id}", NullHandler); }, c => { c.Request.Method = "POST"; } },
|
||||
{ b => { b.MapPost("api/{id}", app => { }); }, c => { c.Request.Method = "POST"; } },
|
||||
{ b => { b.MapPut("api/{id}", NullHandler); }, c => { c.Request.Method = "PUT"; } },
|
||||
{ b => { b.MapPut("api/{id}", app => { }); }, c => { c.Request.Method = "PUT"; } },
|
||||
|
||||
{ b => { b.MapVerb("PUT", "api/{id}", NullHandler); }, c => { c.Request.Method = "PUT"; } },
|
||||
{ b => { b.MapVerb("PUT", "api/{id}", app => { }); }, c => { c.Request.Method = "PUT"; } },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(MatchingActions))]
|
||||
public async Task Map_MatchesRequest(
|
||||
Action<IRouteBuilder> routeSetup,
|
||||
Action<HttpContext> requestSetup)
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateServices();
|
||||
|
||||
var context = CreateRouteContext(services);
|
||||
context.HttpContext.Request.Path = new PathString("/api/5");
|
||||
requestSetup?.Invoke(context.HttpContext);
|
||||
|
||||
var builder = CreateRouteBuilder(services);
|
||||
routeSetup(builder);
|
||||
var route = builder.Build();
|
||||
|
||||
// Act
|
||||
await route.RouteAsync(context);
|
||||
|
||||
// Assert
|
||||
Assert.Same(NullHandler, context.Handler);
|
||||
}
|
||||
|
||||
public static TheoryData<Action<IRouteBuilder>, Action<HttpContext>> NonmatchingActions
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<Action<IRouteBuilder>, Action<HttpContext>>()
|
||||
{
|
||||
{ b => { b.MapRoute("api/{id}/extra", NullHandler); }, null },
|
||||
{ b => { b.MapRoute("api/{id}/extra", app => { }); }, null },
|
||||
|
||||
{ b => { b.MapDelete("api/{id}", NullHandler); }, c => { c.Request.Method = "GET"; } },
|
||||
{ b => { b.MapDelete("api/{id}", app => { }); }, c => { c.Request.Method = "PUT"; } },
|
||||
{ b => { b.MapDelete("api/{id}/extra", NullHandler); }, c => { c.Request.Method = "DELETE"; } },
|
||||
{ b => { b.MapDelete("api/{id}/extra", app => { }); }, c => { c.Request.Method = "DELETE"; } },
|
||||
{ b => { b.MapGet("api/{id}", NullHandler); }, c => { c.Request.Method = "PUT"; } },
|
||||
{ b => { b.MapGet("api/{id}", app => { }); }, c => { c.Request.Method = "POST"; } },
|
||||
{ b => { b.MapGet("api/{id}/extra", NullHandler); }, c => { c.Request.Method = "GET"; } },
|
||||
{ b => { b.MapGet("api/{id}/extra", app => { }); }, c => { c.Request.Method = "GET"; } },
|
||||
{ b => { b.MapPost("api/{id}", NullHandler); }, c => { c.Request.Method = "MEH"; } },
|
||||
{ b => { b.MapPost("api/{id}", app => { }); }, c => { c.Request.Method = "DELETE"; } },
|
||||
{ b => { b.MapPost("api/{id}/extra", NullHandler); }, c => { c.Request.Method = "POST"; } },
|
||||
{ b => { b.MapPost("api/{id}/extra", app => { }); }, c => { c.Request.Method = "POST"; } },
|
||||
{ b => { b.MapPut("api/{id}", NullHandler); }, c => { c.Request.Method = "BLEH"; } },
|
||||
{ b => { b.MapPut("api/{id}", app => { }); }, c => { c.Request.Method = "HEAD"; } },
|
||||
{ b => { b.MapPut("api/{id}/extra", NullHandler); }, c => { c.Request.Method = "PUT"; } },
|
||||
{ b => { b.MapPut("api/{id}/extra", app => { }); }, c => { c.Request.Method = "PUT"; } },
|
||||
|
||||
{ b => { b.MapVerb("PUT", "api/{id}", NullHandler); }, c => { c.Request.Method = "POST"; } },
|
||||
{ b => { b.MapVerb("PUT", "api/{id}", app => { }); }, c => { c.Request.Method = "HEAD"; } },
|
||||
{ b => { b.MapVerb("PUT", "api/{id}/extra", NullHandler); }, c => { c.Request.Method = "PUT"; } },
|
||||
{ b => { b.MapVerb("PUT", "api/{id}/extra", app => { }); }, c => { c.Request.Method = "PUT"; } },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(NonmatchingActions))]
|
||||
public async Task Map_DoesNotMatchRequest(
|
||||
Action<IRouteBuilder> routeSetup,
|
||||
Action<HttpContext> requestSetup)
|
||||
{
|
||||
// Arrange
|
||||
var services = CreateServices();
|
||||
|
||||
var context = CreateRouteContext(services);
|
||||
context.HttpContext.Request.Path = new PathString("/api/5");
|
||||
requestSetup?.Invoke(context.HttpContext);
|
||||
|
||||
var builder = CreateRouteBuilder(services);
|
||||
routeSetup(builder);
|
||||
var route = builder.Build();
|
||||
|
||||
// Act
|
||||
await route.RouteAsync(context);
|
||||
|
||||
// Assert
|
||||
Assert.Null(context.Handler);
|
||||
}
|
||||
|
||||
private static IServiceProvider CreateServices()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddRouting();
|
||||
services.AddLogging();
|
||||
return services.BuildServiceProvider();
|
||||
}
|
||||
|
||||
private static RouteContext CreateRouteContext(IServiceProvider services)
|
||||
{
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.RequestServices = services;
|
||||
return new RouteContext(httpContext);
|
||||
}
|
||||
|
||||
private static IRouteBuilder CreateRouteBuilder(IServiceProvider services)
|
||||
{
|
||||
var applicationBuilder = new Mock<IApplicationBuilder>();
|
||||
applicationBuilder.SetupAllProperties();
|
||||
|
||||
applicationBuilder
|
||||
.Setup(b => b.New().Build())
|
||||
.Returns(NullHandler);
|
||||
|
||||
applicationBuilder.Object.ApplicationServices = services;
|
||||
|
||||
var routeBuilder = new RouteBuilder(applicationBuilder.Object);
|
||||
return routeBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"compilationOptions": {
|
||||
"warningsAsErrors": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Http": "1.0.0-*",
|
||||
"Microsoft.AspNet.Routing.Extensions": "1.0.0-*",
|
||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||
"Microsoft.Extensions.DependencyInjection": "1.0.0-*",
|
||||
"Microsoft.Extensions.Logging.Testing": "1.0.0-*",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnxcore50": {
|
||||
"dependencies": {
|
||||
"moq.netcore": "4.4.0-beta8"
|
||||
}
|
||||
},
|
||||
"dnx451": {
|
||||
"dependencies": {
|
||||
"Moq": "4.2.1312.1622"
|
||||
}
|
||||
}
|
||||
},
|
||||
"commands": {
|
||||
"test": "xunit.runner.aspnet"
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNet.Routing.Constraints
|
|||
public void HttpMethodRouteConstraint_IncomingRequest_AcceptsAllowedMethods(string httpMethod)
|
||||
{
|
||||
// Arrange
|
||||
var constraint = new HttpRouteMethodConstraint("GET", "post");
|
||||
var constraint = new HttpMethodRouteConstraint("GET", "post");
|
||||
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Request.Method = httpMethod;
|
||||
|
|
@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Routing.Constraints
|
|||
public void HttpMethodRouteConstraint_IncomingRequest_RejectsOtherMethods(string httpMethod)
|
||||
{
|
||||
// Arrange
|
||||
var constraint = new HttpRouteMethodConstraint("GET", "post");
|
||||
var constraint = new HttpMethodRouteConstraint("GET", "post");
|
||||
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Request.Method = httpMethod;
|
||||
|
|
@ -57,7 +57,7 @@ namespace Microsoft.AspNet.Routing.Constraints
|
|||
public void HttpMethodRouteConstraint_UrlGeneration_AcceptsAllowedMethods(string httpMethod)
|
||||
{
|
||||
// Arrange
|
||||
var constraint = new HttpRouteMethodConstraint("GET", "post");
|
||||
var constraint = new HttpMethodRouteConstraint("GET", "post");
|
||||
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var route = Mock.Of<IRouter>();
|
||||
|
|
@ -77,7 +77,7 @@ namespace Microsoft.AspNet.Routing.Constraints
|
|||
public void HttpMethodRouteConstraint_UrlGeneration_RejectsOtherMethods(string httpMethod)
|
||||
{
|
||||
// Arrange
|
||||
var constraint = new HttpRouteMethodConstraint("GET", "post");
|
||||
var constraint = new HttpMethodRouteConstraint("GET", "post");
|
||||
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var route = Mock.Of<IRouter>();
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@ using Microsoft.AspNet.Builder;
|
|||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Routing.Constraints;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -1490,15 +1491,14 @@ namespace Microsoft.AspNet.Routing
|
|||
|
||||
private static IRouteBuilder CreateRouteBuilder()
|
||||
{
|
||||
var routeBuilder = new RouteBuilder();
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IInlineConstraintResolver>(_inlineConstraintResolver);
|
||||
|
||||
var applicationBuilder = Mock.Of<IApplicationBuilder>();
|
||||
applicationBuilder.ApplicationServices = services.BuildServiceProvider();
|
||||
|
||||
var routeBuilder = new RouteBuilder(applicationBuilder);
|
||||
routeBuilder.DefaultHandler = new RouteHandler(NullHandler);
|
||||
|
||||
var serviceProviderMock = new Mock<IServiceProvider>();
|
||||
serviceProviderMock.Setup(o => o.GetService(typeof(IInlineConstraintResolver)))
|
||||
.Returns(_inlineConstraintResolver);
|
||||
routeBuilder.ServiceProvider = serviceProviderMock.Object;
|
||||
|
||||
return routeBuilder;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,26 +96,28 @@ namespace Microsoft.AspNet.Routing.Tests
|
|||
var routeBuilder = CreateRouteBuilder();
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<ArgumentException>(
|
||||
() => routeBuilder.MapRoute("mockName",
|
||||
"{controller}/{action}/{id:int=12?}",
|
||||
defaults: new { id = 13 },
|
||||
constraints: null));
|
||||
var ex = Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
routeBuilder.MapRoute(
|
||||
"mockName",
|
||||
"{controller}/{action}/{id:int=12?}",
|
||||
defaults: new { id = 13 },
|
||||
constraints: null);
|
||||
});
|
||||
|
||||
Assert.Equal(message, ex.Message);
|
||||
}
|
||||
|
||||
private static IRouteBuilder CreateRouteBuilder()
|
||||
{
|
||||
var routeBuilder = new RouteBuilder();
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IInlineConstraintResolver>(_inlineConstraintResolver);
|
||||
|
||||
routeBuilder.DefaultHandler = new Mock<IRouter>().Object;
|
||||
|
||||
var serviceProviderMock = new Mock<IServiceProvider>();
|
||||
serviceProviderMock.Setup(o => o.GetService(typeof(IInlineConstraintResolver)))
|
||||
.Returns(_inlineConstraintResolver);
|
||||
routeBuilder.ServiceProvider = serviceProviderMock.Object;
|
||||
var applicationBuilder = Mock.Of<IApplicationBuilder>();
|
||||
applicationBuilder.ApplicationServices = services.BuildServiceProvider();
|
||||
|
||||
var routeBuilder = new RouteBuilder(applicationBuilder);
|
||||
routeBuilder.DefaultHandler = Mock.Of<IRouter>();
|
||||
return routeBuilder;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue