Làm cách nào tôi có thể nhận URL cơ sở của ứng dụng web trong ASP.NET MVC?


300

Làm cách nào tôi có thể nhanh chóng xác định URL gốc là gì cho ứng dụng ASP.NET MVC của mình? Tức là, nếu IIS được thiết lập để phục vụ ứng dụng của tôi tại http://example.com/foo/bar , thì tôi muốn có được URL đó theo cách đáng tin cậy không liên quan đến việc lấy URL hiện tại từ yêu cầu và băm nhỏ nó theo một cách mong manh nào đó sẽ phá vỡ nếu tôi định tuyến lại hành động của mình.

Lý do tôi cần URL cơ sở là ứng dụng web này gọi một ứng dụng khác cần root cho ứng dụng web của người gọi cho mục đích gọi lại.

Câu trả lời:


399

Giả sử bạn có sẵn một đối tượng Yêu cầu, bạn có thể sử dụng:

string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, Url.Content("~"));

Nếu nó không có sẵn, bạn có thể truy cập nó qua ngữ cảnh:

var request = HttpContext.Current.Request

8
urlHelper.Content("~")gì Làm cách nào để tạo định nghĩa urlHelper? Cảm ơn!
Maxim Zaslavsky

31
@Maxim, bạn có thể thay thế một cách đáng kinh ngạc Url.Content ("~")
UpTheCalet

13
Những gì tôi đã kết thúc bằng cách sử dụng:var request = HttpContext.Current.Request; urlBase = string.Format("{0}://{1}{2}", request.Url.Scheme, request.Url.Authority, (new System.Web.Mvc.UrlHelper(request.RequestContext)).Content("~"));
Peter

7
Đối với MVC 4 tôi sử dụngControllerContext.RequestContext.HttpContext.Request
row1

7
@Url.Content("~")giải quyết "/", đó không phải là url cơ sở.
Andrew Hoffman

114

Vì vậy, không ai trong số những người được liệt kê ở đây làm việc cho tôi, nhưng bằng cách sử dụng một vài câu trả lời, tôi đã có một cái gì đó hoạt động:

public string GetBaseUrl()
{
    var request = HttpContext.Current.Request;
    var appUrl = HttpRuntime.AppDomainAppVirtualPath;

    if (appUrl != "/") 
        appUrl = "/" + appUrl;

    var baseUrl = string.Format("{0}://{1}{2}", request.Url.Scheme, request.Url.Authority, appUrl);

    return baseUrl;
}

Cập nhật cho ASP.NET Core / MVC 6:

ASP.NET Corelàm cho quá trình này đau đớn hơn một chút, đặc biệt nếu bạn ở sâu trong mã của mình. Bạn có 2 lựa chọn để nhận được tạiHttpContext

1) Truyền nó từ controller:

var model = new MyClass(HttpContext);

sau đó trong model:

private HttpContext currentContext;

public MyClass(HttpContext currentContext)
{
    this.currentContext = currentContext;
}

2) Có lẽ cách sạch hơn là đưa nó vào lớp của bạn, bắt đầu bằng việc đăng ký các loại trong Startup:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    services.AddTransient<MyClass, MyClass>();
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

sau đó tiêm cho bạn như thế này:

private HttpContext currentContext;

public MyClass(IHttpContextAccessor httpContextAccessor)
{
    currentContext = httpContextAccessor.HttpContext;
}

trong cả hai trường hợp, đây là bản cập nhật cho .NET Core GetBaseUrl():

public string GetBaseUrl()
{
    var request = currentContext.Request;

    var host = request.Host.ToUriComponent();

    var pathBase = request.PathBase.ToUriComponent();

    return $"{request.Scheme}://{host}{pathBase}";
}

Bạn đã đặt phương pháp này ở đâu?
Josh Dean

