2010-01-05 65 views
325

是否有獲取動作完整URL的內置方式?在ASP.NET MVC中獲取動作的完整URL

我在尋找類似GetFullUrl("Action", "Controller")的東西,它會返回類似http://www.fred.com/Controller/Action的東西。

我在尋找的原因是爲了避免在生成的自動電子郵件中對URL進行硬編碼,以便始終可以根據網站的當前位置生成URL。

+0

另請參閱:http://stackoverflow.com/q/434604 – Andrew 2012-04-30 08:01:48

回答

503

Url.Action有一個重載,它將所需的協議(例如http,https)作爲參數 - 如果指定了此參數,則會獲得完全限定的URL。

下面是一個使用當前請求的協議中的操作方法的一個示例:

var fullUrl = this.Url.Action("Edit", "Posts", new { id = 5 }, this.Request.Url.Scheme); 

的HtmlHelper(@Html)還具有ActionLink的方法的重載,你可以在剃刀用於創建錨元素,但它也需要hostName和fragment參數。所以,我只是選擇再次使用@ Url.Action:

<span> 
    Copy 
    <a href='@Url.Action("About", "Home", null, Request.Url.Scheme)'>this link</a> 
    and post it anywhere on the internet! 
</span> 
+4

沒有麻煩 - 你會認爲應該還有更好的方式來做到這一點,但嘿... – Paddy 2010-01-05 11:26:24

+0

當使用Azure模擬器在本地進行測試時返回端口82而不是正確的端口81.不確定這是否正常發佈或不發佈。儘管Marius Schulz提出的答案很完美。 – angularsen 2012-10-16 04:52:40

+1

正確的URL是'https:// 127.0.0.1/Home/Index',但它會生成'https://127.0.0.1:444/Home/Index'。它必須沒有端口。我在Azure模擬器上運行。請幫忙。 – fiberOptics 2014-03-14 08:01:38

123

稻穀提到:如果你使用的UrlHelper.Action()明確指定使用的協議過載,生成的URL將是絕對的,完全合格而不是相對的。

我編寫了一個名爲How to build absolute action URLs using the UrlHelper class一篇博客文章中,我建議寫可讀性的原因自定義擴展方法:

/// <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 UrlHelper url, 
    string actionName, string controllerName, object routeValues = null) 
{ 
    string scheme = url.RequestContext.HttpContext.Request.Url.Scheme; 

    return url.Action(actionName, controllerName, routeValues, scheme); 
} 

然後,您可以簡單地使用它一樣,在您的視圖:

@Url.AbsoluteAction("Action", "Controller") 
+0

希望你有更多的upvotes,這實際上是一個應該是在框架IMO – Roger 2012-05-04 03:55:19

+7

我想添加(或修改)的唯一的事情是用HttpContext.Current.Request.Url.Scheme替換文字「http」 。這將允許在適當的時候使用https。 – Jay 2012-06-07 03:08:35

+0

@Jay,感謝您的建議,我更新了我的代碼示例。我在博客文章中收到了相同的反饋;-)。 – 2012-06-07 09:53:26

0

這個問題是特定於ASP .NET,但我相信你們中的一些人將受益於系統不可知的JavaScript,這在很多情況下都是有益的。

更新:在上面的答案中很好地描述了在頁面之外獲取url的方式。

或者你可以做一個oneliner類似以下內容:

new UrlHelper(actionExecutingContext.RequestContext).Action(
    "SessionTimeout", "Home", 
    new {area = string.Empty}, 
    actionExecutingContext.Request.Url!= null? 
    actionExecutingContext.Request.Url.Scheme : "http" 
); 

從過濾器或:

new UrlHelper(this.Request.RequestContext).Action(
    "Details", 
    "Journey", 
    new { area = productType }, 
    this.Request.Url!= null? this.Request.Url.Scheme : "http" 
); 

但是經常一個人需要用Html.Action獲取當前網頁的網址,對於這些案件,把他對你的名字和頁面控制器給我感覺很尷尬。在這種情況下,我的首選是使用JavaScript代替。這在一半重寫的系統中特別有用MVT半web形式半個vb腳本半數神知道什麼 - 並且獲取當前頁面的URL每次需要使用不同的方法。

的一種方法是使用JavaScript來獲取網址是window.location.href另一個 - document.URL

+1

這隻會用於呈現當前頁面的URL。 OP想要做的是傳遞.Net控制器和視圖的名稱以生成到達該頁面的URL。 – Matthew 2016-02-09 16:33:35

0

這可能只是我是真的,真的很挑剔,但我想只有一次定義常量。如果你使用上面定義的任何方法,你的動作常量將被定義多次。

爲了避免這種情況,你可以做到以下幾點:

public class Url 
    { 
     public string LocalUrl { get; } 

     public Url(string localUrl) 
     { 
      LocalUrl = localUrl; 
     } 

     public override string ToString() 
     { 
      return LocalUrl; 
     } 
    } 

    public abstract class Controller 
    { 
     public Url RootAction => new Url(GetUrl()); 

     protected abstract string Root { get; } 

     public Url BuildAction(string actionName) 
     { 
      var localUrl = GetUrl() + "/" + actionName; 
      return new Url(localUrl); 
     } 

     private string GetUrl() 
     { 
      if (Root == "") 
      { 
       return ""; 
      } 

      return "/" + Root; 
     } 

     public override string ToString() 
     { 
      return GetUrl(); 
     } 
    } 

然後創建你自己的控制器,比方說是DataController類:

public static readonly DataController Data = new DataController(); 
    public class DataController : Controller 
    { 
     public const string DogAction = "dog"; 
     public const string CatAction = "cat"; 
     public const string TurtleAction = "turtle"; 

     protected override string Root => "data"; 

     public Url Dog => BuildAction(DogAction); 
     public Url Cat => BuildAction(CatAction); 
     public Url Turtle => BuildAction(TurtleAction); 
    } 

然後,只需使用它像:

// GET: Data/Cat 
    [ActionName(ControllerRoutes.DataController.CatAction)] 
    public ActionResult Etisys() 
    { 
     return View(); 
    } 

並從您的.cshtml(或任何代碼)

<ul> 
    <li><a href="@ControllerRoutes.Data.Dog">Dog</a></li> 
    <li><a href="@ControllerRoutes.Data.Cat">Cat</a></li> 
</ul> 

這絕對是更多的工作,但我很容易知道編譯時驗證在我身邊。

1

這是你需要做的。

@Url.Action(action,controller, null, Request.Url.Scheme) 
+2

這與接受的答案相同。當引入新內容時,最好發佈解答。 – Doomsknight 2017-02-16 11:34:40

0

我遇到了問題,我的服務器運行在負載平衡器後面。負載均衡器正在終止SSL/TLS連接。然後它使用http將請求傳遞給Web服務器。

在Request.Url.Schema中使用Url.Action()方法,它保持創建一個http url,在我的情況下創建一個自動化郵件(我的PenTester不喜歡)的鏈接。

我可能被騙了一點,但它正是我需要的強制HTTPS URL:

<a href="@Url.Action("Action", "Controller", new { id = Model.Id }, "https")">Click Here</a> 

實際上我用一個web.config AppSetting本地進行調試時,我可以使用HTTP,但所有測試和產品環境使用轉換來設置https值。