Bagaimana cara menemukan url absolut tindakan di ASP.NET MVC?

239

Saya perlu melakukan sesuatu seperti ini:

<script type="text/javascript">
    token_url = "http://example.com/your_token_url";
</script>

Saya menggunakan versi Beta dari MVC, tapi saya tidak tahu cara mendapatkan url absolut dari suatu tindakan. Saya ingin melakukan sesuatu seperti ini:

<%= Url.AbsoluteAction("Action","Controller")) %>

Apakah ada metode pembantu atau Halaman untuk ini?

Mike Comstock
sumber

Jawaban:

480

Klik di sini untuk informasi lebih lanjut, tetapi pada dasarnya tidak perlu untuk metode ekstensi. Ini sudah dipanggang, hanya saja tidak dengan cara yang sangat intuitif.

Url.Action("Action", null, null, Request.Url.Scheme);
Adam Boddington
sumber
6
Menarik, jadi jika Anda menentukan protokolnya, URL itu absolut
Casebash
24
Jawaban ini adalah yang terbaik, dengan cara ini Resharper masih dapat memvalidasi bahwa Action dan Controller ada. Saya menyarankan penggunaan Request.Url.Scheme alih-alih http, sehingga http dan https keduanya didukung.
Pbirkoff
2
@Pbirkoff, setuju bahwa ini adalah jawaban terbaik tetapi Anda mungkin ingin tahu bahwa Anda dapat membuat anotasi metode Anda sendiri untuk ReSharper untuk mengetahui bahwa parameter mewakili tindakan / pengendali. Dengan cara itu R # masih dapat memvalidasi string yang Anda berikan, karena ia melakukannya dengan baik.
Drew Noakes
3
Perbaikan kecil mungkin untuk mengganti "http" dengan Request.Url.Schemesehingga jika Anda menggunakan HTTPS url yang dihasilkan juga akan menggunakan HTTPS.
Erik Schierboom
1
Ini berfungsi Html.ActionLinkjuga (salah satu metode yang menggunakan protokol, 2 terakhir di MVC 4 misalnya)
Chris
74

Perpanjang UrlHelper

namespace System.Web.Mvc
{
    public static class HtmlExtensions
    {
        public static string AbsoluteAction(this UrlHelper url, string action, string controller)
        {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;

            string absoluteAction = string.Format(
                "{0}://{1}{2}",
                requestUrl.Scheme,
                requestUrl.Authority,
                url.Action(action, controller));

            return absoluteAction;
        }
    }
}

Lalu panggil seperti ini

<%= Url.AbsoluteAction("Dashboard", "Account")%>

EDIT - PENGUMUMAN PEMBACA

Komentar yang paling banyak dipilih tentang jawaban yang diterima adalah This answer is the better one, this way Resharper can still validate that the Action and Controller exists.Jadi di sini adalah contoh bagaimana Anda bisa mendapatkan perilaku yang sama.

using JetBrains.Annotations

namespace System.Web.Mvc
{
    public static class HtmlExtensions
    {
        public static string AbsoluteAction(
            this UrlHelper url,
            [AspMvcAction]
            string action,
            [AspMvcController]
            string controller)
        {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;

            string absoluteAction = string.Format(
                "{0}://{1}{2}",
                requestUrl.Scheme,
                requestUrl.Authority,
                url.Action(action, controller));

            return absoluteAction;
        }
    }
}

Info pendukung:

Charlino
sumber
3
Saya juga akan menambahkan parameter opsional untuk solusi ini. Ini harus mencakup semua kasus.
Eugeniu Torica
Sangat bagus! Saya menggunakan kode ini tetapi saya membuat satu-satunya argumen relatifUrl sehingga pemanggil dapat membuatnya menggunakan metode Url apa pun yang mereka suka (nilai router dll), dan metode Anda hanya dapat bertanggung jawab untuk membuatnya relatif. Jadi milikku adalah: AbsoluteUrl (url UrlHelper ini, string relativeUrl).
Rob Kent
26
<%= Url.Action("About", "Home", null, Request.Url.Scheme) %>
<%= Url.RouteUrl("Default", new { Action = "About" }, Request.Url.Scheme) %>
Ryan Sampson
sumber
21

Menggunakan jawaban @Charlino sebagai panduan, saya menemukan ini.