3
Điều đó thực sự phụ thuộc vào tần suất bạn cần sử dụng ... nếu đây là một thỏa thuận sử dụng một lần thì chỉ cần đặt nó vào lớp mà bạn cần dữ liệu này, nếu bạn dự đoán sử dụng nó trong nhiều lớp trong ứng dụng của mình, thì tôi sử dụng một folder tên là Helperstại các cơ sở của ứng dụng của tôi, tôi có một staticlớp được gọi Staticsvà tôi đặt các chức năng như ở trên đó ... chỉ cần đảm bảo bạn thay đổi trên từ public string GetBaseUrl()đểpublic static string GetBaseUrl()
Serj Sagan

Là một bản cập nhật, tôi không còn sử dụng một lớp được gọi Statics, thay vào đó tôi đã chia nó thành các mục đích sử dụng cụ thể hơn, vì vậy trong trường hợp này, nó sẽ đi vào UrlHelperlớp của tôi
Serj Sagan

1
Trong tất cả các lựa chọn mà tôi đã tìm thấy, đây là lựa chọn duy nhất thực sự hiệu quả với tôi. Đó là số 2 của bạn. Cảm ơn nhiều!
adeldegan

2
Ủng hộ điều này bởi vì đây là người duy nhất đề cập đến PathBase, đó chính xác là những gì tôi cần. Cảm ơn!
Dave

69

Trong mã:

Url.Content("~/");

Cú pháp MVC3:

@Url.Content("~/")

11
Điều này tốt cho việc sử dụng trên các trang Dao cạo, nhưng nếu bạn đang cố gắng chuyển URL sang nguồn bên ngoài, nó sẽ không cung cấp cho bạn URL đầy đủ.
krillgar

5
Nó không hoạt động. Nó sẽ chỉ thêm /thay vì tên thực tế.
Mrchief

2
Code đang ở đâu để người Urltrợ giúp sẵn sàng cho bạn ngay lập tức? Có lẽ chỉ trong Controller. Chắc chắn không phải trong ViewModelhoặc bất kỳ classnơi nào khác mà bạn có thể cần điều này ..
Serj Sagan

43

Có thể đó là phần mở rộng hoặc sửa đổi các câu trả lời được đăng ở đây nhưng tôi chỉ sử dụng dòng sau đây và nó hoạt động:

Request.Url.GetLeftPart(UriPartial.Authority) + Url.Content("~")

Khi đường dẫn của tôi là: http://host/iis_foldername/controller/action
thì tôi nhận được:http://host/iis_foldername/


26

Đoạn mã sau hoạt động độc đáo với tôi trong MVC4 và không cần HttpContextcó sẵn:

System.Web.HttpRuntime.AppDomainAppVirtualPath

Có vẻ để làm việc trong MVC3 quá. Tôi sử dụng nó jQuery.load()để xây dựng URL cho bộ điều khiển và hành động tôi muốn gọi: $('#myplaceholder').load('@(Html.Raw(HttpRuntime.AppDomainAppVirtualPath))/MyController/MyAction', ...);
Kjell Rilbe

Tại sao bạn lại làm vậy? thay vì gọi Url.Action?
BlackTigerX

4
Không hoạt động khi được triển khai lên Azure. Câu trả lời đánh giá cao hơn làm việc trong kịch bản này.
Jeff Dunlop

25

Thủ thuật dựa vào IIS là các ràng buộc IIS có thể khác với các URL công khai của bạn (WCF tôi đang nhìn bạn), đặc biệt là với các máy sản xuất đa homed. Tôi có xu hướng hướng tới việc sử dụng cấu hình để xác định rõ ràng url "cơ sở" cho các mục đích bên ngoài vì điều đó có xu hướng thành công hơn một chút so với trích xuất nó từ đối tượng Yêu cầu.


2
Cũng đúng cho các máy chủ đằng sau bộ cân bằng tải hoặc proxy.
Ishmaeel

20

Đối với một URL cơ sở tuyệt đối sử dụng này. Hoạt động với cả HTTP và HTTPS.

new Uri(Request.Url, Url.Content("~"))

15

