Move EndpointModel and IEndpointConventionBuilder to HTTP abstractions (#4274)

This commit is contained in:
James Newton-King 2018-12-17 18:38:49 +13:00 committed by GitHub
parent 708dc5cb5a
commit cc899e2be7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 167 additions and 226 deletions

View File

@ -0,0 +1,35 @@
// 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.Collections.Generic;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Builder
{
/// <summary>
/// A base class for building an new <see cref="Endpoint"/>.
/// </summary>
public abstract class EndpointBuilder
{
/// <summary>
/// Gets or sets the delegate used to process requests for the endpoint.
/// </summary>
public RequestDelegate RequestDelegate { get; set; }
/// <summary>
/// Gets or sets the informational display name of this endpoint.
/// </summary>
public string DisplayName { get; set; }
/// <summary>
/// Gets the collection of metadata associated with this endpoint.
/// </summary>
public IList<object> Metadata { get; } = new List<object>();
/// <summary>
/// Creates an instance of <see cref="Endpoint"/> from the <see cref="EndpointBuilder"/>.
/// </summary>
/// <returns>The created <see cref="Endpoint"/>.</returns>
public abstract Endpoint Build();
}
}

View File

@ -0,0 +1,22 @@
// 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;
namespace Microsoft.AspNetCore.Builder
{
/// <summary>
/// Builds conventions that will be used for customization of <see cref="EndpointBuilder"/> instances.
/// </summary>
/// <remarks>
/// This interface is used at application startup to customize endpoints for the application.
/// </remarks>
public interface IEndpointConventionBuilder
{
/// <summary>
/// Adds the specified convention to the builder. Conventions are used to customize <see cref="EndpointBuilder"/> instances.
/// </summary>
/// <param name="convention">The convention to add to the builder.</param>
void Add(Action<EndpointBuilder> convention);
}
}

View File

@ -109,6 +109,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{DC519C5E-CA6E-48CA-BF35-B46305B83013}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{DC519C5E-CA6E-48CA-BF35-B46305B83013}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.IISIntegration", "..\Servers\IIS\src\Microsoft.AspNetCore.Server.IISIntegration\Microsoft.AspNetCore.Server.IISIntegration.csproj", "{DF1EF1B6-9795-4957-979C-F62F58F91743}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.HttpOverrides", "..\Middleware\HttpOverrides\src\Microsoft.AspNetCore.HttpOverrides.csproj", "{611794D2-EF3A-422A-A077-23E61C7ADE49}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -575,6 +579,30 @@ Global
{1909E2E3-D435-47AA-B2AB-D6EC58BEDC0D}.Release|x64.Build.0 = Release|Any CPU {1909E2E3-D435-47AA-B2AB-D6EC58BEDC0D}.Release|x64.Build.0 = Release|Any CPU
{1909E2E3-D435-47AA-B2AB-D6EC58BEDC0D}.Release|x86.ActiveCfg = Release|Any CPU {1909E2E3-D435-47AA-B2AB-D6EC58BEDC0D}.Release|x86.ActiveCfg = Release|Any CPU
{1909E2E3-D435-47AA-B2AB-D6EC58BEDC0D}.Release|x86.Build.0 = Release|Any CPU {1909E2E3-D435-47AA-B2AB-D6EC58BEDC0D}.Release|x86.Build.0 = Release|Any CPU
{DF1EF1B6-9795-4957-979C-F62F58F91743}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DF1EF1B6-9795-4957-979C-F62F58F91743}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DF1EF1B6-9795-4957-979C-F62F58F91743}.Debug|x64.ActiveCfg = Debug|Any CPU
{DF1EF1B6-9795-4957-979C-F62F58F91743}.Debug|x64.Build.0 = Debug|Any CPU
{DF1EF1B6-9795-4957-979C-F62F58F91743}.Debug|x86.ActiveCfg = Debug|Any CPU
{DF1EF1B6-9795-4957-979C-F62F58F91743}.Debug|x86.Build.0 = Debug|Any CPU
{DF1EF1B6-9795-4957-979C-F62F58F91743}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DF1EF1B6-9795-4957-979C-F62F58F91743}.Release|Any CPU.Build.0 = Release|Any CPU
{DF1EF1B6-9795-4957-979C-F62F58F91743}.Release|x64.ActiveCfg = Release|Any CPU
{DF1EF1B6-9795-4957-979C-F62F58F91743}.Release|x64.Build.0 = Release|Any CPU
{DF1EF1B6-9795-4957-979C-F62F58F91743}.Release|x86.ActiveCfg = Release|Any CPU
{DF1EF1B6-9795-4957-979C-F62F58F91743}.Release|x86.Build.0 = Release|Any CPU
{611794D2-EF3A-422A-A077-23E61C7ADE49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{611794D2-EF3A-422A-A077-23E61C7ADE49}.Debug|Any CPU.Build.0 = Debug|Any CPU
{611794D2-EF3A-422A-A077-23E61C7ADE49}.Debug|x64.ActiveCfg = Debug|Any CPU
{611794D2-EF3A-422A-A077-23E61C7ADE49}.Debug|x64.Build.0 = Debug|Any CPU
{611794D2-EF3A-422A-A077-23E61C7ADE49}.Debug|x86.ActiveCfg = Debug|Any CPU
{611794D2-EF3A-422A-A077-23E61C7ADE49}.Debug|x86.Build.0 = Debug|Any CPU
{611794D2-EF3A-422A-A077-23E61C7ADE49}.Release|Any CPU.ActiveCfg = Release|Any CPU
{611794D2-EF3A-422A-A077-23E61C7ADE49}.Release|Any CPU.Build.0 = Release|Any CPU
{611794D2-EF3A-422A-A077-23E61C7ADE49}.Release|x64.ActiveCfg = Release|Any CPU
{611794D2-EF3A-422A-A077-23E61C7ADE49}.Release|x64.Build.0 = Release|Any CPU
{611794D2-EF3A-422A-A077-23E61C7ADE49}.Release|x86.ActiveCfg = Release|Any CPU
{611794D2-EF3A-422A-A077-23E61C7ADE49}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -621,6 +649,8 @@ Global
{EEA036BB-E6B8-4D01-907B-D4B34B4368DB} = {793FFE24-138A-4C3D-81AB-18D625E36230} {EEA036BB-E6B8-4D01-907B-D4B34B4368DB} = {793FFE24-138A-4C3D-81AB-18D625E36230}
{1909E2E3-D435-47AA-B2AB-D6EC58BEDC0D} = {793FFE24-138A-4C3D-81AB-18D625E36230} {1909E2E3-D435-47AA-B2AB-D6EC58BEDC0D} = {793FFE24-138A-4C3D-81AB-18D625E36230}
{DC519C5E-CA6E-48CA-BF35-B46305B83013} = {14A7B3DE-46C8-4245-B0BD-9AFF3795C163} {DC519C5E-CA6E-48CA-BF35-B46305B83013} = {14A7B3DE-46C8-4245-B0BD-9AFF3795C163}
{DF1EF1B6-9795-4957-979C-F62F58F91743} = {793FFE24-138A-4C3D-81AB-18D625E36230}
{611794D2-EF3A-422A-A077-23E61C7ADE49} = {793FFE24-138A-4C3D-81AB-18D625E36230}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {85B5E151-2E9D-419C-83DD-0DDCF446C83A} SolutionGuid = {85B5E151-2E9D-419C-83DD-0DDCF446C83A}

View File

@ -182,16 +182,16 @@ namespace Microsoft.AspNetCore.Builder
const int defaultOrder = 0; const int defaultOrder = 0;
var routeEndpointModel = new RouteEndpointModel( var routeEndpointBuilder = new RouteEndpointBuilder(
requestDelegate, requestDelegate,
pattern, pattern,
defaultOrder); defaultOrder);
routeEndpointModel.DisplayName = displayName; routeEndpointBuilder.DisplayName = displayName;
if (metadata != null) if (metadata != null)
{ {
foreach (var item in metadata) foreach (var item in metadata)
{ {
routeEndpointModel.Metadata.Add(item); routeEndpointBuilder.Metadata.Add(item);
} }
} }
@ -203,7 +203,7 @@ namespace Microsoft.AspNetCore.Builder
builder.DataSources.Add(modelEndpointDataSource); builder.DataSources.Add(modelEndpointDataSource);
} }
return modelEndpointDataSource.AddEndpointModel(routeEndpointModel); return modelEndpointDataSource.AddEndpointBuilder(routeEndpointBuilder);
} }
#endregion #endregion
} }

