Получение абсолютных URL с помощью Ядра ASP.NET

В MVC 5 у меня были следующие дополнительные методы для генерации абсолютных 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?

  • UrlHelper.RequestContext больше не существует.
  • Вы не можете овладеть HttpContext как больше нет помех HttpContext.Current свойство.

Насколько я вижу, Вы теперь потребовали бы HttpContext или HttpRequest объекты, которые будут переданы в также.Я прав? Там некоторый путь состоит в том, чтобы овладеть текущим запросом?

Я даже на правильном пути, домен должен теперь быть переменной среды, которая является проста добавленный к относительному URL? Это было бы лучшим подходом?

62
задан 30 May 2018 в 14:52

8 ответов

Для Ядра ASP.NET 3.1 Вперед

существуют признаки, что Вы сможете использовать LinkGenerator для создания абсолютного URL без потребности обеспечить HttpContext (Это было самой большой оборотной стороной LinkGenerator и почему IUrlHelper, хотя более сложный для установки использования решения ниже было легче использовать), Видят , "Помогают настроить хост/схему к абсолютным URL с LinkGenerator" .

Для Ядра ASP.NET 1.0 Вперед

можно использовать код ниже или использовать эти Помещенный в коробку. Пакет 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);
    }
}

Бонусная Подсказка

Вы не можете непосредственно зарегистрироваться IUrlHelper в контейнере DI. Разрешение экземпляра IUrlHelper требует, чтобы Вы использовали IUrlHelperFactory и IActionContextAccessor. Однако можно сделать следующее как ярлык:

services
    .AddSingleton<IActionContextAccessor, ActionContextAccessor>()
    .AddScoped<IUrlHelper>(x => x
        .GetRequiredService<IUrlHelperFactory>()
        .GetUrlHelper(x.GetRequiredService<IActionContextAccessor>().ActionContext));
34
ответ дан 31 October 2019 в 13:50

Вы не должны создавать дополнительный метод для этого

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

5
ответ дан 31 October 2019 в 13:50

Если Вы просто хотите преобразовать относительный путь с дополнительными параметрами, я создал дополнительный метод для 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 });
2
ответ дан 31 October 2019 в 13:50

Это - изменение 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
ответ дан 31 October 2019 в 13:50

Если Вы просто хотите Uri для метода, который имеет аннотацию маршрута, следующее работало на меня.

Шаги

Получают Относительный URL

, Отмечающий название Маршрута целевого действия, получают относительный 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);
    }
}
12
ответ дан 31 October 2019 в 13:50

Можно получить URL как это:

Request.Headers["Referer"]

Объяснение

Эти Request.UrlReferer бросит System.UriFormatException, если HTTP-заголовок ссылающегося домена будет уродлив (который может произойти, так как это обычно не находится под Вашим контролем).

Что касается использования Request.ServerVariables, на MSDN:

Запрос. Набор ServerVariables

набор ServerVariables получает значения предопределенных переменных среды и информации заголовка запроса.

Запрос. Свойство

заголовков Получает набор HTTP-заголовков.

я предполагаю, что не понимаю, почему Вы предпочли бы Request.ServerVariables более чем Request.Headers, так как Request.ServerVariables содержит все переменные среды, а также заголовки, где Запрос. Заголовки являются намного более коротким списком, который только содержит заголовки.

, Таким образом, лучшее решение состоит в том, чтобы использовать Request.Headers набор для чтения значения непосредственно. Действительно учтите предупреждения Microsoft о HTML, кодирующем значение, если Вы собираетесь отобразить его на форме, все же.

2
ответ дан 31 October 2019 в 13:50

После 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 . После того как у Вас есть контекст, затем можно получить HttpRequest экземпляр от [1 111] и использовать его свойства Scheme, Host, Protocol и т.д. в качестве в:

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 как аргумент на каждом вызове)

<час>

Просто получение absoluteUri текущего запроса

, Если Вы просто захотите получить абсолютный uri текущего запроса, можно использовать дополнительные методы GetDisplayUrl или GetEncodedUrl от UriHelper класс. (Который отличается от Ура помощник L )

GetDisplayUrl. Возвращает объединенные компоненты URL запроса в полностью незавершенной форме (за исключением QueryString) подходящий только для дисплея. Этот формат не должен использоваться в HTTP-заголовках или других операциях HTTP.

GetEncodedUrl. Возвращает объединенные компоненты URL запроса в полностью завершенной форме, подходящей для использования в HTTP-заголовках и других операций HTTP.

для использования их:

  • Включают пространство имен Microsoft.AspNet.Http.Extensions.
  • , Добираются HttpContext экземпляр. Это уже доступно в некоторых классах (как представления бритвы), но в других Вы, возможно, должны были бы ввести IHttpContextAccessor, как объяснено выше.
  • Затем просто используют их в качестве в [1 125]

, альтернатива тем методам вручную обработала бы себя абсолютный uri с помощью значений в HttpContext.Request объект (Подобный тому, что RequireHttpsAttribute делает):

var absoluteUri = string.Concat(
                        request.Scheme,
                        "://",
                        request.Host.ToUriComponent(),
                        request.PathBase.ToUriComponent(),
                        request.Path.ToUriComponent(),
                        request.QueryString.ToUriComponent());
64
ответ дан 31 October 2019 в 13:50

В новом проекте ASP.Net 5 MVC в действии контроллера можно все еще сделать this.Context, и this.Context.Request Это похоже по Запросу больше нет свойства Url, но дочерние свойства (схема, хост, и т.д.), все по запросу возражают непосредственно.

 public IActionResult About()
    {
        ViewBag.Message = "Your application description page.";
        var schema = this.Context.Request.Scheme;

        return View();
    }

Скорее или не Вы хотите использовать это. Контекст или вводит свойство, другой разговор. Внедрение зависимости в ASP.NET vNext

3
ответ дан 31 October 2019 в 13:50

Другие вопросы по тегам:

Похожие вопросы: