使用ASP.NET Core获取绝对URL

时间:2015-06-10 12:04:45

标签: c# asp.net-core

在MVC 5中,我有以下扩展方法来生成绝对URL,而不是相对的URL:

public static class UrlHelperExtensions
{
    public static string AbsoluteAction(
        this UrlHelper url,
        string actionName, 
        string controllerName, 
        object routeValues = null)
    {
        string scheme = url.RequestContext.HttpContext.Request.Url.Scheme;
        return url.Action(actionName, controllerName, routeValues, scheme);
    }

    public static string AbsoluteContent(
        this UrlHelper url,
        string contentPath)
    {
        return new Uri(url.RequestContext.HttpContext.Request.Url, url.Content(contentPath)).ToString();
    }

    public static string AbsoluteRouteUrl(
        this UrlHelper url,
        string routeName,
        object routeValues = null)
    {
        string scheme = url.RequestContext.HttpContext.Request.Url.Scheme;
        return url.RouteUrl(routeName, routeValues, scheme);
    }
}

ASP.NET Core中的等价物是什么?

  • UrlHelper.RequestContext已不复存在。
  • 由于不再存在静态HttpContext属性,您无法抓住HttpContext.Current

据我所知,您现在还需要传递HttpContextHttpRequest个对象。我对吗?有没有办法掌握当前的请求?

我是否在正确的轨道上,如果域现在是一个环境变量,这是简单的附加到相对URL?这会是一种更好的方法吗?

9 个答案:

答案 0 :(得分:60)

在RC2和1.0 之后,您不再需要向扩展类注入IHttpContextAccessor。它可以通过IUrlHelper立即在urlhelper.ActionContext.HttpContext.Request中使用。然后,您将按照相同的想法创建一个扩展类,但更简单,因为不会涉及注入。

public static string AbsoluteAction(
    this IUrlHelper url,
    string actionName, 
    string controllerName, 
    object routeValues = null)
{
    string scheme = url.ActionContext.HttpContext.Request.Scheme;
    return url.Action(actionName, controllerName, routeValues, scheme);
}

留下关于如何构建它的细节注入访问者,以防它们对某人有用。您可能只对当前请求的绝对URL感兴趣,在这种情况下,请查看答案的结尾。

您可以修改扩展程序类以使用IHttpContextAccessor界面获取HttpContext。获得上下文后,您就可以从HttpContext.Request获取HttpRequest实例并使用其属性SchemeHostProtocol等,如下所示:

string scheme = HttpContextAccessor.HttpContext.Request.Scheme;

例如,您可以要求使用HttpContextAccessor配置您的类:

public static class UrlHelperExtensions
{        
    private static IHttpContextAccessor HttpContextAccessor;
    public static void Configure(IHttpContextAccessor httpContextAccessor)
    {           
        HttpContextAccessor = httpContextAccessor;  
    }

    public static string AbsoluteAction(
        this IUrlHelper url,
        string actionName, 
        string controllerName, 
        object routeValues = null)
    {
        string scheme = HttpContextAccessor.HttpContext.Request.Scheme;
        return url.Action(actionName, controllerName, routeValues, scheme);
    }

    ....
}

您可以在Startup类(Startup.cs文件)上执行以下操作:

public void Configure(IApplicationBuilder app)
{
    ...

    var httpContextAccessor = app.ApplicationServices.GetRequiredService<IHttpContextAccessor>();
    UrlHelperExtensions.Configure(httpContextAccessor);

    ...
}

您可能想出了在扩展类中获取IHttpContextAccessor的不同方法,但如果您想将方法保留为扩展方法,则需要将IHttpContextAccessor注入你的静态类。 (否则你需要IHttpContext作为每个电话的参数)

获取当前请求的绝对值

如果您只想获取当前请求的绝对值,可以使用UriHelper类中的扩展方法GetDisplayUrlGetEncodedUrl。 (这与Ur L Helper不同)

  

<强> GetDisplayUrl 即可。以完全未转义的形式(QueryString除外)仅返回请求URL的组合组件   用于显示。不应在HTTP标头或其他标头中使用此格式   HTTP操作。

     