The dokumentasi ASP.NET MVC untuk UrlHelper menunjukkan bahwa Url.Action akan mengembalikan Url berkualitas sepenuhnya jika hostname dan protokol yang disahkan pada. Saya membuat pembantu ini untuk memaksa hostname dan protokol yang akan diberikan. Kelebihan ganda mencerminkan kelebihan untuk Url.Action:

using System.Web.Routing;

namespace System.Web.Mvc {
    public static class HtmlExtensions {

        public static string AbsoluteAction(this UrlHelper url, string actionName) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, null, (RouteValueDictionary)null, 
                              requestUrl.Scheme, null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            object routeValues) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, null, new RouteValueDictionary(routeValues), 
                              requestUrl.Scheme, null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            RouteValueDictionary routeValues) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, null, routeValues, requestUrl.Scheme, null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            string controllerName) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, controllerName, (RouteValueDictionary)null, 
                              requestUrl.Scheme, null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            string controllerName, 
                                            object routeValues) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, controllerName, 
                              new RouteValueDictionary(routeValues), requestUrl.Scheme, 
                              null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            string controllerName, 
                                            RouteValueDictionary routeValues) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, controllerName, routeValues, requestUrl.Scheme, 
                              null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            string controllerName, object routeValues, 
                                            string protocol) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, controllerName, 
                              new RouteValueDictionary(routeValues), protocol, null);
        }

    }
}
Raleigh Buckner
sumber
4
Terima kasih untuk kode, banyak membantu saya, tetapi ada masalah dengan solusi ini yang biasanya muncul selama pengembangan. Jika situs di-host pada port tertentu, informasi port disertakan dalam requestUrl . Otoritas , seperti localhost: 4423 . Untuk beberapa alasan, metode Action menambahkan port lagi. Jadi ini adalah bug di dalam Metode Tindakan atau Anda tidak seharusnya memasok porta di sini. Tapi yang mana dari Properti yang tersedia pada permintaan adalah yang benar (DnsSafeHost atau Host)? Nah solusinya agak sederhana: Cukup berikan nol dan metode Tindakan akan mengisi nilai yang benar.
ntziolis
Saya telah memperbarui jawaban untuk memasukkan saran @ ntziolis.
Andrew Arnott
3

Saya tidak yakin apakah ada cara yang dibangun untuk melakukannya, tetapi Anda bisa menggulung metode HtmlHelper Anda sendiri.

Sesuatu seperti yang berikut ini

namespace System.Web.Mvc
{
    public static class HtmlExtensions
    {
        public static string AbsoluteAction(this HtmlHelper html, string actionUrl)
        {
            Uri requestUrl = html.ViewContext.HttpContext.Request.Url;

            string absoluteAction = string.Format("{0}://{1}{2}",
                                                  requestUrl.Scheme,
                                                  requestUrl.Authority,
                                                  actionUrl);

            return absoluteAction;
        }
    }
}

Lalu panggil seperti ini

<%= Html.AbsoluteAction(Url.Action("Dashboard", "Account"))%> »

HTHs, Charles

Charlino
sumber
2

Jawaban lengkap dengan argumen adalah:

var url = Url.Action("ActionName", "ControllerName", new { id = "arg_value" }, Request.Url.Scheme);

dan itu akan menghasilkan url absolut

Dashrath
sumber
1

Hasil yang sama tetapi sedikit lebih bersih (tanpa penggabungan / pemformatan string):

public static Uri GetBaseUrl(this UrlHelper url)
{
    Uri contextUri = new Uri(url.RequestContext.HttpContext.Request.Url, url.RequestContext.HttpContext.Request.RawUrl);
    UriBuilder realmUri = new UriBuilder(contextUri) { Path = url.RequestContext.HttpContext.Request.ApplicationPath, Query = null, Fragment = null };
    return realmUri.Uri;
}

public static string ActionAbsolute(this UrlHelper url, string actionName, string controllerName)
{
    return new Uri(GetBaseUrl(url), url.Action(actionName, controllerName)).AbsoluteUri;
}
vegetarian
sumber
0

Mungkin ini (?):

<%= 
  Request.Url.GetLeftPart(UriPartial.Authority) + 
  Url.Action("Action1", "Controller2", new {param1="bla", param2="blabla" })
%>
tytusse
sumber
0

env: dotnet core versi 1.0.4

Url.Action("Join",null, null,Context.Request.IsHttps?"https":"http");
guhyeon
sumber