.NET - 获取协议、主机和端口

278

在.NET中,有没有一种简单的方法可以快速获取当前协议、主机和端口?例如,如果我在以下URL上:

http://www.mywebsite.com:80/pages/page1.aspx

我需要返回:

http://www.mywebsite.com:80

我知道可以使用Request.Url.AbsoluteUri获取完整的URL,也知道可以使用Request.Url.Authority获取主机和端口,但不确定获取协议的最佳方式,而不是解析URL字符串。

您有什么建议吗?


1
请查看我在这里回答类似问题的答案 - https://dev59.com/F3VD5IYBdhLWcg3wE3bz#1534478 - William
9个回答

466

虽然 @Rick 对这个问题有已接受的答案,但实际上有一种更短的方法可以做到这一点,使用名字不太好的Uri.GetLeftPart()方法。

Uri url = new Uri("http://www.mywebsite.com:80/pages/page1.aspx");
string output = url.GetLeftPart(UriPartial.Authority);

不过,GetLeftPart() 有一个限制。如果端口是该方案的默认端口,则会将其删除。由于80端口是http的默认端口,因此上面示例中的GetLeftPart() 输出将为 http://www.mywebsite.com

如果端口号不是80,则它将包含在结果中。


12
在我看来,这是最好的例子。它适用于本地主机和端口以及实时实例。 - The Muffin Man
17
GetLeftPart - 真的,OMG很好的命名。 - Valentin Kuzub
2
微软使用“Authority”这个术语,但我不知道它是否是一个标准术语。请参见https://dev59.com/M3I95IYBdhLWcg3wzhZ9。 - dthrasher
GetLeftPart可能是解决最初问题的最佳方案,只需小心Uri的来源,如果它是ASP.Net请求对象,则在集群环境中可能已被覆盖。在我的情况下,在部署后缺少端口。解决方案可以是来自FunnelWeb源代码的扩展方法(https://bitbucket.org/TheBlueSky/funnelweb/src/b64c74f361d3/src/FunnelWeb/Utilities/HttpRequestExtensions.cs)。 - Grigorii
2
我个人不太喜欢这样使用“Uri”类。在许多情况下,此构造函数会抛出异常。 对于大多数情况,我更喜欢我的代码在放弃当前任务之前具有一定的容错性。 - Jonathan Wood
显示剩余2条评论

187

以下 (C#) 代码应该能解决问题。

Uri uri = new Uri("http://www.mywebsite.com:80/pages/page1.aspx");
string requested = uri.Scheme + Uri.SchemeDelimiter + uri.Host + ":" + uri.Port;

27
所需的字符串为 uri.Scheme + Uri.SchemeDelimiter + uri.Authority。其中,uri.Scheme表示URI的协议部分,Uri.SchemeDelimiter表示该协议所使用的分隔符,uri.Authority表示URI的授权部分。 - tranmq
21
当没有端口时,这个答案可能是错误的,因为它会插入一个“:”。如@dthrasher所指出的,使用Uri.GetLeftPart - gman
请注意,在某些情况下,您仍然希望使用uri.Headers["Host"]而不是GetLeftPart()进行连接,例如在代理后面,您的服务可能正在侦听不同/非标准端口,并且如果您在回调中使用该URL(具有私有端口),则主机将无法访问。 - doveryai
这个答案…如此美丽、优雅而简单。 - Westley Bennett
使用这种解决方案时无需担心没有端口号的问题。微软表示:“如果未将端口指定为 URI 的一部分,则 Port 属性返回协议的默认值。”/ https://learn.microsoft.com/en-us/dotnet/api/system.uri.port?view=net-5.0 - Erk

69

如果你在使用Asp.Net或者可以访问HttpContext.Current.Request的话,我认为以下两种方法更加简单通用:

var scheme = Request.Url.Scheme; // will get http, https, etc.
var host = Request.Url.Host; // will get www.mywebsite.com
var port = Request.Url.Port; // will get the port
var path = Request.Url.AbsolutePath; // should get the /pages/page1.aspx part, can't remember if it only get pages/page1.aspx

我希望这能有所帮助。 :)

1
我更喜欢这种方法,因为我可以只获取我想要的部分,而不必担心字符串是否格式良好以获取端口。+1 - Jrud
这些属性的更多细节请参考:http://blog.jonschneider.com/2014/10/systemuri-net-framework-45-visual-guide.html - Jon Schneider

38

更结构化的方法是使用UriBuilder来获取URL,这避免了直接进行字符串操作。

var builder = new UriBuilder(Request.Url.Scheme, Request.Url.Host, Request.Url.Port);

24

更短的方式,可能需要更新的ASP.Net版本:

string authority = Request.Url.GetComponents(UriComponents.SchemeAndServer,UriFormat.Unescaped)

UriComponents 枚举类型允许您指定要包含哪些 URI 组件。


1
太好了,因为它可以在PCL中运行(.GetLeftPart()在那里不可用) - Sascha

23

Request.Url会返回请求的Uri。一旦您拥有了它,您可以检索几乎任何您想要的东西。要获取协议,请调用Scheme属性。

示例:

Uri url = Request.Url;
string protocol = url.Scheme;

希望这有所帮助。

13

与 Holger 的回答非常相似。如果您需要抓取 URL,可以尝试以下方法:

Uri uri = Context.Request.Url;         
var scheme = uri.Scheme // returns http, https
var scheme2 = uri.Scheme + Uri.SchemeDelimiter; // returns http://, https://
var host = uri.Host; // return www.mywebsite.com
var port = uri.Port; // returns port number

Uri类提供了许多方法,其中很多我没有列出。

在我的情况下,我需要获取LocalHostPort Number,所以我做了以下操作:

var Uri uri = Context.Request.Url;
var host = uri.Scheme + Uri.SchemeDelimiter + uri.Host + ":" + uri.Port; 

成功抓取到的网址:http://localhost:12345


0

对于我的情况

Uri uri = new Uri("http://www.mywebsite.com:80/pages/page1.aspx");
string requested = uri.Scheme + Uri.SchemeDelimiter + uri.Authority;

获取工作

https://www.mywebsite.com:80


这对Rick 2008年的回答有什么补充? - greybeard

0
在我的情况下,我使用这个。
Request.Url.ToString().Remove(Request.Url.ToString().Count() - (Request.ServerVariables["URL"].ToString().Count()))

哪里
Request.Url.ToString() 

返回的文本只有:

返回 http://www.mywebsite.com:80/pages/page1.aspx

Request.ServerVariables["URL"].ToString()

返回/pages/page1.aspx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接