Merge pull request #461 from aspnet/rynowak/endpoints-and-addresses
Making endpoints and addresses easier
This commit is contained in:
commit
9c30dd1256
|
|
@ -23,11 +23,11 @@ namespace DispatcherSample
|
|||
for (var i = context.Endpoints.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var endpoint = context.Endpoints[i];
|
||||
IHttpMethodMetadata metadata = null;
|
||||
ITemplateEndpoint metadata = null;
|
||||
|
||||
for (var j = endpoint.Metadata.Count - 1; j >= 0; j--)
|
||||
{
|
||||
metadata = endpoint.Metadata[j] as IHttpMethodMetadata;
|
||||
metadata = endpoint.Metadata[j] as ITemplateEndpoint;
|
||||
if (metadata != null)
|
||||
{
|
||||
break;
|
||||
|
|
@ -70,17 +70,9 @@ namespace DispatcherSample
|
|||
}
|
||||
}
|
||||
|
||||
private bool Matches(IHttpMethodMetadata metadata, string httpMethod)
|
||||
private bool Matches(ITemplateEndpoint endpoint, string httpMethod)
|
||||
{
|
||||
for (var i = 0; i < metadata.AllowedMethods.Count; i++)
|
||||
{
|
||||
if (string.Equals(metadata.AllowedMethods[i], httpMethod, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return string.Equals(endpoint.HttpMethod, httpMethod, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +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;
|
||||
|
||||
namespace DispatcherSample
|
||||
{
|
||||
public class HttpMethodMetadata : IHttpMethodMetadata
|
||||
{
|
||||
public HttpMethodMetadata(string httpMethod)
|
||||
{
|
||||
if (httpMethod == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(httpMethod));
|
||||
}
|
||||
|
||||
AllowedMethods = new[] { httpMethod, };
|
||||
}
|
||||
|
||||
public IReadOnlyList<string> AllowedMethods { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Collections.Generic;
|
||||
|
||||
namespace DispatcherSample
|
||||
{
|
||||
public interface IHttpMethodMetadata
|
||||
{
|
||||
IReadOnlyList<string> AllowedMethods { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
// 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.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
|
@ -32,27 +31,27 @@ namespace DispatcherSample
|
|||
{
|
||||
Addresses =
|
||||
{
|
||||
new DispatcherValueAddress(new { controller = "Home", action = "Index", }, new object[]{ new RouteTemplateMetadata("{controller=Home}/{action=Index}/{id?}"), }, "Home:Index()"),
|
||||
new DispatcherValueAddress(new { controller = "Home", action = "About", }, new object[]{ new RouteTemplateMetadata("{controller=Home}/{action=Index}/{id?}"), }, "Home:About()"),
|
||||
new DispatcherValueAddress(new { controller = "Admin", action = "Index", }, new object[]{ new RouteTemplateMetadata("{controller=Home}/{action=Index}/{id?}"), }, "Admin:Index()"),
|
||||
new DispatcherValueAddress(new { controller = "Admin", action = "Users", }, new object[]{ new RouteTemplateMetadata("{controller=Home}/{action=Index}/{id?}"), }, "Admin:GetUsers()/Admin:EditUsers()"),
|
||||
new TemplateAddress("{controller=Home}/{action=Index}/{id?}", new { controller = "Home", action = "Index", }, "Home:Index()"),
|
||||
new TemplateAddress("{controller=Home}/{action=Index}/{id?}", new { controller = "Home", action = "About", }, "Home:About()"),
|
||||
new TemplateAddress("{controller=Home}/{action=Index}/{id?}", new { controller = "Admin", action = "Index", }, "Admin:Index()"),
|
||||
new TemplateAddress("{controller=Home}/{action=Index}/{id?}", new { controller = "Admin", action = "Users", }, "Admin:GetUsers()/Admin:EditUsers()"),
|
||||
},
|
||||
Endpoints =
|
||||
{
|
||||
new SimpleEndpoint(Home_Index, new object[] { new RouteTemplateMetadata("{controller=Home}/{action=Index}/{id?}"), }, new { controller = "Home", action = "Index", }, "Home:Index()"),
|
||||
new SimpleEndpoint(Home_About, new object[] { new RouteTemplateMetadata("{controller=Home}/{action=Index}/{id?}"), }, new { controller = "Home", action = "About", }, "Home:About()"),
|
||||
new SimpleEndpoint(Admin_Index, new object[] { new RouteTemplateMetadata("{controller=Home}/{action=Index}/{id?}"), }, new { controller = "Admin", action = "Index", }, "Admin:Index()"),
|
||||
new SimpleEndpoint(Admin_GetUsers, new object[] { new RouteTemplateMetadata("{controller=Home}/{action=Index}/{id?}"), new HttpMethodMetadata("GET"), new AuthorizationPolicyMetadata("Admin"), }, new { controller = "Admin", action = "Users", }, "Admin:GetUsers()"),
|
||||
new SimpleEndpoint(Admin_EditUsers, new object[] { new RouteTemplateMetadata("{controller=Home}/{action=Index}/{id?}"), new HttpMethodMetadata("POST"), new AuthorizationPolicyMetadata("Admin"), }, new { controller = "Admin", action = "Users", }, "Admin:EditUsers()"),
|
||||
new TemplateEndpoint("{controller=Home}/{action=Index}/{id?}", new { controller = "Home", action = "Index", }, Home_Index, "Home:Index()"),
|
||||
new TemplateEndpoint("{controller=Home}/{action=Index}/{id?}", new { controller = "Home", action = "About", }, Home_About, "Home:About()"),
|
||||
new TemplateEndpoint("{controller=Home}/{action=Index}/{id?}", new { controller = "Admin", action = "Index", }, Admin_Index, "Admin:Index()"),
|
||||
new TemplateEndpoint("{controller=Home}/{action=Index}/{id?}", new { controller = "Admin", action = "Users", }, "GET", Admin_GetUsers, "Admin:GetUsers()", new AuthorizationPolicyMetadata("Admin")),
|
||||
new TemplateEndpoint("{controller=Home}/{action=Index}/{id?}", new { controller = "Admin", action = "Users", }, "POST", Admin_EditUsers, "Admin:EditUsers()", new AuthorizationPolicyMetadata("Admin")),
|
||||
},
|
||||
Selectors =
|
||||
{
|
||||
new DispatcherValueEndpointSelector(),
|
||||
new TemplateEndpointSelector(),
|
||||
new HttpMethodEndpointSelector(),
|
||||
}
|
||||
});
|
||||
|
||||
options.HandlerFactories.Add((endpoint) => (endpoint as SimpleEndpoint)?.HandlerFactory);
|
||||
options.HandlerFactories.Add((endpoint) => (endpoint as TemplateEndpoint)?.HandlerFactory);
|
||||
});
|
||||
|
||||
services.AddDispatcher();
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ using Microsoft.Extensions.Primitives;
|
|||
|
||||
namespace Microsoft.AspNetCore.Dispatcher
|
||||
{
|
||||
public class SimpleDispatcherDataSource : DispatcherDataSource
|
||||
public class DefaultDispatcherDataSource : DispatcherDataSource
|
||||
{
|
||||
private readonly List<Address> _addresses;
|
||||
private readonly List<Endpoint> _endpoints;
|
||||
|
||||
public SimpleDispatcherDataSource()
|
||||
public DefaultDispatcherDataSource()
|
||||
{
|
||||
_addresses = new List<Address>();
|
||||
_endpoints = new List<Endpoint>();
|
||||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
|
||||
services.AddSingleton<IStartupFilter, DispatcherEndpointStartupFilter>();
|
||||
services.AddSingleton<AddressTable, DefaultAddressTable>();
|
||||
services.AddSingleton<DispatcherValueAddressSelector>();
|
||||
services.AddSingleton<TemplateAddressSelector>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@
|
|||
|
||||
namespace Microsoft.AspNetCore.Dispatcher
|
||||
{
|
||||
public interface IDispatcherValueSelectableEndpoint
|
||||
public interface ITemplateAddress
|
||||
{
|
||||
string Template { get; }
|
||||
|
||||
DispatcherValueCollection Values { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Dispatcher
|
||||
{
|
||||
public interface ITemplateEndpoint
|
||||
{
|
||||
string HttpMethod { get; }
|
||||
|
||||
string Template { get; }
|
||||
|
||||
DispatcherValueCollection Values { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,82 +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 Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Dispatcher
|
||||
{
|
||||
public class SimpleEndpoint : Endpoint, IDispatcherValueSelectableEndpoint
|
||||
{
|
||||
public SimpleEndpoint(RequestDelegate requestDelegate)
|
||||
: this(requestDelegate, Array.Empty<object>(), null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public SimpleEndpoint(Func<RequestDelegate, RequestDelegate> delegateFactory)
|
||||
: this(delegateFactory, Array.Empty<object>(), null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public SimpleEndpoint(RequestDelegate requestDelegate, IEnumerable<object> metadata)
|
||||
: this(requestDelegate, metadata, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public SimpleEndpoint(Func<RequestDelegate, RequestDelegate> delegateFactory, IEnumerable<object> metadata)
|
||||
: this(delegateFactory, metadata, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public SimpleEndpoint(Func<RequestDelegate, RequestDelegate> delegateFactory, IEnumerable<object> metadata, object values)
|
||||
: this(delegateFactory, metadata, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public SimpleEndpoint(RequestDelegate requestDelegate, IEnumerable<object> metadata, object values, string displayName)
|
||||
{
|
||||
if (metadata == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(metadata));
|
||||
}
|
||||
|
||||
if (requestDelegate == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(requestDelegate));
|
||||
}
|
||||
|
||||
HandlerFactory = (next) => requestDelegate;
|
||||
Metadata = metadata.ToArray();
|
||||
Values = new DispatcherValueCollection(values);
|
||||
DisplayName = displayName;
|
||||
}
|
||||
|
||||
public SimpleEndpoint(Func<RequestDelegate, RequestDelegate> delegateFactory, IEnumerable<object> metadata, object values, string displayName)
|
||||
{
|
||||
if (metadata == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(metadata));
|
||||
}
|
||||
|
||||
if (delegateFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(delegateFactory));
|
||||
}
|
||||
|
||||
HandlerFactory = delegateFactory;
|
||||
Metadata = metadata.ToArray();
|
||||
Values = new DispatcherValueCollection(values);
|
||||
DisplayName = displayName;
|
||||
}
|
||||
|
||||
public override string DisplayName { get; }
|
||||
|
||||
public override IReadOnlyList<object> Metadata { get; }
|
||||
|
||||
public Func<RequestDelegate, RequestDelegate> HandlerFactory { get; }
|
||||
|
||||
public DispatcherValueCollection Values { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -7,24 +7,18 @@ using System.Linq;
|
|||
|
||||
namespace Microsoft.AspNetCore.Dispatcher
|
||||
{
|
||||
public class DispatcherValueAddress : Address
|
||||
public class TemplateAddress : Address, ITemplateAddress
|
||||
{
|
||||
public DispatcherValueAddress(object values)
|
||||
: this(values, Array.Empty<object>(), null)
|
||||
public TemplateAddress(string template, object values, params object[] metadata)
|
||||
: this(template, values, null, metadata)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public DispatcherValueAddress(object values, IEnumerable<object> metadata)
|
||||
: this(values, metadata, null)
|
||||
public TemplateAddress(string template, object values, string displayName, params object[] metadata)
|
||||
{
|
||||
}
|
||||
|
||||
public DispatcherValueAddress(object values, IEnumerable<object> metadata, string displayName)
|
||||
{
|
||||
if (values == null)
|
||||
if (template == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(values));
|
||||
throw new ArgumentNullException(nameof(template));
|
||||
}
|
||||
|
||||
if (metadata == null)
|
||||
|
|
@ -32,15 +26,18 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
throw new ArgumentNullException(nameof(metadata));
|
||||
}
|
||||
|
||||
Template = template;
|
||||
Values = new DispatcherValueCollection(values);
|
||||
Metadata = metadata.ToArray();
|
||||
DisplayName = displayName;
|
||||
Metadata = metadata.ToArray();
|
||||
}
|
||||
|
||||
public override string DisplayName { get; }
|
||||
|
||||
public override IReadOnlyList<object> Metadata { get; }
|
||||
|
||||
public string Template { get; }
|
||||
|
||||
public DispatcherValueCollection Values { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -7,11 +7,11 @@ using System.Collections.Generic;
|
|||
namespace Microsoft.AspNetCore.Dispatcher
|
||||
{
|
||||
// This isn't a proposed design, just a placeholder to demonstrate that things are wired up correctly.
|
||||
public class DispatcherValueAddressSelector
|
||||
public class TemplateAddressSelector
|
||||
{
|
||||
private readonly AddressTable _addressTable;
|
||||
|
||||
public DispatcherValueAddressSelector(AddressTable addressTable)
|
||||
public TemplateAddressSelector(AddressTable addressTable)
|
||||
{
|
||||
if (addressTable == null)
|
||||
{
|
||||
|
|
@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
|
||||
for (var j = 0; j < group.Count; j++)
|
||||
{
|
||||
var address = group[j] as DispatcherValueAddress;
|
||||
var address = group[j] as ITemplateAddress;
|
||||
if (address == null)
|
||||
{
|
||||
continue;
|
||||
|
|
@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
|
||||
if (IsMatch(address, values))
|
||||
{
|
||||
matches.Add(address);
|
||||
matches.Add(group[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
return null;
|
||||
}
|
||||
|
||||
private bool IsMatch(DispatcherValueAddress address, DispatcherValueCollection values)
|
||||
private bool IsMatch(ITemplateAddress address, DispatcherValueCollection values)
|
||||
{
|
||||
foreach (var kvp in address.Values)
|
||||
{
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
// 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 Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Dispatcher
|
||||
{
|
||||
public class TemplateEndpoint : Endpoint, ITemplateEndpoint
|
||||
{
|
||||
public TemplateEndpoint(string template, RequestDelegate requestDelegate, params object[] metadata)
|
||||
: this(template, (object)null, (string)null, requestDelegate, null, metadata)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateEndpoint(string template, Func<RequestDelegate, RequestDelegate> delegateFactory, params object[] metadata)
|
||||
: this(template, (object)null, (string)null, delegateFactory, null, metadata)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateEndpoint(string template, object values, RequestDelegate requestDelegate, params object[] metadata)
|
||||
: this(template, values, null, requestDelegate, null, metadata)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateEndpoint(string template, object values, Func<RequestDelegate, RequestDelegate> delegateFactory, params object[] metadata)
|
||||
: this(template, values, null, delegateFactory, null, metadata)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateEndpoint(string template, object values, RequestDelegate requestDelegate, string displayName, params object[] metadata)
|
||||
: this(template, values, null, requestDelegate, displayName, metadata)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateEndpoint(string template, object values, Func<RequestDelegate, RequestDelegate> delegateFactory, string displayName, params object[] metadata)
|
||||
: this(template, values, null, delegateFactory, displayName, metadata)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateEndpoint(string template, object values, string httpMethod, RequestDelegate requestDelegate, params object[] metadata)
|
||||
: this(template, values, httpMethod, requestDelegate, null, metadata)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateEndpoint(string template, object values, string httpMethod, Func<RequestDelegate, RequestDelegate> delegateFactory, params object[] metadata)
|
||||
: this(template, values, httpMethod, delegateFactory, null, metadata)
|
||||
{
|
||||
}
|
||||
|
||||
public TemplateEndpoint(
|
||||
string template,
|
||||
object values,
|
||||
string httpMethod,
|
||||
RequestDelegate requestDelegate,
|
||||
string displayName,
|
||||
params object[] metadata)
|
||||
{
|
||||
if (template == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(template));
|
||||
}
|
||||
|
||||
if (requestDelegate == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(requestDelegate));
|
||||
}
|
||||
|
||||
if (metadata == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(metadata));
|
||||
}
|
||||
|
||||
Template = template;
|
||||
Values = new DispatcherValueCollection(values);
|
||||
HttpMethod = httpMethod;
|
||||
HandlerFactory = (next) => requestDelegate;
|
||||
DisplayName = displayName;
|
||||
Metadata = metadata.ToArray();
|
||||
}
|
||||
|
||||
public TemplateEndpoint(
|
||||
string template,
|
||||
object values,
|
||||
string httpMethod,
|
||||
Func<RequestDelegate, RequestDelegate> delegateFactory,
|
||||
string displayName,
|
||||
params object[] metadata)
|
||||
{
|
||||
if (template == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(template));
|
||||
}
|
||||
|
||||
if (delegateFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(delegateFactory));
|
||||
}
|
||||
|
||||
if (metadata == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(metadata));
|
||||
}
|
||||
|
||||
Template = template;
|
||||
Values = new DispatcherValueCollection(values);
|
||||
HttpMethod = httpMethod;
|
||||
HandlerFactory = delegateFactory;
|
||||
DisplayName = displayName;
|
||||
Metadata = metadata.ToArray();
|
||||
}
|
||||
|
||||
public override string DisplayName { get; }
|
||||
|
||||
public string HttpMethod { get; }
|
||||
|
||||
public override IReadOnlyList<object> Metadata { get; }
|
||||
|
||||
public Func<RequestDelegate, RequestDelegate> HandlerFactory { get; }
|
||||
|
||||
public string Template { get; }
|
||||
|
||||
public DispatcherValueCollection Values { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Microsoft.AspNetCore.Dispatcher
|
||||
{
|
||||
public class DispatcherValueEndpointSelector : EndpointSelector
|
||||
public class TemplateEndpointSelector : EndpointSelector
|
||||
{
|
||||
public override Task SelectAsync(EndpointSelectorContext context)
|
||||
{
|
||||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Dispatcher
|
|||
|
||||
for (var i = context.Endpoints.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var endpoint = context.Endpoints[i] as IDispatcherValueSelectableEndpoint;
|
||||
var endpoint = context.Endpoints[i] as ITemplateEndpoint;
|
||||
if (!CompareRouteValues(dispatcherFeature.Values, endpoint.Values))
|
||||
{
|
||||
context.Endpoints.RemoveAt(i);
|
||||
|
|
@ -1,14 +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.Dispatcher;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Dispatcher
|
||||
{
|
||||
public interface IRouteTemplateMetadata
|
||||
{
|
||||
string RouteTemplate { get; }
|
||||
|
||||
DispatcherValueCollection Defaults { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Dispatcher
|
||||
{
|
||||
public interface ITreeDispatcherMetadata
|
||||
{
|
||||
int Order { get; }
|
||||
|
||||
string RouteTemplate { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +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 Microsoft.AspNetCore.Dispatcher;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Dispatcher
|
||||
{
|
||||
public class RouteTemplateMetadata : IRouteTemplateMetadata, ITreeDispatcherMetadata
|
||||
{
|
||||
public RouteTemplateMetadata(string routeTemplate)
|
||||
: this(routeTemplate, null)
|
||||
{
|
||||
}
|
||||
|
||||
public RouteTemplateMetadata(string routeTemplate, object defaults)
|
||||
{
|
||||
if (routeTemplate == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(routeTemplate));
|
||||
}
|
||||
|
||||
RouteTemplate = routeTemplate;
|
||||
Defaults = new DispatcherValueCollection(defaults);
|
||||
}
|
||||
|
||||
public string RouteTemplate { get; }
|
||||
|
||||
public DispatcherValueCollection Defaults { get; }
|
||||
|
||||
public int Order { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -14,11 +14,11 @@ namespace Microsoft.AspNetCore.Routing.Dispatcher
|
|||
// This isn't a proposed design, just a placeholder to demonstrate that things are wired up correctly.
|
||||
public class RouteTemplateUrlGenerator
|
||||
{
|
||||
private readonly DispatcherValueAddressSelector _addressSelector;
|
||||
private readonly TemplateAddressSelector _addressSelector;
|
||||
private readonly ObjectPool<UriBuildingContext> _pool;
|
||||
private readonly UrlEncoder _urlEncoder;
|
||||
|
||||
public RouteTemplateUrlGenerator(DispatcherValueAddressSelector addressSelector, UrlEncoder urlEncoder, ObjectPool<UriBuildingContext> pool)
|
||||
public RouteTemplateUrlGenerator(TemplateAddressSelector addressSelector, UrlEncoder urlEncoder, ObjectPool<UriBuildingContext> pool)
|
||||
{
|
||||
_addressSelector = addressSelector;
|
||||
_urlEncoder = urlEncoder;
|
||||
|
|
@ -37,14 +37,13 @@ namespace Microsoft.AspNetCore.Routing.Dispatcher
|
|||
throw new ArgumentNullException(nameof(values));
|
||||
}
|
||||
|
||||
var address = _addressSelector.SelectAddress(new DispatcherValueCollection(values));
|
||||
var address = _addressSelector.SelectAddress(new DispatcherValueCollection(values)) as ITemplateAddress;
|
||||
if (address == null)
|
||||
{
|
||||
throw new InvalidOperationException("Can't find address");
|
||||
}
|
||||
|
||||
var (template, defaults) = GetRouteTemplate(address);
|
||||
var binder = new TemplateBinder(_urlEncoder, _pool, TemplateParser.Parse(template), defaults.AsRouteValueDictionary());
|
||||
var binder = new TemplateBinder(_urlEncoder, _pool, TemplateParser.Parse(address.Template), new RouteValueDictionary());
|
||||
|
||||
var feature = httpContext.Features.Get<IDispatcherFeature>();
|
||||
var result = binder.GetValues(feature.Values.AsRouteValueDictionary(), new RouteValueDictionary(values));
|
||||
|
|
@ -55,18 +54,5 @@ namespace Microsoft.AspNetCore.Routing.Dispatcher
|
|||
|
||||
return binder.BindValues(result.AcceptedValues);
|
||||
}
|
||||
private (string, DispatcherValueCollection) GetRouteTemplate(Address address)
|
||||
{
|
||||
for (var i = address.Metadata.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var metadata = address.Metadata[i] as IRouteTemplateMetadata;
|
||||
if (metadata != null)
|
||||
{
|
||||
return (metadata.RouteTemplate, metadata.Defaults);
|
||||
}
|
||||
}
|
||||
|
||||
return (null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,16 +142,16 @@ namespace Microsoft.AspNetCore.Routing.Dispatcher
|
|||
{
|
||||
var endpoint = endpoints[i];
|
||||
|
||||
var metadata = endpoint.Metadata.OfType<ITreeDispatcherMetadata>().LastOrDefault();
|
||||
if (metadata == null)
|
||||
var templateEndpoint = endpoint as ITemplateEndpoint;
|
||||
if (templateEndpoint == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!groups.TryGetValue(new Key(metadata.Order, metadata.RouteTemplate), out var group))
|
||||
if (!groups.TryGetValue(new Key(0, templateEndpoint.Template), out var group))
|
||||
{
|
||||
group = new List<Endpoint>();
|
||||
groups.Add(new Key(metadata.Order, metadata.RouteTemplate), group);
|
||||
groups.Add(new Key(0, templateEndpoint.Template), group);
|
||||
}
|
||||
|
||||
group.Add(endpoint);
|
||||
|
|
|
|||
|
|
@ -58,11 +58,11 @@ namespace Microsoft.AspNetCore.Dispatcher.FunctionalTest
|
|||
{
|
||||
Endpoints =
|
||||
{
|
||||
new SimpleEndpoint(Products_Get, new object[]{ new RouteTemplateMetadata("api/products"), }),
|
||||
new TemplateEndpoint("api/products", Products_Get),
|
||||
},
|
||||
});
|
||||
|
||||
options.HandlerFactories.Add(endpoint => (endpoint as SimpleEndpoint)?.HandlerFactory);
|
||||
options.HandlerFactories.Add(endpoint => (endpoint as TemplateEndpoint)?.HandlerFactory);
|
||||
}
|
||||
|
||||
private Task Products_Get(HttpContext httpContext) => httpContext.Response.WriteAsync("Hello, Products_Get");
|
||||
|
|
|
|||
Loading…
Reference in New Issue