Đây là một chuyển đổi của một thuộc tính asp.net sang MVC . Đó là khá nhiều tất cả hát tất cả nhảy múa nhận được phương pháp url gốc.

Khai báo một lớp người trợ giúp:

namespace MyTestProject.Helpers
{
    using System.Web;

    public static class PathHelper
    {
        public static string FullyQualifiedApplicationPath(HttpRequestBase httpRequestBase)
        {
            string appPath = string.Empty;

            if (httpRequestBase != null)
            {
                //Formatting the fully qualified website url/name
                appPath = string.Format("{0}://{1}{2}{3}",
                            httpRequestBase.Url.Scheme,
                            httpRequestBase.Url.Host,
                            httpRequestBase.Url.Port == 80 ? string.Empty : ":" + httpRequestBase.Url.Port,
                            httpRequestBase.ApplicationPath);
            }

            if (!appPath.EndsWith("/"))
            {
                appPath += "/";
            }

            return appPath;
        }
    }
}

Sử dụng:

Để sử dụng từ bộ điều khiển:

PathHelper.FullyQualifiedApplicationPath(ControllerContext.RequestContext.HttpContext.Request)

Để sử dụng trong chế độ xem:

@using MyTestProject.Helpers

PathHelper.FullyQualifiedApplicationPath(Request)

1
Đây là câu trả lời duy nhất tính đến khả năng một trang web chạy trên một cổng khác ngoài 80. Tất cả các câu trả lời khác đều không an toàn theo như tôi nghĩ. Cảm ơn!
jebar8

12

Trong MVC _Layout.cshtml:

<base href="@Request.GetBaseUrl()" />

Đó là những gì chúng ta sử dụng!

public static class ExtensionMethods
{
public static string GetBaseUrl(this HttpRequestBase request)
        {
          if (request.Url == (Uri) null)
            return string.Empty;
          else
            return request.Url.Scheme + "://" + request.Url.Authority + VirtualPathUtility.ToAbsolute("~/");
        }
}

+1 để sử dụng <base>. Ngoài ra, bạn có thể bỏ qua Lược đồ sao cho nó sẽ hoạt động với http hoặc https. Điều đó có nghĩa là bạn có thể bắt đầu url với //.
Jess

5

Điều này hoạt động tốt với tôi (cũng với một bộ cân bằng tải):

@{
    var urlHelper = new UrlHelper(Html.ViewContext.RequestContext);
    var baseurl = urlHelper.Content(“~”);
}

<script>
    var base_url = "@baseurl";
</script>

Đặc biệt nếu bạn đang sử dụng số cổng không chuẩn, sử dụng Request.Url.Authority xuất hiện như một khách hàng tiềm năng tốt lúc đầu, nhưng thất bại trong môi trường LB.


3

Bạn có thể có một phương thức tĩnh nhìn vào HTTPContext. Hiện tại và quyết định sử dụng URL nào (phát triển hoặc máy chủ trực tiếp) tùy thuộc vào ID máy chủ. HttpContext thậm chí có thể cung cấp một số cách dễ dàng hơn để làm điều đó, nhưng đây là tùy chọn đầu tiên tôi tìm thấy và nó hoạt động tốt.


3

Bạn có thể sử dụng đoạn script sau trong dạng xem:

<script type="text/javascript">
    var BASE_URL = '<%= ResolveUrl("~/") %>';
</script>

3

Đối với ASP.NET MVC 4 thì hơi khác một chút:

string url = HttpContext.Request.Url.AbsoluteUri;

3

Điều này đang hoạt động trong ASP .NET MVC 4 Trong bất kỳ hành động điều khiển nào bạn có thể viết: Dòng thứ nhất có toàn bộ url + Chuỗi truy vấn. Dòng thứ 2 xóa đường dẫn & truy vấn cục bộ, ký hiệu '/' cuối cùng. Dòng thứ 3 thêm biểu tượng '/' ở vị trí cuối cùng.