<强> GetEncodedUrl 即可。以完全转义的形式返回请求URL的组合组件,适用于HTTP标头和其他标头   HTTP操作。

为了使用它们:

  • 包含名称空间Microsoft.AspNet.Http.Extensions
  • 获取HttpContext个实例。它已经在某些类(如剃刀视图)中可用,但在其他类中,您可能需要注入IHttpContextAccessor,如上所述。
  • 然后只需在this.Context.Request.GetDisplayUrl()
  • 中使用它们即可

这些方法的替代方法是使用HttpContext.Request对象中的值手动制作绝对uri(类似于RequireHttpsAttribute所做的):

var absoluteUri = string.Concat(
                        request.Scheme,
                        "://",
                        request.Host.ToUriComponent(),
                        request.PathBase.ToUriComponent(),
                        request.Path.ToUriComponent(),
                        request.QueryString.ToUriComponent());

答案 1 :(得分:33)

对于ASP.NET Core 1.0 Onwards

您可以使用以下代码或使用Django docs NuGet包或查看Boxed.AspNetCore GitHub存储库中的代码。

IUrlHelper

奖金提示

您无法在DI容器中直接注册IUrlHelper。解析IUrlHelperFactory的实例需要您使用IActionContextAccessorservices .AddSingleton<IActionContextAccessor, ActionContextAccessor>() .AddScoped<IUrlHelper>(x => x .GetRequiredService<IUrlHelperFactory>() .GetUrlHelper(x.GetRequiredService<IActionContextAccessor>().ActionContext)); 。但是,您可以执行以下操作作为快捷方式:

angular js

答案 2 :(得分:10)

如果您只是想要一个具有路径注释的方法的Uri,以下内容对我有效。

步骤

获取相对网址

注意目标操作的路由名称,使用控制器的URL属性获取相对URL,如下所示:

var routeUrl = Url.RouteUrl("*Route Name Here*", new { *Route parameters here* });

创建绝对URL

var absUrl = string.Format("{0}://{1}{2}", Request.Scheme,
            Request.Host, routeUrl);

创建一个新的Uri

var uri = new Uri(absUrl, UriKind.Absolute)

实施例

[Produces("application/json")]
[Route("api/Children")]
public class ChildrenController : Controller
{
    private readonly ApplicationDbContext _context;

    public ChildrenController(ApplicationDbContext context)
    {
        _context = context;
    }

    // GET: api/Children
    [HttpGet]
    public IEnumerable<Child> GetChild()
    {
        return _context.Child;
    }

    [HttpGet("uris")]
    public IEnumerable<Uri> GetChildUris()
    {
        return from c in _context.Child
               select
                   new Uri(
                       $"{Request.Scheme}://{Request.Host}{Url.RouteUrl("GetChildRoute", new { id = c.ChildId })}",
                       UriKind.Absolute);
    }


    // GET: api/Children/5
    [HttpGet("{id}", Name = "GetChildRoute")]
    public IActionResult GetChild([FromRoute] int id)
    {
        if (!ModelState.IsValid)
        {
            return HttpBadRequest(ModelState);
        }

        Child child = _context.Child.Single(m => m.ChildId == id);

        if (child == null)
        {
            return HttpNotFound();
        }

        return Ok(child);
    }
}

答案 3 :(得分:4)

这是anwser Muhammad Rehan Saeed的变体,该类被寄生地附加到同名的现有.net核心MVC类,因此一切正常。

namespace Microsoft.AspNetCore.Mvc
{
    /// <summary>
    /// <see cref="IUrlHelper"/> extension methods.
    /// </summary>
    public static partial class UrlHelperExtensions
    {
        /// <summary>
        /// Generates a fully qualified URL to an action method by using the specified action name, controller name and
        /// route values.
        /// </summary>
        /// <param name="url">The URL helper.</param>
        /// <param name="actionName">The name of the action method.</param>
        /// <param name="controllerName">The name of the controller.</param>
        /// <param name="routeValues">The route values.</param>
        /// <returns>The absolute URL.</returns>
        public static string AbsoluteAction(
            this IUrlHelper url,
            string actionName,
            string controllerName,
            object routeValues = null)
        {
            return url.Action(actionName, controllerName, routeValues, url.ActionContext.HttpContext.Request.Scheme);
        }

