ASP.NET Core를 사용하여 절대 URL 가져 오기


82

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속성 이 없기 때문에을 (를) 잡을 수 없습니다 .

내가 볼 수있는 한, 이제 HttpContext또는 HttpRequest객체도 전달 해야합니다 . 내가 맞아? 현재 요청을받을 수있는 방법이 있습니까?

내가 올바른 길을 가고 있습니까? 이제 도메인이 상대 URL에 간단하게 추가되는 환경 변수 여야합니까? 이것이 더 나은 접근 방식일까요?


1
절대 URL을 얻는 것은 무엇입니까?
im1dermike 2015-06-10

@ im1dermike 예http://example.com/controller/action
무하마드 Rehan 사이드

답변:


74

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에서 인스턴스를 HttpContext.Request하고 해당 속성 사용 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클래스입니다. (Ur L Helper 와 다른 점 )

GetDisplayUrl . 표시 전용으로 적합한 완전히 이스케이프되지 않은 형식 (QueryString 제외)으로 요청 URL의 결합 된 구성 요소를 반환합니다. 이 형식은 HTTP 헤더 또는 기타 HTTP 작업에 사용해서는 안됩니다.

GetEncodedUrl . HTTP 헤더 및 기타 HTTP 작업에 사용하기에 적합한 완전히 이스케이프 된 형식으로 요청 URL의 결합 된 구성 요소를 반환합니다.

그것들을 사용하려면 :

  • 네임 스페이스를 포함합니다 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());

이제 UrlHelper 대신 IUrlHelper를 사용해야합니다. 모든 객체는 MVC 6에서 훨씬 더 분리되어 있습니다. 귀하의 옵션이 최선이라고 생각합니다.
Muhammad Rehan Saeed 2015 년

RC1에서는 작동하지 않습니다. View는 확장 메서드에 런타임 오류를 생성합니다. 또한 UriHelper링크가 끊어졌습니다.
Mrchief

2
@Mrchief 링크를 업데이트했습니다 (RC2의 네임 스페이스가 변경되었으므로 dev 브랜치에 대한 모든 링크가 죽었습니다 ...). 그러나 난 그냥 추가 한 RC1 프로젝트 만든 @using Microsoft.AspNet.Http.ExtensionsIndex.cshtml보기로하고 같이 그 확장을 사용 할 수 있었다@Context.Request.GetDisplayUrl()
다니엘 JG

44

ASP.NET Core 1.0 이상

/// <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);
    }
}

보너스 팁

IUrlHelperDI 컨테이너에를 직접 등록 할 수 없습니다 . 의 인스턴스를 해결 IUrlHelper하려면 IUrlHelperFactory및 을 사용해야합니다 IActionContextAccessor. 그러나 바로 가기로 다음을 수행 할 수 있습니다.

services
    .AddSingleton<IActionContextAccessor, ActionContextAccessor>()
    .AddScoped<IUrlHelper>(x => x
        .GetRequiredService<IUrlHelperFactory>()
        .GetUrlHelper(x.GetRequiredService<IActionContextAccessor>().ActionContext));

ASP.NET Core 백 로그

업데이트 : 이것은 ASP.NET Core 5를 만들지 않습니다.

LinkGenerator제공 할 필요없이 절대 URL을 생성하는 데 사용할 수 있다는 표시가 있습니다 HttpContext( 아래 솔루션을 사용하여 설정하는 것이 더 복잡했지만 사용하기가 더 쉬웠지만 LinkGenerator이것이 가장 큰 단점이었던 이유 IUrlHelper). "구성하기 쉽게 만들기 LinkGenerator를 사용하는 절대 URL에 대한 호스트 / 체계 " .


1
그게 내가 필요한 일도 할 수 있을까요? stackoverflow.com/q/37928214/153923
jp2code

4
이것은 괜찮지 만 나에게 너무 많은 코드가 너무 많은 것 같습니다. 우리는 그냥 고수 할 수 있을까string url = string.Concat(this.Request.Scheme, "://", this.Request.Host, this.Request.Path, this.Request.QueryString);
Junior Mayhé

19

이를 위해 확장 메서드를 만들 필요가 없습니다.

@Url.Action("Action", "Controller", values: null);

  • Action -액션의 이름
  • Controller -컨트롤러 이름
  • values -경로 값을 포함하는 객체 : 일명 GET 매개 변수

링크를 생성하는 데 사용할 수있는 다른 많은 오버로드Url.Action 도 있습니다.


1
감사! 이것은 정확히 내가 필요로했지만 this.Context.Request.Scheme. URL의 프로토콜과 도메인 부분 만 가져 오나요?
Lukas

this.Context.Request.Schema요청에 사용 된 프로토콜을 반환합니다. 그것은 것 http또는 https. 여기에 문서가 있지만 스키마가 무엇을 의미하는지 실제로 설명하지는 않습니다.
Kelly Elton

14

경로 주석이있는 메서드에 대한 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);
    }
}

9

이것은 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);
        }
    }
}

5

이 전화로 할 수 있다는 것을 방금 발견했습니다.

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

이것은 체계, 호스트, 포트, 모든 것을 유지합니다.


3

컨트롤러 액션 여전히 할 수있는 새로운 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

선택적 매개 변수를 사용하여 상대 경로를 변환하려는 경우 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

다음과 같은 URL을 얻을 수 있습니다.

Request.Headers["Referer"]

설명

Request.UrlRefererA가 발생합니다 System.UriFormatException리퍼러 HTTP 헤더 형식이 잘못된 경우 (그것이 당신의 통제하에 일반적으로되지 않기 때문에 어떤 일이 일어날 수 있습니다.)

사용에 관해서는 Request.ServerVariables, MSDN 당 :

Request.ServerVariables 컬렉션

ServerVariables 컬렉션은 미리 결정된 환경 변수의 값과 요청 헤더 정보를 검색합니다.

Request.Headers 속성

HTTP 헤더 컬렉션을 가져옵니다.

난 당신이 선호하는 이유를 이해하지 못하는 것 같아요 Request.ServerVariables이상을 Request.Headers하기 때문에,Request.ServerVariablesRequest.Headers는 헤더 만 포함하는 훨씬 짧은 목록 인 헤더뿐만 아니라 모든 환경 변수를 포함하기 .

따라서 가장 좋은 해결책은 Request.Headers컬렉션을 사용 하여 값을 직접 읽는 것입니다. 하지만 양식에 표시하려는 경우 값을 인코딩하는 HTML에 대한 Microsoft의 경고에 유의하십시오.


Referer는 신뢰할 수 없으며 브라우저는 강제로 전송하지 않습니다. 즉, 사용자는 보안 조치로 참조자를 보내지 않도록 브라우저를 구성 할 수 있습니다.
mikiqex
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.