aspnetcore/src/Microsoft.AspNetCore.Mvc.Core/Routing/DispatcherUrlHelper.cs

144 lines
5.2 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 Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.EndpointFinders;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Mvc.Routing
{
/// <summary>
/// An implementation of <see cref="IUrlHelper"/> that uses <see cref="ILinkGenerator"/> to build URLs
/// for ASP.NET MVC within an application.
/// </summary>
internal class DispatcherUrlHelper : UrlHelperBase
{
private readonly ILogger<DispatcherUrlHelper> _logger;
private readonly ILinkGenerator _linkGenerator;
private readonly IEndpointFinder<RouteValuesBasedEndpointFinderContext> _routeValuesBasedEndpointFinder;
/// <summary>
/// Initializes a new instance of the <see cref="DispatcherUrlHelper"/> class using the specified
/// <paramref name="actionContext"/>.
/// </summary>
/// <param name="actionContext">The <see cref="Mvc.ActionContext"/> for the current request.</param>
/// <param name="routeValuesBasedEndpointFinder">
/// The <see cref="IEndpointFinder{T}"/> which finds endpoints by required route values.
/// </param>
/// <param name="linkGenerator">The <see cref="ILinkGenerator"/> used to generate the link.</param>
/// <param name="logger">The <see cref="ILogger"/>.</param>
public DispatcherUrlHelper(
ActionContext actionContext,
IEndpointFinder<RouteValuesBasedEndpointFinderContext> routeValuesBasedEndpointFinder,
ILinkGenerator linkGenerator,
ILogger<DispatcherUrlHelper> logger)
: base(actionContext)
{
if (linkGenerator == null)
{
throw new ArgumentNullException(nameof(linkGenerator));
}
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
}
_linkGenerator = linkGenerator;
_routeValuesBasedEndpointFinder = routeValuesBasedEndpointFinder;
_logger = logger;
}
/// <inheritdoc />
public override string Action(UrlActionContext urlActionContext)
{
if (urlActionContext == null)
{
throw new ArgumentNullException(nameof(urlActionContext));
}
var valuesDictionary = GetValuesDictionary(urlActionContext.Values);
if (urlActionContext.Action == null)
{
if (!valuesDictionary.ContainsKey("action") &&
AmbientValues.TryGetValue("action", out var action))
{
valuesDictionary["action"] = action;
}
}
else
{
valuesDictionary["action"] = urlActionContext.Action;
}
if (urlActionContext.Controller == null)
{
if (!valuesDictionary.ContainsKey("controller") &&
AmbientValues.TryGetValue("controller", out var controller))
{
valuesDictionary["controller"] = controller;
}
}
else
{
valuesDictionary["controller"] = urlActionContext.Controller;
}
var endpoints = _routeValuesBasedEndpointFinder.FindEndpoints(
new RouteValuesBasedEndpointFinderContext()
{
ExplicitValues = valuesDictionary,
AmbientValues = AmbientValues
});
var successfullyGeneratedLink = _linkGenerator.TryGetLink(
endpoints,
valuesDictionary,
AmbientValues,
out var link);
if (!successfullyGeneratedLink)
{
//TODO: log here
return null;
}
return GenerateUrl(urlActionContext.Protocol, urlActionContext.Host, link, urlActionContext.Fragment);
}
/// <inheritdoc />
public override string RouteUrl(UrlRouteContext routeContext)
{
if (routeContext == null)
{
throw new ArgumentNullException(nameof(routeContext));
}
var valuesDictionary = routeContext.Values as RouteValueDictionary ?? GetValuesDictionary(routeContext.Values);
var endpoints = _routeValuesBasedEndpointFinder.FindEndpoints(
new RouteValuesBasedEndpointFinderContext()
{
RouteName = routeContext.RouteName,
ExplicitValues = valuesDictionary,
AmbientValues = AmbientValues
});
var successfullyGeneratedLink = _linkGenerator.TryGetLink(
endpoints,
valuesDictionary,
AmbientValues,
out var link);
if (!successfullyGeneratedLink)
{
return null;
}
return GenerateUrl(routeContext.Protocol, routeContext.Host, link, routeContext.Fragment);
}
}
}