如何从URL字符串中删除端口号

81

我有以下代码片段:

string tmp = String.Format("<SCRIPT FOR='window' EVENT='onload' LANGUAGE='JavaScript'>javascript:window.open('{0}');</SCRIPT>", url);

ClientScript.RegisterClientScriptBlock(this.GetType(), "NewWindow", tmp);

此代码生成的URL包括端口号,我认为这是因为网站使用端口80,在这个代码中我尝试从网站的虚拟目录加载页面。有什么方法可以抑制此代码生成的URL字符串中的端口号?


4
请点击答案分数下方的粗体来接受最佳答案!这样可以使内容更易于理解。 - ahmadali shafiee
8个回答

154

使用Uri.GetComponents方法。如果要删除端口组件,您需要将所有其他组件组合起来,例如:

var uri = new Uri( "http://www.example.com:80/dir/?query=test" );
var clean = uri.GetComponents( UriComponents.Scheme | 
                               UriComponents.Host | 
                               UriComponents.PathAndQuery, 
                               UriFormat.UriEscaped );

编辑:我找到了更好的方法:

var clean = uri.GetComponents( UriComponents.AbsoluteUri & ~UriComponents.Port,
                               UriFormat.UriEscaped );

UriComponents.AbsoluteUri 会保留所有组件,因此 & ~UriComponents.Port 只会排除端口。


6
根据最新编辑:很遗憾我无法再次点赞。非常优雅的回答;-) - zerkms
谢谢!通常你只需要使用“或”标志-枚举,所以我几乎忘记了你可以使用其他位运算。 - Danko Durbić
1
非常干净的解决方案,只需将ToCleanUrl()扩展添加到Uri中即可。 - Gent
Danko的解决方案对于我来说不起作用,使用了uri = new Uri("localhost:52798"),所以我使用了var clean = uri.OriginalString.Replace(":" + uri.LocalPath,""),这看起来很丑陋但是有效。 - Xavave
要清除端口,您可以使用.setPort(-1),要清除字符串组件,您可以使用.setUserInfo(null),null将起到作用。 - Barel elbaz

97
UriBuilder u1 = new UriBuilder( "http://www.example.com:80/dir/?query=test" );
u1.Port = -1;
string clean = u1.Uri.ToString();

UriBuilderPort 属性设置为 -1 将删除任何显式端口,并隐式使用协议方案的默认端口值。


1
我发现在这个解决方案中跳过 u1.Port = -1; 就可以了 - 虽然上面的那个方法也会排除任何端口号,而不仅仅是80,所以对于某些情况仍然有用。 - StormFoo
2
请注意,您可能需要使用.AbsoluteUri而不是.ToString。https://dev59.com/Nmsz5IYBdhLWcg3w17jQ#7624992 - Michael Haren
在将Port设置为_-1_后,不需要调用Uri。相反,可以简单地使用string clean = u1.ToString(); - Ray

51

基于Ian Flynn的想法,这是一个更通用的解决方案(适用于http、https、ftp等协议)。如果有自定义端口,则此方法不会将其删除。根据协议自动定义自定义端口。

    var uriBuilder = new UriBuilder("http://www.google.fr/");
    if (uriBuilder.Uri.IsDefaultPort)
    {
        uriBuilder.Port = -1;
    }
    return uriBuilder.Uri.AbsoluteUri;

2021年4月更新

在较新的 .NET 版本中,Uri.AbsoluteUri 默认情况下会移除默认端口并保留自定义端口。上述代码片段等同于:

    var uriBuilder = new UriBuilder("http://www.google.fr/");
    return uriBuilder.Uri.AbsoluteUri;

3
完美主义者 ;) +1 - T-moty
4
请注意,您可能希望使用.AbsoluteUri而不是.ToString。 https://dev59.com/Nmsz5IYBdhLWcg3w17jQ#7624992 - Michael Haren
默认情况下,.AbsoluteUri 是否会自动剥离默认端口?我们需要第一部分吗? - Shubham Sharma
1
@ShubhamSharma 看起来最新的 .net 框架已经有所改变。 - labilbe

8

我会使用 System.Uri 进行此操作。虽然我没有尝试过,但它似乎的 ToString 实际上会输出你想要的内容:

var url = new Uri("http://google.com:80/asd?qwe=asdff");
var cleanUrl = url.ToString();

如果没有,您可以组合url成员的组件来创建cleanUrl字符串。

5
这并不会移除除默认端口(通常为80端口)以外的端口。 - Jens
是的,我错过了“当端口是方案的默认端口时,此方法返回的字符串不包含端口信息。”(http://msdn.microsoft.com/en-us/library/system.uri.tostring.aspx),当我写我的答案时。 - zerkms
@Jens:它不应该删除其他端口。只有80应该是http协议的默认端口。如果您删除任何端口,则会得到指向另一个资源的url。 - zerkms

4
var url = "http://google.com:80/asd?qwe=zxc#asd";
var regex = new Regex(@":\d+");
var cleanUrl = regex.Replace(url, "");

System.Uri 这个方案也是可行的,但会更加臃肿。


那个正则表达式会破坏像 http://asdf.com:80/asdf?something:12:34:56 这样的URI。(尽管该URI应该被正确编码,但您不能确定它是否被编码) - Isak Savo
@Isak:你可以使用@"(?<![^/]/[^/]*):\d+"来避免这种情况。 - Jens
@Isak:我不确定我们是否应该使用构造错误的URL。RFC规定查询路径中的“:”应编码为%3A。点。 - zerkms
是的,我知道,但我更喜欢编写防弹代码,不对输入做任何假设。 - Isak Savo
3
用一句话概括:将URL中的端口号去掉。 - Bjørn Thomsen
显示剩余2条评论

2
您可以使用UriBuilder并将端口的值设置为-1,代码如下:
Uri tmpUri = new Uri("http://LocalHost:443/Account/Index");
UriBuilder builder = new UriBuilder(tmpUri);
builder.Port = -1;
Uri newUri = builder.Uri;

0

好的,谢谢,我想通了...使用了KISS原则...

string redirectstr = String.Format(
   "http://localhost/Gradebook/AcademicHonestyGrid.aspx?StudentID={0}&ClassSectionId={1}&uid={2}", 
   studid, 
   intSectionID, 
   HttpUtility.UrlEncode(encrypter.Encrypt(uinfo.ToXml())));

Response.Redirect(redirectstr );

对于我的测试工具来说,它的表现很好


0

你也可以使用URIBuilder属性来实现这个功能,它具有按照你想要的方式输出URL的属性。


大家好,我正在尝试在生成URL字符串之前抑制端口号。如果无法使用此命令,我也可以接受等效的解决方案。 - Brono The Vibrator
请注意,tmp变量的内容为: <SCRIPT FOR='window' EVENT='onload' LANGUAGE='JavaScript'>javascript:window.open('../Gradebook/AcademicHonestyGrid.aspx?StudentID=35832&ClassSectionId=8487&uid=yjoEG2CuaptYAyqOEPwBFSbAarVk%...(由于加密和过长而省略) - Brono The Vibrator
看起来像是 .NET Framework 或 IIS 中添加了 http://localhost:port 数字。 - Brono The Vibrator
使用 UriBuilder.Uri 属性,然后您可以使用此线程中顶部答案中显示的模板。 - maxp

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