Phương pháp tốt nhất trong ASP.NET để lấy tên miền hiện tại là gì?


102

Tôi đang tự hỏi cách tốt nhất để có được miền hiện tại trong ASP.NET là gì?

Ví dụ:

http://www.domainname.com/subdir/ sẽ mang lại lợi nhuận http://www.domainname.com http://www.sub.domainname.com/subdir/ sẽ mang lại http://sub.domainname.com

Theo hướng dẫn, tôi sẽ có thể thêm một url như "/Folder/Content/filename.html" (giả sử như được tạo bởi Url.RouteUrl () trong ASP.NET MVC) vào thẳng URL và nó sẽ hoạt động.


3
Lưu ý rằng "tên miền hiện tại" ở đây thực sự là những gì mà tác nhân người dùng sử dụng để truy cập vào trang web của bạn, trong nhiều trường hợp khác với "URL chính thức" của trang web của bạn cũng như những gì người dùng cuối có thể đã nhập vào trình duyệt của họ ( proxy ngược, proxy chuyển tiếp, tên máy nội bộ, địa chỉ IP, ...).
bzlm

1
Vậy có cách nào để lấy "URL chính thức" (URL từ IIS không?)
Matt Mitchell

Câu trả lời:


186

Câu trả lời tương tự như của MattMitchell nhưng với một số sửa đổi. Điều này sẽ kiểm tra cổng mặc định thay thế.

Chỉnh sửa: Cập nhật cú pháp và sử dụng Request.Url.Authoritytheo đề xuất

$"{Request.Url.Scheme}{System.Uri.SchemeDelimiter}{Request.Url.Authority}"

3
Có trường nào được định nghĩa i .NET mà tôi có thể sử dụng thay cho ":" không? Một cái gì đó giống như System.Uri.PortDelimiter? Bạn biết đấy, chỉ vì sự nhất quán. :)
Jan Aagaard

2
Không phải tôi biết, Jan Aagaard, nhưng bạn luôn có thể làm một chiếc ở địa phương. Tôi làm điều đó cho hầu hết các chuỗi và số "ma thuật". Cho rằng vấn đề, sau đó bạn sẽ sử dụng string.Empty thay cho "" trong Carlos' câu trả lời;)
vbullinger

8
Bạn có thể sử dụng Request.Url.Authoritynhư Korayem được đề xuất thay vì Request.Url.HostRequest.Url.Port.
Schmalls

4
Thay vì nối các chuỗi, bạn nên sử dụng lớp System.UriBuilder.
BrainSlugs83

3
@MattMitchell, có vẻ như nó không tạo ra các vấn đề với Authority, nó tương đương với Host + ":" + Port, xem mã nguồn dotnetframework.org/default.aspx/DotNET/DotNET/8@0/untmp/…
Giuseppe Romagnuolo

40

Theo liên kết này, điểm khởi đầu tốt là:

Request.Url.Scheme + System.Uri.SchemeDelimiter + Request.Url.Host 

Tuy nhiên, nếu miền là http://www.domainname.com:500, điều này sẽ không thành công.

Một cái gì đó như sau đang hấp dẫn để giải quyết điều này:

int defaultPort = Request.IsSecureConnection ? 443 : 80;
Request.Url.Scheme + System.Uri.SchemeDelimiter + Request.Url.Host 
  + (Request.Url.Port != defaultPort ? ":" + Request.Url.Port : "");

Tuy nhiên, cổng 80 và 443 sẽ phụ thuộc vào cấu hình.

Như vậy, bạn nên sử dụng IsDefaultPortnhư trong Câu trả lời được chấp nhận ở trên từ Carlos Muñoz.


1
Tại sao lại giả sử cổng 80 ở đây? Nếu bạn loại bỏ giả định đó, mã sẽ giống như một bản tóm tắt. Khi bạn giả sử cổng 80, bạn sẽ thất bại trong nhiều trường hợp (xem nhận xét về các anwers khác). Nếu bạn muốn xóa số cổng nếu có thể, bạn phải kiểm tra xem số cổng có phải là số cổng mặc định cho lược đồ được đề cập và lược đồ đó có hỗ trợ số cổng mặc định hay không.
bzlm 29-04-09

Vâng, hãy xem lưu ý rằng cổng 80 có thể là một ý tưởng tồi. Tôi không biết bất kỳ cách nào khác để giải quyết vấn đề này mặc dù đó là lý do tại sao tôi đã đề cập rằng nó sẽ cần phải phụ thuộc vào cấu hình.
Matt Mitchell

1
Tôi không biết điều này có hữu ích hay không nhưng bạn cũng có thể thử: if Request.IsSecureConnection để xác định xem HTTPS có được sử dụng hay không?
Erick Brown

1
@EricBrown - Đúng vậy, câu trả lời này không tuyệt vời trong 5 năm sau đó. Tôi sẽ đi với câu trả lời được chấp nhận của Carlos Muñoz để tránh vấn đề đó.
Matt Mitchell

29
Request.Url.GetLeftPart(UriPartial.Authority)

Đây là chương trình bao gồm.


23
Tôi rất muốn có mặt trong cuộc họp khi họ nghĩ ra cái tên đó
Simon_Weaver

20

CẢNH BÁO! Cho bất cứ ai sử dụng Current.Request .Url.Host. Hiểu rằng bạn đang làm việc dựa trên YÊU CẦU HIỆN TẠI và yêu cầu hiện tại sẽ KHÔNG LUÔN với máy chủ của bạn và đôi khi có thể với các máy chủ khác.

Vì vậy, nếu bạn sử dụng điều này trong một cái gì đó như Application_BeginRequest () trong Global.asax, thì 99,9% thời gian sẽ ổn, nhưng 0,1% bạn có thể nhận được thứ gì đó khác với tên máy chủ của máy chủ của bạn.

Một ví dụ điển hình về điều này là điều mà tôi đã phát hiện ra cách đây không lâu. Máy chủ của tôi có xu hướng truy cập http://proxyjudge1.proxyfire.net/fastenv theo thời gian. Application_BeginRequest () sẵn lòng xử lý yêu cầu này, vì vậy nếu bạn gọi Request.Url.Host khi nó thực hiện yêu cầu này, bạn sẽ nhận lại proxyjudge1.proxyfire.net. Một số bạn có thể nghĩ "không có gì đâu" nhưng đáng chú ý vì đây là một lỗi rất khó nhận thấy vì nó chỉ xảy ra 0,1% thời gian: P

Lỗi này đã buộc tôi phải chèn máy chủ miền của mình dưới dạng một chuỗi trong các tệp cấu hình.


Đã làm chính xác như vậy. Tên miền của tôi hiện ở trong web.config.
Korayem

Tôi nghĩ tôi hiểu, mặc dù vậy - tại sao máy chủ của bạn lại gặp sự cố proxy? Đó có phải là trang web của bạn không? Tuy nhiên, về tổng thể, có ý nghĩa - việc sử dụng một đối tượng dành riêng cho yêu cầu trong một sự kiện dành riêng cho ứng dụng có thể không hoạt động quá tốt. Có mối nguy hiểm nào trong một sự kiện dành riêng cho yêu cầu, chẳng hạn như sự kiện vòng đời của trang (Page.LoadCompleted, v.v.) không?
mlhDev

Tôi đã không điều tra quá khó về lý do tại sao nó lại giải quyết được proxyfire. Nó chắc chắn không phải là trang web của tôi, nhưng nó đã cho tôi thấy rằng Current.Request.Url không đáng tin cậy 100%. Sau rất nhiều nghiên cứu, tôi cũng đã phát hiện ra rằng việc xác định động tên máy chủ của bạn là không dễ dàng, do nhiều thẻ NIC, IP và tên miền phân giải thành cùng một IP. Đối với câu hỏi khác của bạn Matt, tôi không chắc chắn những gì bạn có nghĩa là: (
Thirlan

vậy điều này chỉ xảy ra trong Application_BeginRequest? Tôi không hiểu làm cách nào mà IIS có thể gửi yêu cầu này đến ứng dụng của bạn trừ khi bạn không có bộ tiêu đề máy chủ lưu trữ?
Simon_Weaver

@Thirlan - Tôi đang cố gắng gỡ lỗi sự cố có vẻ tương tự như sự cố này. Tôi đang cố gắng lấy tên miền phụ bằng Request.Url.Host và 'thường' hoạt động tốt, nhưng không phải lúc nào cũng vậy. Có thực sự là anyway xung quanh điều này? Giống như một cái gì đó khác trong yêu cầu có thể đúng?
scojomodena

14

Tại sao không sử dụng

Request.Url.Authority

Nó trả về toàn bộ miền VÀ cổng.

Bạn vẫn cần tìm http hoặc https


2
Điều này cũng hoạt động. Để "hình" http hoặc https, simlpy đặt "//" trước nó. Vì vậy, ví dụ, nó sẽ đọc là href = "// @ Request.Url.Authority ..."
EdwardM

2

Cách đơn giảnngắn gọn (nó hỗ trợ lược đồ, miền và cổng):

Sử dụng Request.GetFullDomain()

// Add this class to your project
public static class HttpRequestExtensions{
    public static string GetFullDomain(this HttpRequestBase request)
    {
        var uri= request?.UrlReferrer;
        if (uri== null)
            return string.Empty;
        return uri.Scheme + Uri.SchemeDelimiter + uri.Authority;
    }
}

// Now Use it like this:
Request.GetFullDomain();
// Example output:    https://www.example.com:5031
// Example output:    http://www.example.com:5031
// Example output:    https://www.example.com

1

Cách khác:


string domain;
Uri url = HttpContext.Current.Request.Url;
domain= url.AbsoluteUri.Replace(url.PathAndQuery, string.Empty);

Câu trả lời đơn giản nhưng đơn giản là tuyệt vời!
Shiroy

1

Làm thế nào về:

NameValueCollection vars = HttpContext.Current.Request.ServerVariables;
string protocol = vars["SERVER_PORT_SECURE"] == "1" ? "https://" : "http://";
string domain = vars["SERVER_NAME"];
string port = vars["SERVER_PORT"];

0

Sử dụng UriBuilder:

    var relativePath = ""; // or whatever-path-you-want
    var uriBuilder = new UriBuilder
    {
        Host = Request.Url.Host,
        Path = relativePath,
        Scheme = Request.Url.Scheme
    };

    if (!Request.Url.IsDefaultPort)
        uriBuilder.Port = Request.Url.Port;

    var fullPathToUse = uriBuilder.ToString();

-1

Làm thế nào về:

String domain = "http://" + Request.Url.Host

Không tệ, nhưng điều gì sẽ xảy ra nếu trang web của bạn có các trang an toàn, tức là https: // Nếu miền của bạn không được lưu trữ trên cổng 80 thì sao?
Matt Mitchell,
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.