        /// <summary>
        /// Generates a fully qualified URL to the specified content by using the specified content path. Converts a
        /// virtual (relative) path to an application absolute path.
        /// </summary>
        /// <param name="url">The URL helper.</param>
        /// <param name="contentPath">The content path.</param>
        /// <returns>The absolute URL.</returns>
        public static string AbsoluteContent(
            this IUrlHelper url,
            string contentPath)
        {
            HttpRequest request = url.ActionContext.HttpContext.Request;
            return new Uri(new Uri(request.Scheme + "://" + request.Host.Value), url.Content(contentPath)).ToString();
        }

        /// <summary>
        /// Generates a fully qualified URL to the specified route by using the route name and route values.
        /// </summary>
        /// <param name="url">The URL helper.</param>
        /// <param name="routeName">Name of the route.</param>
        /// <param name="routeValues">The route values.</param>
        /// <returns>The absolute URL.</returns>
        public static string AbsoluteRouteUrl(
            this IUrlHelper url,
            string routeName,
            object routeValues = null)
        {
            return url.RouteUrl(routeName, routeValues, url.ActionContext.HttpContext.Request.Scheme);
        }
    }
}

答案 4 :(得分:4)

我刚刚发现您可以通过以下电话进行操作:

Url.Action(new UrlActionContext
{
    Protocol = Request.Scheme,
    Host = Request.Host.Value,
    Action = "Action"
})

这将维护方案,主机,端口以及所有内容。

答案 5 :(得分:3)

在控制器操作中的新ASP.Net 5 MVC项目中,您仍然可以bthis.Context看起来在请求中不再有Url属性,而是子属性(模式) ,主机等)都直接在请求对象上。

this.Context.Request

你想要使用this.Context还是注入属性是另一个对话。 Dependency Injection in ASP.NET vNext

答案 6 :(得分:2)

你可以得到这样的网址:

Request.Headers["Referer"]

<强>解释

如果引用HTTP标头格式不正确,Request.UrlReferer将抛出System.UriFormatException(这可能发生,因为它通常不受您的控制)。

至于使用Request.ServerVariablesper MSDN

  

Request.ServerVariables Collection

     

ServerVariables集合检索预定环境变量的值并请求标头信息。

Request.Headers Property

获取HTTP标头的集合。

我想我不明白为什么你更喜欢Request.ServerVariables而不是Request.Headers,因为Request.ServerVariables包含所有环境变量以及标题,其中Request.Headers是一个只包含标题的更短的列表。

所以最好的解决方案是使用Request.Headers集合直接读取值。如果您打算在表单上显示该值,请注意Microsoft关于HTML编码值的警告。

答案 7 :(得分:2)

您无需为此创建扩展方法

@Url.Action("Action", "Controller", null, this.Context.Request.Scheme);

答案 8 :(得分:0)

如果只想转换带有可选参数的相对路径,我为 IHttpContextAccessor

创建了扩展方法
public static string AbsoluteUrl(this IHttpContextAccessor httpContextAccessor, string relativeUrl, object parameters = null)
{
    var request = httpContextAccessor.HttpContext.Request;

    var url = new Uri(new Uri($"{request.Scheme}://{request.Host.Value}"), relativeUrl).ToString();

    if (parameters != null)
    {
        url = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString(url, ToDictionary(parameters));
    }

    return url;
}


private static Dictionary<string, string> ToDictionary(object obj)
{
    var json = JsonConvert.SerializeObject(obj);
    return JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
}

然后您可以使用注入的 IHttpContextAccessor

从服务/视图中调用该方法。
var callbackUrl = _httpContextAccessor.AbsoluteUrl("/Identity/Account/ConfirmEmail", new { userId = applicationUser.Id, code });