View File

@ -1,19 +0,0 @@
// 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.Collections.Generic;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing
{
public abstract class EndpointModel
{
public RequestDelegate RequestDelegate { get; set; }
public string DisplayName { get; set; }
public IList<object> Metadata { get; } = new List<object>();
public abstract Endpoint Build();
}
}

View File

@ -1,12 +0,0 @@
// 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;
namespace Microsoft.AspNetCore.Routing
{
public interface IEndpointConventionBuilder
{
void Apply(Action<EndpointModel> convention);
}
}

View File

@ -1,9 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // 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 System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
@ -19,9 +20,9 @@ namespace Microsoft.AspNetCore.Routing
_endpointConventionBuilders = new List<EndpointConventionBuilder>(); _endpointConventionBuilders = new List<EndpointConventionBuilder>();
} }
public IEndpointConventionBuilder AddEndpointModel(EndpointModel endpointModel) public IEndpointConventionBuilder AddEndpointBuilder(EndpointBuilder endpointBuilder)
{ {
var builder = new EndpointConventionBuilder(endpointModel); var builder = new EndpointConventionBuilder(endpointBuilder);
_endpointConventionBuilders.Add(builder); _endpointConventionBuilders.Add(builder);
return builder; return builder;
@ -35,21 +36,21 @@ namespace Microsoft.AspNetCore.Routing
public override IReadOnlyList<Endpoint> Endpoints => _endpointConventionBuilders.Select(e => e.Build()).ToArray(); public override IReadOnlyList<Endpoint> Endpoints => _endpointConventionBuilders.Select(e => e.Build()).ToArray();
// for testing // for testing
internal IEnumerable<EndpointModel> EndpointModels => _endpointConventionBuilders.Select(b => b.EndpointModel); internal IEnumerable<EndpointBuilder> EndpointBuilders => _endpointConventionBuilders.Select(b => b.EndpointBuilder);
private class EndpointConventionBuilder : IEndpointConventionBuilder private class EndpointConventionBuilder : IEndpointConventionBuilder
{ {
internal EndpointModel EndpointModel { get; } internal EndpointBuilder EndpointBuilder { get; }
private readonly List<Action<EndpointModel>> _conventions; private readonly List<Action<EndpointBuilder>> _conventions;
public EndpointConventionBuilder(EndpointModel endpointModel) public EndpointConventionBuilder(EndpointBuilder endpointBuilder)
{ {
EndpointModel = endpointModel; EndpointBuilder = endpointBuilder;
_conventions = new List<Action<EndpointModel>>(); _conventions = new List<Action<EndpointBuilder>>();
} }
public void Apply(Action<EndpointModel> convention) public void Add(Action<EndpointBuilder> convention)
{ {
_conventions.Add(convention); _conventions.Add(convention);
} }
@ -58,11 +59,11 @@ namespace Microsoft.AspNetCore.Routing
{ {
foreach (var convention in _conventions) foreach (var convention in _conventions)
{ {
convention(EndpointModel); convention(EndpointBuilder);
} }
return EndpointModel.Build(); return EndpointBuilder.Build();
} }
} }
} }
} }

