ASP.NETCoreを使用して絶対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プロパティがなくなったため、を取得することはできません。

私が見る限り、HttpContextorHttpRequestオブジェクトも渡す必要があります。私は正しいですか?現在のリクエストを取得する方法はありますか?

私は正しい方向に進んでいますか?ドメインは、相対URLに単純に追加される環境変数にする必要がありますか?これはより良いアプローチでしょうか?


1
絶対URLを取得するのは何ですか?
im1dermike 2015年

@ im1dermike例http://example.com/controller/action
Muhammad

回答:


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、そのプロパティを使用して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、各呼び出しの引数としてが必要になります)


現在のリクエストのabsoluteUriを取得するだけです

現在のリクエストの絶対URIを取得したいだけの場合は、拡張メソッドGetDisplayUrlまたはクラスGetEncodedUrlから使用できますUriHelper。(これはUr Lヘルパーとは異なります)

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());

UrlHelperではなくIUrlHelperを使用する必要があります。MVC 6では、すべてのオブジェクトがはるかに切断されています。あなたのオプションが最適だと思います。
Muhammad Rehan Saeed 2015

RC1では動作しません。ビューは、拡張メソッドでランタイムエラーを生成します。また、UriHelperリンクが切れています。
Mrchief 2016

2
@Mrchiefリンクを更新しました(RC2の名前空間が変更されたため、devブランチへのリンクはすべて無効になっています...)。ただし、RC1プロジェクトを作成@using Microsoft.AspNet.Http.Extensionsし、Index.cshtmlビューに追加したところ、次のようにこれらの拡張機能を使用できました@Context.Request.GetDisplayUrl()
Daniel JG

44

ASP.NET Core1.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コアバックログ

更新:これはASP.NET Core5にはなりません

LinkGenerator提供する必要なしに絶対URLを作成するために使用できるという兆候がありますHttpContext(これが最大の欠点でLinkGeneratorあり、IUrlHelper以下のソリューションを使用してセットアップするのがより複雑であるのに、なぜそれが使いやすかったのか)を参照してください。 LinkGeneratorを使用した絶対URLのホスト/スキーム」


1
それは私も必要なことをしますか?stackoverflow.com/q/37928214/153923
jp2code 2016年

4
これは大丈夫ですが、私にはやり過ぎのようです。単純なものにはコードが多すぎます。私たちはただ固執することができますかstring url = string.Concat(this.Request.Scheme, "://", this.Request.Host, this.Request.Path, this.Request.QueryString);
ジュニアメイヘム2018

19

このための拡張メソッドを作成する必要はありません

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

  • Action -アクションの名前
  • Controller -コントローラーの名前
  • values -ルート値を含むオブジェクト:別名GETパラメータ

リンクを生成するために使用できる他のオーバーロードUrl.Actionたくさんあります。


1
ありがとう!これはまさに私が必要としていたものでしたが、私は何であるかを理解する必要はありませんthis.Context.Request.Scheme。それはURLのプロトコルとドメイン部分を取得するだけですか?
ルーカス・

this.Context.Request.Schemaリクエストに使用されたプロトコルを返します。httpまたはになりますhttps。ここだドキュメントが、それは本当にスキーマの意味を説明していません。
ケリーエルトン

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.Contextthis.Context.RequestリクエストにUrlプロパティがなくなったように見えませんが、子のプロパティ(スキーマ、ホスト、など)を直接リクエストオブジェクト上ですべてです。

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

        return View();
    }

むしろ、this.Contextを使用するかどうか、またはプロパティを挿入することは別の会話です。 ASP.NETvNextでの依存性注入


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.UrlRefererスローされますSystem.UriFormatExceptionリファラHTTPヘッダーの形式が正しくない場合(それはあなたのコントロール下で、通常ではありませんので、これが起こることができます)。

使用に関してはRequest.ServerVariablesMSDNごとに

Request.ServerVariablesコレクション

ServerVariablesコレクションは、事前定義された環境変数の値を取得し、ヘッダー情報を要求します。

Request.Headersプロパティ

HTTPヘッダーのコレクションを取得します。

Request.Headersはヘッダーのみを含むはるかに短いリストであるため、すべての環境変数とヘッダーが含まれているため、なぜRequest.ServerVariablesオーバーを好むのか理解できないと思います。Request.HeadersRequest.ServerVariables

したがって、最善の解決策は、Request.Headersコレクションを使用して値を直接読み取ることです。ただし、フォームに値を表示する場合は、値をHTMLエンコードすることに関するMicrosoftの警告に注意してください。


リファラーは信頼できません。ブラウザーはリファラーを送信する必要はありません。言い換えると、ユーザーは、セキュリティ対策などとして、リファラーを送信しないようにブラウザーを構成できます。
mikiqex 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.