Uri url = System.Web.HttpContext.Current.Request.Url;
string UrlLink = url.OriginalString.Replace(url.PathAndQuery,"");
UrlLink = String.Concat(UrlLink,"/" );

3

trong html đơn giản và ASP.NET hoặc ASP.NET MVC nếu bạn đang sử dụng thẻ:

<a href="~/#about">About us</a>

3

Đối với url có bí danh ứng dụng như http://example.com/appAlias/ ... Bạn có thể thử điều này:

var req = HttpContext.Current.Request;
string baseUrl = string.Format("{0}://{1}/{2}", req.Url.Scheme, req.Url.Authority, req.ApplicationPath);

3

Trên trang web của chính nó:

<input type="hidden" id="basePath" value="@string.Format("{0}://{1}{2}",
  HttpContext.Current.Request.Url.Scheme,
  HttpContext.Current.Request.Url.Authority,
  Url.Content("~"))" />

Trong javascript:

function getReportFormGeneratorPath() {
  var formPath = $('#reportForm').attr('action');
  var newPath = $("#basePath").val() + formPath;
  return newPath;
}

Điều này làm việc cho dự án MVC của tôi, hy vọng nó sẽ giúp


@hemp Đã chỉnh sửa nhưng không bỏ phiếu cho nó? Hy vọng các điểm có giá trị với bạn
Ngày Andrew

Câu hỏi này và các câu trả lời liên quan không hữu ích cho vấn đề cụ thể của tôi nên tôi đã không thử hoặc bỏ phiếu cho bất kỳ câu hỏi nào. Tôi đã chỉnh sửa cái này bởi vì tôi tình cờ thấy nó và nghĩ rằng nó có thể là một câu trả lời đàng hoàng nếu nó được định dạng chính xác. Chỉ cần cố gắng để trở thành một công dân tốt.
cây gai dầu

Ngoài ra, không có điểm danh tiếng đạt được để chỉnh sửa một câu trả lời.
cây gai dầu


2

Có lẽ nó là một giải pháp tốt hơn.

@{
   var baseUrl = @Request.Host("/");
}

sử dụng

<a href="@baseUrl" class="link">Base URL</a>

1
Tôi đã không kiểm tra, nhưng tôi nghi ngờ điều này sẽ hoạt động khi url cơ sở là ảo trực tiếp. I E. localhost / myApp
emragins

1

Đối với MVC 4:

String.Format("{0}://{1}{2}", Url.Request.RequestUri.Scheme, Url.Request.RequestUri.Authority, ControllerContext.Configuration.VirtualPathRoot);

1

Sau đây làm việc vững chắc cho tôi

var request = HttpContext.Request;
                        var appUrl = System.Web.HttpRuntime.AppDomainAppVirtualPath;

                        if (appUrl != "/")
                            appUrl = "/" + appUrl + "/";

                        var newUrl = string.Format("{0}://{1}{2}{3}/{4}", request.Url.Scheme, request.UrlReferrer.Host, appUrl, "Controller", "Action");


1

Đây là giải pháp của tôi (sử dụng .net core 3.1, trong bộ điều khiển api):

string baseUrl = $"{Request.Scheme}://{Request.Headers.Where(h => h.Key == "Host").First().Value}";

0

Chỉ cần trong một dòng lấy BaseUrl

string baseUrl = new Uri(Request.Url, Url.Content("~")).AbsoluteUri;

//output example: https://stackoverflow.com


0

thêm chức năng này trong lớp tĩnh trong dự án như lớp tiện ích:

nội dung tiện ích.cs :

public static class Utility
{
    public static string GetBaseUrl()
    {
        var request = HttpContext.Current.Request;
        var urlHelper = new UrlHelper(request.RequestContext);
        var baseUrl = $"{request.Url.Scheme}://{request.Url.Authority}{urlHelper.Content("~")}";
        return baseUrl;
    }
}

sử dụng mã này bất cứ nơi nào và tận hưởng nó:

var baseUrl = Utility.GetBaseUrl();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.