Comment obtenir l'URL de la page actuelle dans MVC 3

360

J'utilise le plugin de commentaires Facebook sur un blog que je crée. Il a des balises FBXML qui sont interprétées par le javascript facebook référencé sur la page.

Tout cela fonctionne bien, mais je dois transmettre l'URL actuelle et complète au plugin.

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

Quelle est la meilleure façon d'obtenir l'URL de la page actuelle? L'URL de la demande.

Solution

Voici le code final de ma solution:

<fb:comments href="@Request.Url.AbsoluteUri" num_posts="15" width="900"></fb:comments>
Chev
la source

Réponses:

533

Vous pouvez utiliser le Request.RawUrl, Request.Url.OriginalString, Request.Url.ToString()ou Request.Url.AbsoluteUri.

Darin Dimitrov
la source
2
Pour une raison quelconque, cela ne semble pas obtenir l'URL entière, juste tout ce qui se trouve après le domaine.
Chev
6
@Chevex, que diriez-vous Request.Url.ToString()ou Request.Url.AbsoluteUri?
Darin Dimitrov
9
Presque. Request.Url.AbsoluteUril'a fait :)
Chev
2
@Chevex - sur quel port le site est-il hébergé? Si c'est le port 80 alors, oui, vous n'en verrez pas. Je dis que dans un environnement où il y a un port de publication IP virtuel 80 vers une ou plusieurs machines sur un port différent (par exemple 81), Asp.Net ajoutera toujours: 81 à l'URL incorrectement
Andras Zoltan
29
pour obtenir des échantillons des différents fragments d'URL, consultez: cambiaresearch.com/articles/53/…
ms007
48

Ajoutez cette méthode d'extension à votre code:

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));
}

Et puis vous pouvez l'exécuter sur la RequestContext.HttpContext.Requestpropriété.

Il y a un bogue (peut être contourné, voir ci-dessous) dans Asp.Net qui se produit sur les machines qui utilisent des ports autres que le port 80 pour le site Web local (un gros problème si les sites Web internes sont publiés via l'équilibrage de charge sur IP virtuelle et les ports sont utilisés en interne pour les règles de publication), où Asp.Net ajoutera toujours le port sur la AbsoluteUripropriété - même si la requête d'origine ne l'utilise pas.

Ce code garantit que l'URL renvoyée est toujours égale à l'URL que le navigateur a initialement demandée (y compris le port - car il serait inclus dans l'en-tête de l'hôte) avant tout équilibrage de charge, etc.

Au moins, c'est le cas dans notre environnement (plutôt alambiqué!) :)

S'il y a des procurations géniales entre les deux qui réécrivent l'en-tête de l'hôte, cela ne fonctionnera pas non plus.

Mise à jour du 30 juillet 2013

Comme mentionné par @KevinJones dans les commentaires ci-dessous - le paramètre que je mentionne dans la section suivante a été documenté ici: http://msdn.microsoft.com/en-us/library/hh975440.aspx

Même si je dois dire que je ne pouvais pas le faire fonctionner quand je l'ai essayé - mais cela pourrait simplement être moi qui fais une faute de frappe ou quelque chose.

Mise à jour du 9 juillet 2012

Je suis tombé sur cela il y a un petit moment et je voulais mettre à jour cette réponse, mais je ne l'ai jamais fait. Quand un vote positif est venu sur cette réponse, j'ai pensé que je devais le faire maintenant.

Le «bug» que je mentionne dans Asp.Net peut être contrôlé avec une valeur appSettings apparemment non documentée - appelée 'aspnet:UseHostHeaderForRequest'- c'est-à-dire:

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

Je suis tombé sur cela en regardant HttpRequest.Urldans ILSpy - indiqué par le --->côté gauche du copier / coller suivant de cette vue 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 */
       ...

Personnellement, je ne l'ai pas utilisé - il n'est pas documenté et donc pas garanti de rester - mais il pourrait faire la même chose que je mentionne ci-dessus. Pour augmenter la pertinence des résultats de recherche - et pour reconnaître quelqu'un d'autre qui semble avoir découvert cela - le 'aspnet:UseHostHeaderForRequest'paramètre a également été mentionné par Nick Aceves sur Twitter

Andras Zoltan
la source
ok alors où ou comment obtenez-vous l'instance man de HttpRequestBase permet de dire si vous ne travailliez pas directement avec du code dans un contrôleur par exemple?
PositiveGuy
@CoffeeAddict Eh bien, dans mvc3, vous avez HttpContext.Current.Request, car Asp.net 4 utilise les abstractions de base. Si sur .net 3.5 ou inférieur, vous pouvez utiliser HttpRequestWrapper autour de la même propriété, à partir de System.Web.Abstractions
Andras Zoltan
3
Très tard, mais UseHostHeaderForRequestUrl est documenté ici msdn.microsoft.com/en-us/library/hh975440.aspx
Kevin Jones
bon endroit! au moins, ils l'ont finalement ajouté pour la documentation 4.5!
Andras Zoltan
14
public static string GetCurrentWebsiteRoot()
{
    return HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
}
Brian Ogden
la source
12
Request.Url.PathAndQuery

devrait fonctionner parfaitement, surtout si vous ne voulez que l'URI relatif (mais en gardant les chaînes de requête)

Lucius
la source
8

Moi aussi, je cherchais cela pour des raisons Facebook et aucune des réponses fournies jusqu'à présent ne fonctionnait comme nécessaire ou n'était trop compliquée.

@Request.Url.GetLeftPart(UriPartial.Path)

Obtient le protocole complet, l'hôte et le chemin d'accès "sans" la chaîne de requête. Inclut également le port si vous utilisez autre chose que le 80 par défaut.

johnw182
la source
Super trouvaille! Je soupçonne que cela n'existait pas au moment de la demande? Je sens que j'aurais vu ça :)
Chev
Je pensais avoir vu où cela venait d'être ajouté, mais je viens de vérifier et il semble que cela existe depuis .NET 1.1. Qui sait.
johnw182
4