View File

@ -1,18 +1,19 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.Patterns;
namespace Microsoft.AspNetCore.Routing namespace Microsoft.AspNetCore.Routing
{ {
public sealed class RouteEndpointModel : EndpointModel public sealed class RouteEndpointBuilder : EndpointBuilder
{ {
public RoutePattern RoutePattern { get; set; } public RoutePattern RoutePattern { get; set; }
public int Order { get; set; } public int Order { get; set; }
public RouteEndpointModel( public RouteEndpointBuilder(
RequestDelegate requestDelegate, RequestDelegate requestDelegate,
RoutePattern routePattern, RoutePattern routePattern,
int order) int order)

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
@ -19,9 +19,9 @@ namespace Microsoft.AspNetCore.Builder
return Assert.IsType<ModelEndpointDataSource>(Assert.Single(endpointRouteBuilder.DataSources)); return Assert.IsType<ModelEndpointDataSource>(Assert.Single(endpointRouteBuilder.DataSources));
} }
private RouteEndpointModel GetRouteEndpointBuilder(IEndpointRouteBuilder endpointRouteBuilder) private RouteEndpointBuilder GetRouteEndpointBuilder(IEndpointRouteBuilder endpointRouteBuilder)
{ {
return Assert.IsType<RouteEndpointModel>(Assert.Single(GetBuilderEndpointDataSource(endpointRouteBuilder).EndpointModels)); return Assert.IsType<RouteEndpointBuilder>(Assert.Single(GetBuilderEndpointDataSource(endpointRouteBuilder).EndpointBuilders));
} }
[Fact] [Fact]

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
@ -10,7 +10,7 @@ using Xunit;
namespace Microsoft.AspNetCore.Routing namespace Microsoft.AspNetCore.Routing
{ {
public class RouteEndpointModelTest public class RouteEndpointBuilderTest
{ {
[Fact] [Fact]
public void Build_AllValuesSet_EndpointCreated() public void Build_AllValuesSet_EndpointCreated()
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Routing
var metadata = new object(); var metadata = new object();
RequestDelegate requestDelegate = (d) => null; RequestDelegate requestDelegate = (d) => null;
var builder = new RouteEndpointModel(requestDelegate, RoutePatternFactory.Parse("/"), defaultOrder) var builder = new RouteEndpointBuilder(requestDelegate, RoutePatternFactory.Parse("/"), defaultOrder)
{ {
DisplayName = "Display name!", DisplayName = "Display name!",
Metadata = { metadata } Metadata = { metadata }

View File

@ -1,25 +0,0 @@
// 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.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using RoutingSample.Web.AuthorizationMiddleware;
namespace Microsoft.AspNetCore.Builder
{
public static class AuthorizationAppBuilderExtensions
{
public static IApplicationBuilder UseAuthorization(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
return app.UseMiddleware<AuthorizationMiddleware>();
}
}
}

View File

@ -1,25 +0,0 @@
// 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.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace RoutingSample.Web.AuthorizationMiddleware
{
public class AuthorizationMetadata
{
public AuthorizationMetadata(IEnumerable<string> roles)
{
if (roles == null)
{
throw new ArgumentNullException(nameof(roles));
}
Roles = roles.ToArray();
}
public IReadOnlyList<string> Roles { get; }
}
}

View File

@ -1,59 +0,0 @@
// 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.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
namespace RoutingSample.Web.AuthorizationMiddleware
{
public class AuthorizationMiddleware
{
private readonly ILogger _logger;
private readonly RequestDelegate _next;
public AuthorizationMiddleware(ILogger<AuthorizationMiddleware> logger, RequestDelegate next)
{
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
}
if (next == null)
{
throw new ArgumentNullException(nameof(next));
}
_logger = logger;
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
var endpoint = httpContext.Features.Get<IEndpointFeature>()?.Endpoint;
if (endpoint != null)
{
var metadata = endpoint.Metadata.GetMetadata<AuthorizationMetadata>();
// Only run authorization if endpoint has metadata
if (metadata != null)
{
if (!httpContext.Request.Query.TryGetValue("x-role", out var role) ||
!metadata.Roles.Contains(role.ToString()))
{
httpContext.Response.StatusCode = 401;
httpContext.Response.ContentType = "text/plain";
await httpContext.Response.WriteAsync($"Unauthorized access to '{endpoint.DisplayName}'.");
return;
}
}
}
await _next(httpContext);
}
}
}

View File

@ -1,17 +0,0 @@
// 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 Microsoft.AspNetCore.Routing;
using RoutingSample.Web.AuthorizationMiddleware;
namespace Microsoft.AspNetCore.Builder
{
public static class EndpointConventionBuilderExtensions
{
public static IEndpointConventionBuilder RequireAuthorization(this IEndpointConventionBuilder builder, params string[] roles)
{
builder.Apply(endpointBuilder => endpointBuilder.Metadata.Add(new AuthorizationMetadata(roles)));
return builder;
}
}
}

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.Patterns;
@ -16,7 +17,7 @@ namespace RoutingSandbox.Framework
internal class FrameworkEndpointDataSource : EndpointDataSource, IEndpointConventionBuilder internal class FrameworkEndpointDataSource : EndpointDataSource, IEndpointConventionBuilder
{ {
private readonly RoutePatternTransformer _routePatternTransformer; private readonly RoutePatternTransformer _routePatternTransformer;
private readonly List<Action<EndpointModel>> _conventions; private readonly List<Action<EndpointBuilder>> _conventions;
public List<RoutePattern> Patterns { get; } public List<RoutePattern> Patterns { get; }
public List<HubMethod> HubMethods { get; } public List<HubMethod> HubMethods { get; }
@ -26,7 +27,7 @@ namespace RoutingSandbox.Framework
public FrameworkEndpointDataSource(RoutePatternTransformer routePatternTransformer) public FrameworkEndpointDataSource(RoutePatternTransformer routePatternTransformer)
{ {
_routePatternTransformer = routePatternTransformer; _routePatternTransformer = routePatternTransformer;
_conventions = new List<Action<EndpointModel>>(); _conventions = new List<Action<EndpointBuilder>>();
Patterns = new List<RoutePattern>(); Patterns = new List<RoutePattern>();
HubMethods = new List<HubMethod>(); HubMethods = new List<HubMethod>();
@ -62,18 +63,18 @@ namespace RoutingSandbox.Framework
continue; continue;
} }
var endpointModel = new RouteEndpointModel( var endpointBuilder = new RouteEndpointBuilder(
hubMethod.RequestDelegate, hubMethod.RequestDelegate,
resolvedPattern, resolvedPattern,
order++); order++);
endpointModel.DisplayName = $"{hubMethod.Hub}.{hubMethod.Method}"; endpointBuilder.DisplayName = $"{hubMethod.Hub}.{hubMethod.Method}";
foreach (var convention in _conventions) foreach (var convention in _conventions)
{ {
convention(endpointModel); convention(endpointBuilder);
} }
endpoints.Add(endpointModel.Build()); endpoints.Add(endpointBuilder.Build());
} }
} }
@ -85,7 +86,7 @@ namespace RoutingSandbox.Framework
return NullChangeToken.Singleton; return NullChangeToken.Singleton;
} }
public void Apply(Action<EndpointModel> convention) public void Add(Action<EndpointBuilder> convention)
{ {
_conventions.Add(convention); _conventions.Add(convention);
} }

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Patterns; using Microsoft.AspNetCore.Routing.Patterns;

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;

View File

@ -35,9 +35,6 @@ namespace RoutingSandbox
{ {
builder.MapHello("/helloworld", "World"); builder.MapHello("/helloworld", "World");
builder.MapHello("/helloworld-secret", "Secret World")
.RequireAuthorization("swordfish");
builder.MapGet( builder.MapGet(
"/", "/",
(httpContext) => (httpContext) =>
@ -94,10 +91,6 @@ namespace RoutingSandbox
}); });
app.UseStaticFiles(); app.UseStaticFiles();
app.UseAuthorization();
app.UseEndpoint();
} }
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;

View File

@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Builder
throw new ArgumentNullException(nameof(builder)); throw new ArgumentNullException(nameof(builder));
} }
builder.Apply(endpointBuilder => builder.Add(endpointBuilder =>
{ {
endpointBuilder.Metadata.Add(new EnableCorsAttribute(policyName)); endpointBuilder.Metadata.Add(new EnableCorsAttribute(policyName));
}); });
@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Builder
configurePolicy(policyBuilder); configurePolicy(policyBuilder);
var policy = policyBuilder.Build(); var policy = policyBuilder.Build();
builder.Apply(endpointBuilder => builder.Add(endpointBuilder =>
{ {
endpointBuilder.Metadata.Add(new CorsPolicyMetadata(policy)); endpointBuilder.Metadata.Add(new CorsPolicyMetadata(policy));
}); });

