关于asp.net mvc:获取没有非标准端口的原始URL(C#)

Get original url without non-standard port (C#)

第一个问题!

环境

MVC,C,AppHarbor。

问题

我正在调用OpenID提供者,并基于域生成绝对回调URL。

在我的本地机器上,如果我打了http://localhost:12345/login,这个就可以了。

1
Request.Url; //gives me `http://localhost:12345/callback`

但是,在我部署的AppHarbor上,因为它们使用的是非标准端口,即使我在"http://sub.example.com/login"上访问它也是如此。

1
Request.Url; //gives me http://sub.example.com:15232/callback

这会使我的回调变得更糟,因为端口号不在原始源URL中!

我试过了

  • 请求URL
  • 请求.url.originalString
  • 请求网址

所有这些都给了我"http://sub.example.com:15232/callback"。

此外,为了澄清这不是领域问题,我从DotNetOpenAuth得到的错误消息是

1
'http://sub.example.com:14107/accounts/openidcallback' not under realm 'http://*.example.com/'.

我想我没把那个塞进去?

现在,我要考虑一些像

  • 预处理器命令(如果调试,则输入端口)
  • 字符串替换(request.url.contains("localhost"))

所有这些都不是100%的解决方案,但我厌倦了思考什么是我所缺少的简单属性。我也读过这篇文章,但似乎没有一个公认的答案(更多的是关于道路而不是权威)。所以我要对你们说。

总结

所以如果我有http://localhost:12345/login,我需要从请求上下文中获取http://localhost:12345/callback

如果我有"http://sub.example.com/login",不管它在哪个端口上,我都应该得到"http://sub.example.com/callback"。

谢谢!(睡眠时间,早上回答任何问题)


这是像AppHarbor这样的负载平衡设置中的一个常见问题-我们提供了一个示例解决方案。

更新:对于许多ASP.NET应用程序来说,更理想的解决方案可能是将aspnet:UseHostHeaderForRequestUrlappsetting设置为true。我们(AppHarbor)已经看到一些客户在将它与他们的WCF应用程序一起使用时遇到问题,这就是为什么我们在默认情况下没有启用它的原因,并且Stil为这些情况推荐了上述解决方案。您可以使用AppHarbor的"配置变量"配置它,以便在部署时插入AppSettings。在本文中可以找到更多信息。


我最近遇到了一个问题,我将一个URL与当前的URL进行了比较,然后在此基础上突出显示了导航。它在本地工作,但不在生产中。

我把http://example.com/path/to/file.aspx作为我的文件,但当查看该文件并运行Request.Url.ToString()时,它在负载平衡的生产环境中生成https://example.com:81/path/to/file.aspx

现在我使用Request.Url.AbsolutePath只是给我/path/to/file.aspx,因此忽略了模式、主机名和端口号。

当我需要将它与我使用的每个导航项的URL进行比较时:New Uri(theLink.Href).AbsolutePath


我看这是一条旧线。我在IIs7.5上运行MVC5时遇到了这个问题,前面有一个Apache代理。在服务器外部,我将得到"空响应",因为ASP.NET应用程序从带有自定义端口的Apache获取URL。

为了让应用程序重定向到子路径而不包括"自定义"端口,请忘记响应/请求对象,并使用传输方法。例如,如果我希望用户在尚未登录的情况下自动重定向到登录页面:

1
2
if (!User.Identity.IsAuthenticated)  
    Server.TransferRequest("Account/Login");

如果在框架中使用urlbuilder类,您可以轻松地绕过这个问题。在builder类上,如果将端口设置为-1,则将删除端口号:

1
new UriBuilder("http://sub.example.com:15232/callback"){ Port = -1}

返回:http://sub.example.com/callback

要在本地计算机上保留端口号,只需检查request.islocal,不要将-1应用于端口。

我将把它包装成一个扩展方法来保持它的整洁。


类似的东西

1
2
3
String port = Request.ServerVariables["SERVER_PORT"] =="80" ?"" :":" + Request.ServerVariables["SERVER_PORT"];
String virtualRoot = Url.Content("~/");
destinationUrl = String.Format("http://{0}{1}{2}", Request.ServerVariables["SERVER_NAME"], port + virtualRoot,"/callback");


我最初的想法是获取referer变量并检查它是否包含端口,如果包含端口,请使用它,否则不要使用。

如果这不是一个选项,因为代理可能会删除referer头变量,那么您可能需要使用一些客户端脚本来获取位置并将其传递回服务器。

我猜AppHarbor使用端口转发到IIS服务器,因此即使站点在端口80上,IIS也将其托管在另一个端口上,因此它不知道客户端连接的端口。