2010-01-05 50 views
325

Có cách tích hợp để nhận URL đầy đủ của một hành động không?Nhận URL đầy đủ của hành động trong ASP.NET MVC

Tôi đang tìm kiếm một cái gì đó như GetFullUrl("Action", "Controller") sẽ trả về một cái gì đó như http://www.fred.com/Controller/Action.

Lý do tôi tìm kiếm điều này là tránh mã hóa các URL trong email tự động được tạo để URL luôn có thể được tạo tương ứng với vị trí hiện tại của trang web.

+0

Xem thêm: http://stackoverflow.com/q/434604 – Andrew

Trả lời

503

Có sự quá tải của Url.Chuyển đổi có giao thức mong muốn của bạn (ví dụ http, https) làm đối số - nếu bạn chỉ định điều này, bạn sẽ nhận được URL đủ điều kiện.

Dưới đây là một ví dụ sử dụng giao thức được yêu cầu hiện tại trong một phương pháp hành động:

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

HtmlHelper (@Html) cũng có một tình trạng quá tải của các phương pháp ActionLink mà bạn có thể sử dụng trong dao cạo để tạo ra một neo phần tử, nhưng nó cũng yêu cầu các tham số hostName và fragment. Vì vậy, tôi muốn chỉ lựa chọn để sử dụng @ Url.Action một lần nữa:

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

Không bận tâm - bạn nghĩ rằng vẫn có cách tốt hơn để thực hiện việc này, nhưng ... – Paddy

+0

Khi thử nghiệm cục bộ với trình mô phỏng Azure này trả về cổng 82 thay vì cổng chính xác 81. Không chắc chắn nếu điều này hoạt động tốt khi xuất bản hay không. Câu trả lời do Marius Schulz đề xuất hoạt động hoàn hảo. – angularsen

+1

Url phải là 'https: // 127.0.0.1/Home/Index' nhưng nó tạo ra' https: //127.0.0.1: 444/Home/Index'. Nó không có cổng. Tôi đang chạy trên trình giả lập Azure. Hãy giúp tôi. – fiberOptics

123

Như Paddy nói: nếu bạn sử dụng một quá tải của UrlHelper.Action() mà xác định một cách rõ ràng các giao thức để sử dụng, URL được tạo ra sẽ là tuyệt đối và đầy đủ thay vì là người thân.

tôi đã viết một bài đăng blog gọi How to build absolute action URLs using the UrlHelper class trong đó tôi đề nghị viết một phương pháp mở rộng thông thường vì lợi ích của khả năng đọc:

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

Bạn có thể sau đó chỉ cần sử dụng nó như thế theo quan điểm của bạn:

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

Chúc các bạn có nhiều upvotes, điều này thực sự là không có trí tuệ mà nên có trong khuôn khổ IMO – Roger

+7

Điều duy nhất tôi sẽ thêm (hoặc sửa đổi) là thay thế chữ "http" bằng HttpContext.Current.Request.Url.Scheme . Điều này sẽ cho phép https được sử dụng khi thích hợp. – Jay

+0

@Jay, cảm ơn đề xuất của bạn, tôi đã cập nhật ví dụ về mã của mình. Tôi đã nhận được phản hồi tương tự trên bài đăng trên blog của tôi ;-). –

0

Câu hỏi này dành riêng cho ASP .NET tuy nhiên tôi chắc chắn một số bạn sẽ hưởng lợi từ javascript bất khả tri của hệ thống, điều này có lợi trong nhiều trường hợp.

CẬP NHẬT: Cách để url được tạo bên ngoài trang được mô tả chính xác trong câu trả lời ở trên.

Hoặc bạn có thể làm một oneliner như sau:

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

từ bộ lọc hoặc:

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

Tuy nhiên khá thường xuyên người ta cần để có được url của trang hiện tại, đối với những trường hợp sử dụng Html.Action và đặt tên và điều khiển của trang bạn đang ở với tôi cảm thấy khó xử. Tùy chọn của tôi trong các trường hợp như vậy là sử dụng JavaScript để thay thế. Điều này đặc biệt tốt trong các hệ thống được viết lại bằng nửa nửa MVT nửa dạng nửa vb-script một nửa Chúa biết điều gì - và để lấy URL của trang hiện tại, người ta cần sử dụng phương pháp khác nhau mỗi lần.

Một cách là sử dụng JavaScript để có được URL là window.location.href khác - document.URL

+1

Điều này sẽ chỉ hoạt động để trình bày URL của trang hiện tại. Những gì OP muốn làm là chuyển tên của .Net Controller và View để tạo URL để đến trang đó. – Matthew

0

này có thể chỉ cho tôi là thực sự, thực sự kén chọn, nhưng tôi muốn chỉ định nghĩa các hằng số một lần. Nếu bạn sử dụng bất kỳ phương pháp nào được xác định ở trên, thì hằng số hành động của bạn sẽ được xác định nhiều lần.

Để tránh điều này, bạn có thể làm như sau:

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

Sau đó tạo các bộ điều khiển của bạn, nói ví dụ như 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); 
    } 

Sau đó, chỉ cần sử dụng nó như:

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

Và từ .cshtml của bạn (hoặc bất kỳ mã nào)

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

Điều này chắc chắn là nhiều công việc hơn, nhưng tôi rất dễ hiểu khi xác nhận thời gian biên dịch ở bên cạnh tôi.

1

Điều bạn cần làm.

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

Điều này giống như câu trả lời được chấp nhận. Câu trả lời được đăng tốt nhất khi có nội dung mới được giới thiệu. – Doomsknight

0

Tôi gặp vấn đề với việc này, máy chủ của tôi đang chạy phía sau bộ cân bằng tải. Trình cân bằng tải đã chấm dứt kết nối SSL/TLS. Sau đó, nó đã chuyển yêu cầu tới các máy chủ web bằng cách sử dụng http.

Sử dụng phương thức Url.Action() với Request.Url.Schema, nó tiếp tục tạo url http, trong trường hợp của tôi để tạo liên kết trong email tự động (mà PenTester của tôi không thích).

tôi có thể đã lừa dối một chút, nhưng nó là chính xác những gì tôi cần thiết để buộc một url https:

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

Tôi thực sự sử dụng một web.config AppSetting vì vậy tôi có thể sử dụng http khi gỡ lỗi tại địa phương, nhưng tất cả môi trường thử nghiệm và prod sử dụng phép biến đổi để đặt giá trị https.

Các vấn đề liên quan