Mon préféré...

Url.Content(Request.Url.PathAndQuery)

ou juste...

Url.Action()
Carter Medlin
la source
Url.Action () fournit uniquement le côté droit de l'url, que faire si vous avez besoin d'une URL complète complète?
Alok
1

Une chose qui n'est pas mentionnée dans les autres réponses est la sensibilité à la casse, si elle va être référencée à plusieurs endroits (ce qui n'est pas dans la question d'origine mais mérite d'être pris en compte car cette question apparaît dans de nombreuses recherches similaires ). Sur la base d'autres réponses, j'ai trouvé que les éléments suivants ont fonctionné pour moi au départ:

Request.Url.AbsoluteUri.ToString()

Mais pour être plus fiable, cela est devenu:

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

Et puis pour mes besoins (vérifier à partir de quel nom de domaine le site est accédé et montrer le contenu pertinent):

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

Lyall
la source
Cela ne le rend pas "plus fiable". L'utilité de la minuscule dépend entièrement de ce que vous essayez de faire et de la raison pour laquelle la sensibilité à la casse aurait un sens. En général , vous ne voulez que l'URL pour être sensible à la casse.
CodeCaster
1
@CodeCaster Oui, le terme «plus fiable» était basé sur ma propre expérience, car je ne veux certainement pas que les URL soient sensibles à la casse car cela ne cause pas de problèmes aux clients.
Lyall
0

Pour moi, le problème était quand j'ai essayé d'accéder HTTPContextau constructeur du contrôleur alors qu'il HTTPContextn'était pas encore prêt. Lorsque déplacé à l'intérieur de la méthode Index, cela a fonctionné:

var uri = new Uri(Request.Url.AbsoluteUri);
url = uri.Scheme + "://" + uri.Host + "/";enter code here
bateaueng
la source
0

Le cas (style de page unique) pour l'historique du navigateur

HttpContext.Request.UrlReferrer
Hamit YILDIRIM
la source