aspnetcore/test/Microsoft.AspNetCore.Mvc.Co.../Routing/EndpointRoutingUrlHelperTes...

332 lines
14 KiB
C#

// 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.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Routing
{
public class EndpointRoutingUrlHelperTest : UrlHelperTestBase
{
[Fact]
public void RouteUrl_WithRouteName_GeneratesUrl_UsingDefaults()
{
// Arrange
var endpoint1 = CreateEndpoint(
"api/orders/{id}",
defaults: new { controller = "Orders", action = "GetById" },
requiredValues: new { controller = "Orders", action = "GetById" },
routeName: "OrdersApi");
var endpoint2 = CreateEndpoint(
"api/orders",
defaults: new { controller = "Orders", action = "GetAll" },
requiredValues: new { controller = "Orders", action = "GetAll" },
routeName: "OrdersApi");
var urlHelper = CreateUrlHelper(new[] { endpoint1, endpoint2 });
// Act
var url = urlHelper.RouteUrl(
routeName: "OrdersApi",
values: new { });
// Assert
Assert.Equal("/" + endpoint2.RoutePattern.RawText, url);
}
[Fact]
public void RouteUrl_WithRouteName_UsesAmbientValues()
{
// Arrange
var endpoint1 = CreateEndpoint(
"api/orders/{id}",
defaults: new { controller = "Orders", action = "GetById" },
requiredValues: new { controller = "Orders", action = "GetById" },
routeName: "OrdersApi");
var endpoint2 = CreateEndpoint(
"api/orders",
defaults: new { controller = "Orders", action = "GetAll" },
requiredValues: new { controller = "Orders", action = "GetAll" },
routeName: "OrdersApi");
var urlHelper = CreateUrlHelper(new[] { endpoint1, endpoint2 });
// Set the endpoint feature and current context just as a normal request to MVC app would be
var endpointFeature = new EndpointFeature();
urlHelper.ActionContext.HttpContext.Features.Set<IEndpointFeature>(endpointFeature);
urlHelper.ActionContext.HttpContext.Features.Set<IRouteValuesFeature>(endpointFeature);
endpointFeature.Endpoint = endpoint1;
endpointFeature.RouteValues = new RouteValueDictionary
{
["controller"] = "Orders",
["action"] = "GetById",
["id"] = "500"
};
// Act
var url = urlHelper.RouteUrl(
routeName: "OrdersApi",
values: new { });
// Assert
Assert.Equal("/api/orders/500", url);
}
[Fact]
public void RouteUrl_WithRouteName_UsesSuppliedValue_OverridingAmbientValue()
{
// Arrange
var endpoint1 = CreateEndpoint(
"api/orders/{id}",
defaults: new { controller = "Orders", action = "GetById" },
requiredValues: new { controller = "Orders", action = "GetById" },
routeName: "OrdersApi");
var endpoint2 = CreateEndpoint(
"api/orders",
defaults: new { controller = "Orders", action = "GetAll" },
requiredValues: new { controller = "Orders", action = "GetAll" },
routeName: "OrdersApi");
var urlHelper = CreateUrlHelper(new[] { endpoint1, endpoint2 });
urlHelper.ActionContext.RouteData.Values["id"] = "500";
// Act
var url = urlHelper.RouteUrl(
routeName: "OrdersApi",
values: new { id = "10" });
// Assert
Assert.Equal("/api/orders/10", url);
}
[Fact]
public void RouteUrl_DoesNotGenerateLink_ToEndpointsWithSuppressLinkGeneration()
{
// Arrange
var endpoint = CreateEndpoint(
"Home/Index",
defaults: new { controller = "Home", action = "Index" },
requiredValues: new { controller = "Home", action = "Index" },
metadataCollection: new EndpointMetadataCollection(new[] { new SuppressLinkGenerationMetadata() }));
var urlHelper = CreateUrlHelper(new[] { endpoint });
// Act
var url = urlHelper.RouteUrl(new { controller = "Home", action = "Index" });
// Assert
Assert.Null(url);
}
protected override IUrlHelper CreateUrlHelper(string appRoot, string host, string protocol)
{
return CreateUrlHelper(Enumerable.Empty<RouteEndpoint>(), appRoot, host, protocol);
}
protected override IUrlHelper CreateUrlHelperWithDefaultRoutes(string appRoot, string host, string protocol)
{
return CreateUrlHelper(GetDefaultEndpoints(), appRoot, host, protocol);
}
protected override IUrlHelper CreateUrlHelperWithDefaultRoutes(
string appRoot,
string host,
string protocol,
string routeName,
string template)
{
var endpoints = GetDefaultEndpoints();
endpoints.Add(new RouteEndpoint(
httpContext => Task.CompletedTask,
RoutePatternFactory.Parse(template),
0,
EndpointMetadataCollection.Empty,
null));
return CreateUrlHelper(endpoints, appRoot, host, protocol);
}
protected override IUrlHelper CreateUrlHelper(ActionContext actionContext)
{
var httpContext = actionContext.HttpContext;
httpContext.Features.Set<IEndpointFeature>(new EndpointFeature()
{
Endpoint = new Endpoint(
context => Task.CompletedTask,
EndpointMetadataCollection.Empty,
null)
});
var urlHelperFactory = httpContext.RequestServices.GetRequiredService<IUrlHelperFactory>();
var urlHelper = urlHelperFactory.GetUrlHelper(actionContext);
Assert.IsType<EndpointRoutingUrlHelper>(urlHelper);
return urlHelper;
}
protected override IServiceProvider CreateServices()
{
return CreateServices(Enumerable.Empty<Endpoint>());
}
protected override IUrlHelper CreateUrlHelper(
string appRoot,
string host,
string protocol,
string routeName,
string template,
object defaults)
{
var endpoint = GetEndpoint(routeName, template, new RouteValueDictionary(defaults));
var services = CreateServices(new[] { endpoint });
var httpContext = CreateHttpContext(services, appRoot: "", host: null, protocol: null);
var actionContext = CreateActionContext(httpContext);
return CreateUrlHelper(actionContext);
}
private IUrlHelper CreateUrlHelper(IEnumerable<RouteEndpoint> endpoints, ActionContext actionContext = null)
{
var serviceProvider = CreateServices(endpoints);
var httpContext = CreateHttpContext(serviceProvider, null, null, "http");
actionContext = actionContext ?? CreateActionContext(httpContext);
return CreateUrlHelper(actionContext);
}
private IUrlHelper CreateUrlHelper(
IEnumerable<RouteEndpoint> endpoints,
string appRoot,
string host,
string protocol)
{
var serviceProvider = CreateServices(endpoints);
var httpContext = CreateHttpContext(serviceProvider, appRoot, host, protocol);
var actionContext = CreateActionContext(httpContext);
return CreateUrlHelper(actionContext);
}
private List<RouteEndpoint> GetDefaultEndpoints()
{
var endpoints = new List<RouteEndpoint>();
endpoints.Add(
CreateEndpoint(
"home/newaction/{id}",
defaults: new { id = "defaultid", controller = "home", action = "newaction" },
requiredValues: new { controller = "home", action = "newaction" },
order: 1));
endpoints.Add(
CreateEndpoint(
"home/contact/{id}",
defaults: new { id = "defaultid", controller = "home", action = "contact" },
requiredValues: new { controller = "home", action = "contact" },
order: 2));
endpoints.Add(
CreateEndpoint(
"home2/newaction/{id}",
defaults: new { id = "defaultid", controller = "home2", action = "newaction" },
requiredValues: new { controller = "home2", action = "newaction" },
order: 3));
endpoints.Add(
CreateEndpoint(
"home2/contact/{id}",
defaults: new { id = "defaultid", controller = "home2", action = "contact" },
requiredValues: new { controller = "home2", action = "contact" },
order: 4));
endpoints.Add(
CreateEndpoint(
"home3/contact/{id}",
defaults: new { id = "defaultid", controller = "home3", action = "contact" },
requiredValues: new { controller = "home3", action = "contact" },
order: 5));
endpoints.Add(
CreateEndpoint(
"named/home/newaction/{id}",
defaults: new { id = "defaultid", controller = "home", action = "newaction" },
requiredValues: new { controller = "home", action = "newaction" },
order: 6,
routeName: "namedroute"));
endpoints.Add(
CreateEndpoint(
"named/home2/newaction/{id}",
defaults: new { id = "defaultid", controller = "home2", action = "newaction" },
requiredValues: new { controller = "home2", action = "newaction" },
order: 7,
routeName: "namedroute"));
endpoints.Add(
CreateEndpoint(
"named/home/contact/{id}",
defaults: new { id = "defaultid", controller = "home", action = "contact" },
requiredValues: new { controller = "home", action = "contact" },
order: 8,
routeName: "namedroute"));
endpoints.Add(
CreateEndpoint(
"any/url",
defaults: new { },
requiredValues: new { },
order: 9,
routeName: "MyRouteName"));
endpoints.Add(
CreateEndpoint(
"api/orders/{id}",
defaults: new { controller = "Orders", action = "GetById" },
requiredValues: new { controller = "Orders", action = "GetById" },
order: 10,
routeName: "OrdersApi"));
return endpoints;
}
private RouteEndpoint CreateEndpoint(
string template,
object defaults = null,
object requiredValues = null,
int order = 0,
string routeName = null,
EndpointMetadataCollection metadataCollection = null)
{
if (metadataCollection == null)
{
metadataCollection = new EndpointMetadataCollection(
new RouteValuesAddressMetadata(routeName, new RouteValueDictionary(requiredValues)));
}
return new RouteEndpoint(
(httpContext) => Task.CompletedTask,
RoutePatternFactory.Parse(template, defaults, parameterPolicies: null),
order,
metadataCollection,
null);
}
private IServiceProvider CreateServices(IEnumerable<Endpoint> endpoints)
{
if (endpoints == null)
{
endpoints = Enumerable.Empty<Endpoint>();
}
var services = GetCommonServices();
services.AddRouting();
services.TryAddEnumerable(
ServiceDescriptor.Singleton<EndpointDataSource>(new DefaultEndpointDataSource(endpoints)));
services.TryAddSingleton<IUrlHelperFactory, UrlHelperFactory>();
return services.BuildServiceProvider();
}
private RouteEndpoint GetEndpoint(string name, string template, RouteValueDictionary defaults)
{
return new RouteEndpoint(
c => Task.CompletedTask,
RoutePatternFactory.Parse(template, defaults, parameterPolicies: null),
0,
EndpointMetadataCollection.Empty,
null);
}
private class SuppressLinkGenerationMetadata : ISuppressLinkGenerationMetadata { }
}
}