Como encontro o URL absoluto de uma ação no ASP.NET MVC?

239

Eu preciso fazer algo assim:

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

Estou usando a versão beta do MVC, mas não consigo descobrir como obter o URL absoluto de uma ação. Eu gostaria de fazer algo assim:

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

Existe um método auxiliar ou Page para isso?

Mike Comstock
fonte

Respostas:

480

Clique aqui para obter mais informações, mas essencialmente não há necessidade de métodos de extensão. Já está cozido, mas não de uma maneira muito intuitiva.

Url.Action("Action", null, null, Request.Url.Scheme);
Adam Boddington
fonte
6
Interessante, por isso, se você especificar o protocolo, o URL é absoluta
Casebash
24
Essa resposta é a melhor, dessa forma o Resharper ainda pode validar que a Ação e o Controlador existem. Eu sugeriria o uso de Request.Url.Scheme em vez do http, dessa forma, http e https são suportados.
Pbirkoff
2
@Pbirkoff, concorda que esta é a melhor resposta, mas você gostaria de saber que pode anotar seus próprios métodos para o ReSharper saber que os parâmetros representam ações / controladores. Dessa forma, o R # ainda pode validar as strings que você fornece, como faz muito bem.
de Drew Noakes
3
Uma pequena melhoria poderia ser substituir "http" por, Request.Url.Schemepara que, se você usa HTTPS, o URL gerado também use HTTPS.
Erik Schierboom
1
Isso funciona para Html.ActionLinkbem (qualquer um dos métodos que levam um protocolo, o último 2 em MVC 4 por exemplo)
Chris
74

Estender o 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;
        }
    }
}

Então chame assim

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

EDITAR - ANOTAÇÕES DE RESHARPER

O comentário mais votado sobre a resposta aceita é This answer is the better one, this way Resharper can still validate that the Action and Controller exists.Então, aqui está um exemplo de como você pode obter o mesmo comportamento.

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

Informações de suporte:

Charlino
fonte
3
Eu adicionaria também parâmetros opcionais para esta solução. Isso deve cobrir todos os casos.
Eugeniu Torica 27/05/09
Muito agradável! Usei esse código, mas criei o único argumento relativoUrl para que o chamador possa criá-lo usando o método Url que desejar (valores do roteador etc.), e seu método pode ser responsável por torná-lo relativo. Então o meu é: AbsoluteUrl (esse URL de UrlHelper, string relativeUrl).
Rob Kent
26
<%= Url.Action("About", "Home", null, Request.Url.Scheme) %>
<%= Url.RouteUrl("Default", new { Action = "About" }, Request.Url.Scheme) %>
Ryan Sampson
fonte
21

Usando a resposta de @Charlino como guia, eu vim com isso.

A documentação do ASP.NET MVC para UrlHelper mostra que Url.Action retornará uma URL totalmente qualificada se um nome de host e protocolo forem passados. Criei esses auxiliares para forçar o nome de host e o protocolo a serem fornecidos. As várias sobrecargas refletem as sobrecargas de 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
fonte
4
Thx para o código, me ajudou muito, mas há um problema com esta solução que geralmente surge durante o desenvolvimento. Se o site estiver hospedado em uma porta específica, as informações da porta serão incluídas em requestUrl.Authority , como localhost: 4423 . Por alguma razão, o método Action anexa a porta novamente. Portanto, isso é um bug dentro do Action Method ou você não deve fornecer a porta aqui. Mas qual das propriedades disponíveis na solicitação é a correta (DnsSafeHost ou Host)? Bem, a solução é bastante simples: basta fornecer nulo e o método Action preencherá o valor correto.
Ntziolis 14/09/10
Atualizei a resposta para incorporar a sugestão de @ ntziolis.
Andrew Arnott
3

Não tenho certeza se existe uma maneira integrada de fazer isso, mas você pode rolar seu próprio método HtmlHelper.

Algo como o seguinte

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

Então chame assim

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

Charles HTHs

Charlino
fonte
2

A resposta completa com argumentos seria:

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

e isso produzirá um URL absoluto

Dashrath
fonte
1

Mesmo resultado, mas um pouco mais limpo (sem concatenação / formatação de 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;
}
veggerby
fonte
0

Talvez isto (?):

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

env: dotnet core versão 1.0.4

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