Allow to pass in HttpContext when generating links

This commit is contained in:
Kiran Challa 2018-07-16 12:42:03 -07:00
parent 02e1d78319
commit aed2e24483
4 changed files with 93 additions and 28 deletions

View File

@ -2,18 +2,21 @@
// 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.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing namespace Microsoft.AspNetCore.Routing
{ {
public interface ILinkGenerator public abstract class LinkGenerator
{ {
bool TryGetLink( public abstract bool TryGetLink(
HttpContext httpContext,
IEnumerable<Endpoint> endpoints, IEnumerable<Endpoint> endpoints,
RouteValueDictionary explicitValues, RouteValueDictionary explicitValues,
RouteValueDictionary ambientValues, RouteValueDictionary ambientValues,
out string link); out string link);
string GetLink( public abstract string GetLink(
HttpContext httpContext,
IEnumerable<Endpoint> endpoints, IEnumerable<Endpoint> endpoints,
RouteValueDictionary explicitValues, RouteValueDictionary explicitValues,
RouteValueDictionary ambientValues); RouteValueDictionary ambientValues);

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing.Internal; using Microsoft.AspNetCore.Routing.Internal;
using Microsoft.AspNetCore.Routing.Matchers; using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.AspNetCore.Routing.Template; using Microsoft.AspNetCore.Routing.Template;
@ -13,7 +14,7 @@ using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Routing namespace Microsoft.AspNetCore.Routing
{ {
internal class DefaultLinkGenerator : ILinkGenerator internal class DefaultLinkGenerator : LinkGenerator
{ {
private readonly MatchProcessorFactory _matchProcessorFactory; private readonly MatchProcessorFactory _matchProcessorFactory;
private readonly ObjectPool<UriBuildingContext> _uriBuildingContextPool; private readonly ObjectPool<UriBuildingContext> _uriBuildingContextPool;
@ -29,12 +30,13 @@ namespace Microsoft.AspNetCore.Routing
_logger = logger; _logger = logger;
} }
public string GetLink( public override string GetLink(
HttpContext httpContext,
IEnumerable<Endpoint> endpoints, IEnumerable<Endpoint> endpoints,
RouteValueDictionary explicitValues, RouteValueDictionary explicitValues,
RouteValueDictionary ambientValues) RouteValueDictionary ambientValues)
{ {
if (TryGetLink(endpoints, explicitValues, ambientValues, out var link)) if (TryGetLink(httpContext, endpoints, explicitValues, ambientValues, out var link))
{ {
return link; return link;
} }
@ -42,7 +44,8 @@ namespace Microsoft.AspNetCore.Routing
throw new InvalidOperationException("Could not find a matching endpoint to generate a link."); throw new InvalidOperationException("Could not find a matching endpoint to generate a link.");
} }
public bool TryGetLink( public override bool TryGetLink(
HttpContext httpContext,
IEnumerable<Endpoint> endpoints, IEnumerable<Endpoint> endpoints,
RouteValueDictionary explicitValues, RouteValueDictionary explicitValues,
RouteValueDictionary ambientValues, RouteValueDictionary ambientValues,
@ -64,7 +67,7 @@ namespace Microsoft.AspNetCore.Routing
foreach (var endpoint in matcherEndpoints) foreach (var endpoint in matcherEndpoints)
{ {
link = GetLink(endpoint, explicitValues, ambientValues); link = GetLink(httpContext, endpoint, explicitValues, ambientValues);
if (link != null) if (link != null)
{ {
return true; return true;
@ -75,6 +78,7 @@ namespace Microsoft.AspNetCore.Routing
} }
private string GetLink( private string GetLink(
HttpContext httpContext,
MatcherEndpoint endpoint, MatcherEndpoint endpoint,
RouteValueDictionary explicitValues, RouteValueDictionary explicitValues,
RouteValueDictionary ambientValues) RouteValueDictionary ambientValues)
@ -92,7 +96,7 @@ namespace Microsoft.AspNetCore.Routing
return null; return null;
} }
if (!Match(endpoint, templateValuesResult.CombinedValues)) if (!Match(httpContext, endpoint, templateValuesResult.CombinedValues))
{ {
return null; return null;
} }
@ -100,7 +104,7 @@ namespace Microsoft.AspNetCore.Routing
return templateBinder.BindValues(templateValuesResult.AcceptedValues); return templateBinder.BindValues(templateValuesResult.AcceptedValues);
} }
private bool Match(MatcherEndpoint endpoint, RouteValueDictionary routeValues) private bool Match(HttpContext httpContext, MatcherEndpoint endpoint, RouteValueDictionary routeValues)
{ {
if (routeValues == null) if (routeValues == null)
{ {
@ -117,7 +121,7 @@ namespace Microsoft.AspNetCore.Routing
} }
var matchProcessor = _matchProcessorFactory.Create(matchProcessorReference); var matchProcessor = _matchProcessorFactory.Create(matchProcessorReference);
if (!matchProcessor.ProcessOutbound(httpContext: null, routeValues)) if (!matchProcessor.ProcessOutbound(httpContext, routeValues))
{ {
return false; return false;
} }

View File

@ -41,7 +41,7 @@ namespace Microsoft.Extensions.DependencyInjection
// Link generation related services // Link generation related services
services.TryAddSingleton<IEndpointFinder<string>, NameBasedEndpointFinder>(); services.TryAddSingleton<IEndpointFinder<string>, NameBasedEndpointFinder>();
services.TryAddSingleton<IEndpointFinder<RouteValuesBasedEndpointFinderContext>, RouteValuesBasedEndpointFinder>(); services.TryAddSingleton<IEndpointFinder<RouteValuesBasedEndpointFinderContext>, RouteValuesBasedEndpointFinder>();
services.TryAddSingleton<ILinkGenerator, DefaultLinkGenerator>(); services.TryAddSingleton<LinkGenerator, DefaultLinkGenerator>();
// //
// Endpoint Selection // Endpoint Selection
// //

View File

@ -7,7 +7,6 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Routing.EndpointFinders; using Microsoft.AspNetCore.Routing.EndpointFinders;
using Microsoft.AspNetCore.Routing.Internal; using Microsoft.AspNetCore.Routing.Internal;
using Microsoft.AspNetCore.Routing.Matchers; using Microsoft.AspNetCore.Routing.Matchers;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.ObjectPool; using Microsoft.Extensions.ObjectPool;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -27,7 +26,11 @@ namespace Microsoft.AspNetCore.Routing
var context = CreateRouteValuesContext(new { controller = "Home" }); var context = CreateRouteValuesContext(new { controller = "Home" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home", link); Assert.Equal("/Home", link);
@ -44,7 +47,11 @@ namespace Microsoft.AspNetCore.Routing
// Act & Assert // Act & Assert
var exception = Assert.Throws<InvalidOperationException>( var exception = Assert.Throws<InvalidOperationException>(
() => linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues)); () => linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues));
Assert.Equal(expectedMessage, exception.Message); Assert.Equal(expectedMessage, exception.Message);
} }
@ -58,6 +65,7 @@ namespace Microsoft.AspNetCore.Routing
// Act // Act
var canGenerateLink = linkGenerator.TryGetLink( var canGenerateLink = linkGenerator.TryGetLink(
httpContext: null,
new[] { endpoint }, new[] { endpoint },
context.ExplicitValues, context.ExplicitValues,
context.AmbientValues, context.AmbientValues,
@ -80,6 +88,7 @@ namespace Microsoft.AspNetCore.Routing
// Act // Act
var link = linkGenerator.GetLink( var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint1, endpoint2, endpoint3 }, new[] { endpoint1, endpoint2, endpoint3 },
context.ExplicitValues, context.ExplicitValues,
context.AmbientValues); context.AmbientValues);
@ -100,6 +109,7 @@ namespace Microsoft.AspNetCore.Routing
// Act // Act
var link = linkGenerator.GetLink( var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint1, endpoint2, endpoint3 }, new[] { endpoint1, endpoint2, endpoint3 },
context.ExplicitValues, context.ExplicitValues,
context.AmbientValues); context.AmbientValues);
@ -119,7 +129,11 @@ namespace Microsoft.AspNetCore.Routing
ambientValues: new { controller = "Home", action = "Index" }); ambientValues: new { controller = "Home", action = "Index" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home/Index?name=name%20with%20%25special%20%23characters", link); Assert.Equal("/Home/Index?name=name%20with%20%25special%20%23characters", link);
@ -136,7 +150,11 @@ namespace Microsoft.AspNetCore.Routing
new { controller = "Home", action = "Index" }); new { controller = "Home", action = "Index" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home/Index?color=red&color=green&color=blue", link); Assert.Equal("/Home/Index?color=red&color=green&color=blue", link);
@ -153,7 +171,11 @@ namespace Microsoft.AspNetCore.Routing
new { controller = "Home", action = "Index" }); new { controller = "Home", action = "Index" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home/Index?items=10&items=20&items=30", link); Assert.Equal("/Home/Index?items=10&items=20&items=30", link);
@ -170,7 +192,11 @@ namespace Microsoft.AspNetCore.Routing
new { controller = "Home", action = "Index" }); new { controller = "Home", action = "Index" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home/Index", link); Assert.Equal("/Home/Index", link);
@ -187,7 +213,11 @@ namespace Microsoft.AspNetCore.Routing
new { controller = "Home", action = "Index" }); new { controller = "Home", action = "Index" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home/Index?page=1&color=red&color=green&color=blue&message=textfortest", link); Assert.Equal("/Home/Index?page=1&color=red&color=green&color=blue&message=textfortest", link);
@ -204,7 +234,11 @@ namespace Microsoft.AspNetCore.Routing
ambientValues: new { controller = "Home" }); ambientValues: new { controller = "Home" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home/Index", link); Assert.Equal("/Home/Index", link);
@ -582,7 +616,11 @@ namespace Microsoft.AspNetCore.Routing
suppliedValues: new { action = "Index", controller = "Home", name = "products" }); suppliedValues: new { action = "Index", controller = "Home", name = "products" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home/Index/products", link); Assert.Equal("/Home/Index/products", link);
@ -598,7 +636,11 @@ namespace Microsoft.AspNetCore.Routing
suppliedValues: new { action = "Index", controller = "Home" }); suppliedValues: new { action = "Index", controller = "Home" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home/Index", link); Assert.Equal("/Home/Index", link);
@ -616,7 +658,11 @@ namespace Microsoft.AspNetCore.Routing
suppliedValues: new { action = "Index", controller = "Home", name = "products" }); suppliedValues: new { action = "Index", controller = "Home", name = "products" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home/Index/products", link); Assert.Equal("/Home/Index/products", link);
@ -634,7 +680,11 @@ namespace Microsoft.AspNetCore.Routing
suppliedValues: new { action = "Index", controller = "Home" }); suppliedValues: new { action = "Index", controller = "Home" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home/Index", link); Assert.Equal("/Home/Index", link);
@ -650,7 +700,11 @@ namespace Microsoft.AspNetCore.Routing
suppliedValues: new { action = "Index", controller = "Home", name = "products", format = "json" }); suppliedValues: new { action = "Index", controller = "Home", name = "products", format = "json" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home/Index/products?format=json", link); Assert.Equal("/Home/Index/products?format=json", link);
@ -710,7 +764,11 @@ namespace Microsoft.AspNetCore.Routing
suppliedValues: new { action = "Index", controller = "Home" }); suppliedValues: new { action = "Index", controller = "Home" });
// Act // Act
var link = linkGenerator.GetLink(new[] { endpoint }, context.ExplicitValues, context.AmbientValues); var link = linkGenerator.GetLink(
httpContext: null,
new[] { endpoint },
context.ExplicitValues,
context.AmbientValues);
// Assert // Assert
Assert.Equal("/Home/Index", link); Assert.Equal("/Home/Index", link);
@ -796,7 +854,7 @@ namespace Microsoft.AspNetCore.Routing
null); null);
} }
private ILinkGenerator CreateLinkGenerator() private LinkGenerator CreateLinkGenerator()
{ {
return new DefaultLinkGenerator( return new DefaultLinkGenerator(
new DefaultMatchProcessorFactory( new DefaultMatchProcessorFactory(