如何在MVC 3中获取当前页面的URL

403

我在构建一个博客时使用了 Facebook 评论插件。它包含一些 FBXML 标签,由页面引用的 Facebook JavaScript 解释。

一切都正常工作,但我必须将当前的完全限定 URL 传递给插件。

<div style="width: 900px; margin: auto;">
    <div id="fb-root"></div>
    <fb:comments href="URL HERE" num_posts="10" width="900"></fb:comments>
</div>

如何获取当前页面URL的最佳方法?请求URL。

解决方案

以下是我的解决方案的最终代码:

<fb:comments href="@Request.Url.AbsoluteUri" num_posts="15" width="900"></fb:comments>
10个回答

580

3
出于某种原因,似乎无法获取完整的URL,只能获取域名后面的部分。 - Chev
6
@Chevex,Request.Url.ToString()Request.Url.AbsoluteUri 怎么样? - Darin Dimitrov
9
几乎了。Request.Url.AbsoluteUri就可以了 :) - Chev
2
@Chevex - 网站托管在哪个端口?如果是80端口,那么是的,你看不到端口号。我是说,在一个环境中,有一个虚拟IP发布端口80到一个或多个机器上的不同端口(例如81),那么Asp.Net将始终不正确地向URL添加:81。 - Andras Zoltan
30
要获取不同的URL片段示例,请查看以下网址:http://www.cambiaresearch.com/articles/53/how-do-i-get-paths-and-url-fragments-from-the-httprequest-object - ms007
显示剩余7条评论

49
将此扩展方法添加到您的代码中:
public static Uri UrlOriginal(this HttpRequestBase request)
{
  string hostHeader = request.Headers["host"];

  return new Uri(string.Format("{0}://{1}{2}",
     request.Url.Scheme, 
     hostHeader, 
     request.RawUrl));
}

然后,您可以通过RequestContext.HttpContext.Request属性执行它。

在使用本地网站的端口(如果内部网站通过虚拟IP负载平衡发布,并且端口用于发布规则,则是一个重大问题)不是80端口的计算机上会出现Asp.Net的错误(可以通过以下方法避免)- 即使原始请求没有使用端口,Asp.Net也始终会在AbsoluteUri属性上添加端口。

此代码确保返回的URL始终等于浏览器最初请求的URL(包括端口 - 因为它将包含在主机标头中)在任何负载平衡等操作之前。

至少,在我们(相当复杂的!)环境中是这样的 :)

如果有任何奇怪的代理在其中重写主机标头,那么这也将无法正常工作。

更新 2013年7月30日

如下面的评论中@KevinJones提到的 - 我在下一节中提到的设置已在此处记录:http://msdn.microsoft.com/en-us/library/hh975440.aspx

虽然我必须说,当我尝试时,我无法让它起作用 - 但那可能只是我打错了一个字母。

更新 2012年7月9日

我有一段时间以前就遇到了这个问题,本来想更新这个答案,但从未这样做。当这个答案收到投票时,我想现在应该更新一下。

我在Asp.Net中提到的“错误”可以使用一个显然未记录的appSettings值来控制 - 称为'aspnet: UseHostHeaderForRequest'

<appSettings>
  <add key="aspnet:UseHostHeaderForRequest" value="true" />
</appSettings>

我在查看ILSpy中的HttpRequest.Url时发现了这个 - 在以下从ILSpy视图复制/粘贴的左边用--->表示:

public Uri Url
{
  get
  {
    if (this._url == null && this._wr != null)
    {
      string text = this.QueryStringText;
      if (!string.IsNullOrEmpty(text))
      {
        text = "?" + HttpEncoder.CollapsePercentUFromStringInternal(text, 
          this.QueryStringEncoding);
      }
 ---> if (AppSettings.UseHostHeaderForRequestUrl)
      {
        string knownRequestHeader = this._wr.GetKnownRequestHeader(28);
        try
        {
          if (!string.IsNullOrEmpty(knownRequestHeader))
          {
            this._url = new Uri(string.Concat(new string[]
            {
              this._wr.GetProtocol(),
              "://",
              knownRequestHeader,
              this.Path,
              text 
            }));
          }
        }
        catch (UriFormatException)
        { }
     }
     if (this._url == null) { /* build from server name and port */
       ...

我个人还没有使用过它 - 由于它是未记录的,因此不能保证会一直存在 - 不过它可能会做我上面提到的同样的事情。为了增加搜索结果的相关性 - 并承认其他人发现了这一点 - 在 Twitter 上 Nick Aceves 也提到了'aspnet:UseHostHeaderForRequest'设置


好的,那么如果你不直接在控制器中编写代码,你从哪里或如何获取HttpRequestBase实例呢? - PositiveGuy
@CoffeeAddict 嗯,在mvc3中,你有HttpContext.Current.Request,因为Asp.net 4使用基本抽象。如果在.net 3.5或更低版本上,则可以使用System.Web.Abstractions中的HttpRequestWrapper来包装相同的属性。 - Andras Zoltan
3
很晚才来,但是UseHostHeaderForRequestUrl在这里有文档http://msdn.microsoft.com/en-us/library/hh975440.aspx。 - Kevin Jones
不错的发现!至少他们终于在4.5文档中添加了它! - Andras Zoltan

17
public static string GetCurrentWebsiteRoot()
{
    return HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
}

14
Request.Url.PathAndQuery
应该完美地运行,特别是当你只需要相对 URI(但保留查询字符串)时。

9

我也因为Facebook原因而寻找这个,迄今为止给出的答案都不符合要求或过于复杂。

@Request.Url.GetLeftPart(UriPartial.Path)

获取完整的协议、主机和路径,"不包括"查询字符串。如果使用非默认80端口,则还包括端口。


太好了!我怀疑在提问时这个还不存在?我感觉我应该会看到它 :) - Chev
我以为我看到这是刚刚添加的,但我刚刚检查了一下,似乎自.NET 1.1以来就一直存在。谁知道呢。 - johnw182

5

我最喜欢的技术是...

Url.Content(Request.Url.PathAndQuery)

或者只是...
Url.Action()

Url.Action() 只提供 URL 的右侧部分,如果您需要完整的 URL 呢? - Alok

4

对于完整的URL,我在Core 3.0上成功实现了这个方法:

$"{Request.Scheme}://{Request.Host.Value}{Request.Path.Value}"

1

在其他答案中没有提到的一件事是大小写敏感性,如果它将被多次引用(原始问题中没有,但考虑到这个问题出现在许多类似搜索中,这是值得考虑的)。根据我找到的其他答案,最初以下内容适用于我:

Request.Url.AbsoluteUri.ToString()

但为了更可靠,这个过程变成了:

Request.Url.AbsoluteUri.ToString().ToLower()

然后针对我的需求(检查网站正在访问的域名并显示相关内容):

Request.Url.AbsoluteUri.ToString().ToLower().Contains("xxxx")


这并不能使其“更可靠”。是否将其转换为小写取决于您实际尝试做什么以及为什么区分大小写在那里有意义。通常,您确实希望URL区分大小写。 - CodeCaster
1
@CodeCaster 是的,“更可靠”的术语是基于我的个人经验而言的,因为我绝对不希望URL区分大小写,因为这会给客户带来无尽的问题。 - Lyall

1
对我来说,问题出在我试图在控制器的构造函数中访问HTTPContext,而此时HTTPContext还没有准备好。当将其移至Index方法内部时,它可以正常工作:
var uri = new Uri(Request.Url.AbsoluteUri);
url = uri.Scheme + "://" + uri.Host + "/";enter code here

0

浏览器历史记录的单页样式案例

HttpContext.Request.UrlReferrer

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