View File

@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Assert // Assert
var addCorsPolicy = Assert.Single(testConventionBuilder.Conventions); var addCorsPolicy = Assert.Single(testConventionBuilder.Conventions);
var endpointModel = new TestEndpointModel(); var endpointModel = new TestEndpointBuilder();
addCorsPolicy(endpointModel); addCorsPolicy(endpointModel);
var endpoint = endpointModel.Build(); var endpoint = endpointModel.Build();
@ -45,9 +45,9 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
// Assert // Assert
var addCorsPolicy = Assert.Single(testConventionBuilder.Conventions); var addCorsPolicy = Assert.Single(testConventionBuilder.Conventions);
var endpointModel = new TestEndpointModel(); var endpointBuilder = new TestEndpointBuilder();
addCorsPolicy(endpointModel); addCorsPolicy(endpointBuilder);
var endpoint = endpointModel.Build(); var endpoint = endpointBuilder.Build();
var metadata = endpoint.Metadata.GetMetadata<ICorsPolicyMetadata>(); var metadata = endpoint.Metadata.GetMetadata<ICorsPolicyMetadata>();
Assert.NotNull(metadata); Assert.NotNull(metadata);
@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
Assert.True(metadata.Policy.AllowAnyOrigin); Assert.True(metadata.Policy.AllowAnyOrigin);
} }
private class TestEndpointModel : EndpointModel private class TestEndpointBuilder : EndpointBuilder
{ {
public override Endpoint Build() public override Endpoint Build()
{ {
@ -65,9 +65,9 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
private class TestEndpointConventionBuilder : IEndpointConventionBuilder private class TestEndpointConventionBuilder : IEndpointConventionBuilder
{ {
public IList<Action<EndpointModel>> Conventions { get; } = new List<Action<EndpointModel>>(); public IList<Action<EndpointBuilder>> Conventions { get; } = new List<Action<EndpointBuilder>>();
public void Apply(Action<EndpointModel> convention) public void Add(Action<EndpointBuilder> convention)
{ {
Conventions.Add(convention); Conventions.Add(convention);
} }

View File

@ -251,6 +251,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleDestination", "CORS\s
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleOrigin", "CORS\samples\SampleOrigin\SampleOrigin.csproj", "{198FFE3B-0346-4856-A6C9-8752D51C4EB3}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleOrigin", "CORS\samples\SampleOrigin\SampleOrigin.csproj", "{198FFE3B-0346-4856-A6C9-8752D51C4EB3}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.IISIntegration", "..\Servers\IIS\src\Microsoft.AspNetCore.Server.IISIntegration\Microsoft.AspNetCore.Server.IISIntegration.csproj", "{F6206539-038C-410A-86F7-3919D49A28C7}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -1377,6 +1379,18 @@ Global
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Release|x64.Build.0 = Release|Any CPU {198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Release|x64.Build.0 = Release|Any CPU
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Release|x86.ActiveCfg = Release|Any CPU {198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Release|x86.ActiveCfg = Release|Any CPU
{198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Release|x86.Build.0 = Release|Any CPU {198FFE3B-0346-4856-A6C9-8752D51C4EB3}.Release|x86.Build.0 = Release|Any CPU
{F6206539-038C-410A-86F7-3919D49A28C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F6206539-038C-410A-86F7-3919D49A28C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F6206539-038C-410A-86F7-3919D49A28C7}.Debug|x64.ActiveCfg = Debug|Any CPU
{F6206539-038C-410A-86F7-3919D49A28C7}.Debug|x64.Build.0 = Debug|Any CPU
{F6206539-038C-410A-86F7-3919D49A28C7}.Debug|x86.ActiveCfg = Debug|Any CPU
{F6206539-038C-410A-86F7-3919D49A28C7}.Debug|x86.Build.0 = Debug|Any CPU
{F6206539-038C-410A-86F7-3919D49A28C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F6206539-038C-410A-86F7-3919D49A28C7}.Release|Any CPU.Build.0 = Release|Any CPU
{F6206539-038C-410A-86F7-3919D49A28C7}.Release|x64.ActiveCfg = Release|Any CPU
{F6206539-038C-410A-86F7-3919D49A28C7}.Release|x64.Build.0 = Release|Any CPU
{F6206539-038C-410A-86F7-3919D49A28C7}.Release|x86.ActiveCfg = Release|Any CPU
{F6206539-038C-410A-86F7-3919D49A28C7}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -1486,6 +1500,7 @@ Global
{E025D98E-BD85-474A-98A9-E7F44F392F8E} = {4967DE1B-FEC2-4C2B-8F7F-6262D67C9434} {E025D98E-BD85-474A-98A9-E7F44F392F8E} = {4967DE1B-FEC2-4C2B-8F7F-6262D67C9434}
{52CDD110-77DD-4C4D-8C72-4570F6EF20DD} = {7CF63806-4C4F-4C48-8922-A75113975308} {52CDD110-77DD-4C4D-8C72-4570F6EF20DD} = {7CF63806-4C4F-4C48-8922-A75113975308}
{198FFE3B-0346-4856-A6C9-8752D51C4EB3} = {7CF63806-4C4F-4C48-8922-A75113975308} {198FFE3B-0346-4856-A6C9-8752D51C4EB3} = {7CF63806-4C4F-4C48-8922-A75113975308}
{F6206539-038C-410A-86F7-3919D49A28C7} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {83786312-A93B-4BB4-AB06-7C6913A59AFA} SolutionGuid = {83786312-A93B-4BB4-AB06-7C6913A59AFA}

View File

@ -11,12 +11,12 @@ namespace Microsoft.AspNetCore.Builder
{ {
public DefaultEndpointConventionBuilder() public DefaultEndpointConventionBuilder()
{ {
Conventions = new List<Action<EndpointModel>>(); Conventions = new List<Action<EndpointBuilder>>();
} }
public List<Action<EndpointModel>> Conventions { get; } public List<Action<EndpointBuilder>> Conventions { get; }
public void Apply(Action<EndpointModel> convention) public void Add(Action<EndpointBuilder> convention)
{ {
Conventions.Add(convention); Conventions.Add(convention);
} }

View File

@ -269,7 +269,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing
RouteValueDictionary dataTokens, RouteValueDictionary dataTokens,
bool suppressLinkGeneration, bool suppressLinkGeneration,
bool suppressPathMatching, bool suppressPathMatching,
List<Action<EndpointModel>> conventions) List<Action<EndpointBuilder>> conventions)
{ {
RequestDelegate requestDelegate = (context) => RequestDelegate requestDelegate = (context) =>
{ {
@ -281,17 +281,16 @@ namespace Microsoft.AspNetCore.Mvc.Routing
return invoker.InvokeAsync(); return invoker.InvokeAsync();
}; };
var model = new RouteEndpointModel(requestDelegate, routePattern, order); var endpointBuilder = new RouteEndpointBuilder(requestDelegate, routePattern, order);
AddEndpointMetadata( AddEndpointMetadata(
model.Metadata, endpointBuilder.Metadata,
action, action,
routeName, routeName,
dataTokens, dataTokens,
suppressLinkGeneration, suppressLinkGeneration,
suppressPathMatching); suppressPathMatching);
model.DisplayName = action.DisplayName; endpointBuilder.DisplayName = action.DisplayName;
// REVIEW: When should conventions be run // REVIEW: When should conventions be run
// Metadata should have lower precedence that data source metadata // Metadata should have lower precedence that data source metadata
@ -299,11 +298,11 @@ namespace Microsoft.AspNetCore.Mvc.Routing
{ {
foreach (var convention in conventions) foreach (var convention in conventions)
{ {
convention(model); convention(endpointBuilder);
} }
} }
return (RouteEndpoint)model.Build(); return (RouteEndpoint)endpointBuilder.Build();
} }
private static void AddEndpointMetadata( private static void AddEndpointMetadata(

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Builder
throw new ArgumentNullException(nameof(authorizeData)); throw new ArgumentNullException(nameof(authorizeData));
} }
builder.Apply(endpointBuilder => builder.Add(endpointBuilder =>
{ {
foreach (var data in authorizeData) foreach (var data in authorizeData)
{ {
@ -47,4 +47,4 @@ namespace Microsoft.AspNetCore.Builder
return builder.RequireAuthorization(policyNames.Select(n => new AuthorizeAttribute(n)).ToArray()); return builder.RequireAuthorization(policyNames.Select(n => new AuthorizeAttribute(n)).ToArray());
} }
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Authorization.Test
// Assert // Assert
var convention = Assert.Single(builder.Conventions); var convention = Assert.Single(builder.Conventions);
var endpointModel = new RouteEndpointModel((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0); var endpointModel = new RouteEndpointBuilder((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);
convention(endpointModel); convention(endpointModel);
Assert.Equal(metadata, Assert.Single(endpointModel.Metadata)); Assert.Equal(metadata, Assert.Single(endpointModel.Metadata));
@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Authorization.Test
// Assert // Assert
var convention = Assert.Single(builder.Conventions); var convention = Assert.Single(builder.Conventions);
var endpointModel = new RouteEndpointModel((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0); var endpointModel = new RouteEndpointBuilder((context) => Task.CompletedTask, RoutePatternFactory.Parse("/"), 0);
convention(endpointModel); convention(endpointModel);
Assert.Equal("policy", Assert.IsAssignableFrom<IAuthorizeData>(Assert.Single(endpointModel.Metadata)).Policy); Assert.Equal("policy", Assert.IsAssignableFrom<IAuthorizeData>(Assert.Single(endpointModel.Metadata)).Policy);
@ -52,9 +52,9 @@ namespace Microsoft.AspNetCore.Authorization.Test
private class TestEndpointConventionBuilder : IEndpointConventionBuilder private class TestEndpointConventionBuilder : IEndpointConventionBuilder
{ {
public IList<Action<EndpointModel>> Conventions { get; } = new List<Action<EndpointModel>>(); public IList<Action<EndpointBuilder>> Conventions { get; } = new List<Action<EndpointBuilder>>();
public void Apply(Action<EndpointModel> convention) public void Add(Action<EndpointBuilder> convention)
{ {
Conventions.Add(convention); Conventions.Add(convention);
} }