aspnetcore/src/Microsoft.AspNet.Mvc.Core/UrlHelper.cs

132 lines
4.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.DependencyInjection;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Routing;
namespace Microsoft.AspNet.Mvc
{
public class UrlHelper : IUrlHelper
{
private readonly HttpContext _httpContext;
private readonly IRouter _router;
private readonly IDictionary<string, object> _ambientValues;
public UrlHelper(IContextAccessor<ActionContext> contextAccessor)
{
_httpContext = contextAccessor.Value.HttpContext;
_router = contextAccessor.Value.Router;
_ambientValues = contextAccessor.Value.RouteValues;
}
public string Action(string action, string controller, object values, string protocol, string host, string fragment)
{
var valuesDictionary = values as IDictionary<string, object>;
if (valuesDictionary == null)
{
valuesDictionary = new RouteValueDictionary(values);
}
else
{
valuesDictionary = new RouteValueDictionary(valuesDictionary);
}
if (action != null)
{
valuesDictionary["action"] = action;
}
if (controller != null)
{
valuesDictionary["controller"] = controller;
}
var path = GeneratePathFromRoute(valuesDictionary);
if (path == null)
{
return null;
}
return GenerateUrl(protocol, host, path, fragment);
}
public string RouteUrl(object values, string protocol, string host, string fragment)
{
var path = GeneratePathFromRoute(new RouteValueDictionary(values));
if (path == null)
{
return null;
}
return GenerateUrl(protocol, host, path, fragment);
}
private string GeneratePathFromRoute(IDictionary<string, object> values)
{
var context = new VirtualPathContext(_httpContext, _ambientValues, values);
var path = _router.GetVirtualPath(context);
// See Routing Issue#31
if (path.Length > 0 && !path.StartsWith("/", StringComparison.Ordinal))
{
path = "/" + path;
}
return _httpContext.Request.PathBase.Add(new PathString(path)).Value;
}
public string Content([NotNull] string contentPath)
{
return GenerateClientUrl(_httpContext.Request.PathBase, contentPath);
}
private static string GenerateClientUrl([NotNull] PathString applicationPath,
[NotNull] string path)
{
if (path.StartsWith("~/", StringComparison.Ordinal))
{
var segment = new PathString(path.Substring(1));
return applicationPath.Add(segment).Value;
}
return path;
}
private string GenerateUrl(string protocol, string host, string path, string fragment)
{
// We should have a robust and centrallized version of this code. See HttpAbstractions#28
Contract.Assert(path != null);
var url = path;
if (!string.IsNullOrEmpty(fragment))
{
url += "#" + fragment;
}
if (string.IsNullOrEmpty(protocol) && string.IsNullOrEmpty(host))
{
// We're returning a partial url (just path + query + fragment), but we still want it
// to be rooted.
if (!url.StartsWith("/", StringComparison.Ordinal))
{
url = "/" + url;
}
return url;
}
else
{
protocol = string.IsNullOrEmpty(protocol) ? "http" : protocol;
host = string.IsNullOrEmpty(host) ? _httpContext.Request.Host.Value : host;
url = protocol + "://" + host + url;
return url;
}
}
}
}