使用ASP.NET Core获取绝对URL

Muh*_*eed 63 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • UrlHelper.RequestContext 不复存在.
  • 你不能掌握,HttpContext因为不再有静态HttpContext.Current属性.

据我所知,您现在还需要传入HttpContextHttpRequest传递对象.我对吗?有没有办法获取当前的请求?

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

Dan*_*.G. 65

在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);
}
Run Code Online (Sandbox Code Playgroud)

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


您可以修改扩展类以使用该IHttpContextAccessor接口来获取HttpContext.一旦你的情况下,那么你就可以得到HttpRequest从实例HttpContext.Request和使用其属性Scheme,Host,Protocol等如:

string scheme = HttpContextAccessor.HttpContext.Request.Scheme;
Run Code Online (Sandbox Code Playgroud)

例如,您可以要求使用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);
    }

    ....
}
Run Code Online (Sandbox Code Playgroud)

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

public void Configure(IApplicationBuilder app)
{
    ...

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

您可能会想出不同的方法来获取IHttpContextAccessor扩展类,但如果您想将方法保留为扩展方法,则需要将其IHttpContextAccessor注入静态类.(否则你需要IHttpContext在每次通话时作为参数)


刚刚获得当前请求的绝对优先级

如果你只是想获得当前请求的绝对URI,则可以使用扩展方法GetDisplayUrlGetEncodedUrlUriHelper类.(与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());
Run Code Online (Sandbox Code Playgroud)

  • @Mrchief 我已更新链接(RC2 的命名空间已更改,因此所有这些指向 dev 分支的链接都已失效...)。但是我刚刚创建了一个 RC1 项目,将 `@using Microsoft.AspNet.Http.Extensions` 添加到 Index.cshtml 视图,并且能够像在 `@Context.Request.GetDisplayUrl()` 中使用这些扩展 (2认同)

Muh*_*eed 35

对于ASP.NET Core 1.0 Onwards

您可以使用下面的代码或使用Boxed.AspNetCore NuGet包或查看Dotnet-Boxed/Framework GitHub存储库中的代码.

/// <summary>
/// <see cref="IUrlHelper"/> extension methods.
/// </summary>
public static 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

奖金提示

您无法直接LinkGenerator在DI容器中注册.解析实例HttpContext需要您使用LinkGeneratorIUrlHelper.但是,您可以执行以下操作作为快捷方式:

services
    .AddSingleton<IActionContextAccessor, ActionContextAccessor>()
    .AddScoped<IUrlHelper>(x => x
        .GetRequiredService<IUrlHelperFactory>()
        .GetUrlHelper(x.GetRequiredService<IActionContextAccessor>().ActionContext));
Run Code Online (Sandbox Code Playgroud)

  • 这没关系,但对我来说似乎有点矫枉过正,对于简单的事情来说代码太多了。我们可以坚持使用`string url = string.Concat(this.Request.Scheme, "://", this.Request.Host, this.Request.Path, this.Request.QueryString);` (7认同)

Jon*_*Jon 12

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

脚步

获取相对URL

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

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

创建一个绝对URL

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

创建一个新的Uri

var uri = new Uri(absUrl, UriKind.Absolute)
Run Code Online (Sandbox Code Playgroud)

[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);
    }
}
Run Code Online (Sandbox Code Playgroud)


pav*_*rom 8

我刚刚发现你可以通过这个电话做到这一点:

Url.Action(new UrlActionContext
{
    Protocol = Request.Scheme,
    Host = Request.Host.Value,
    Action = "Action"
})
Run Code Online (Sandbox Code Playgroud)

这将维护方案,主机,端口,一切。


Kel*_*ton 7

您不需要为此创建扩展方法

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


Jos*_*iah 6

这是Muhammad Rehan Saeed对anwser的一种改进,该类寄生于现有的同名.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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)