2010-09-29 3 views
15

J'utilise le module Rewrite IIS 7 pour réécrire une URL comme entrant:exception ASP.NET MVC UrlHelper.GenerateUrl: "Impossible d'utiliser l'un des principaux .. pour sortir au-dessus du répertoire principal"

http://server/year/all

à

http://server/application/controller/year/all

tout fonctionne très bien, sauf quand, lors du traitement de la requête réécrite, j'utilise la méthode UrlHelper.GenerateUrl() de MVC:

UrlHelper.GenerateUrl(
    "Assets", 
    "Css", 
    "Asset", 
    new RouteValueDictionary(new { site = site.Name, assetPath = assetPath }), 
    RouteTable.Routes, 
    controllerContext.RequestContext, 
    false); 

appel de cette méthode dans un HttpException:

System.Web.HttpException: Cannot use a leading .. to exit above the top directory. 
    at System.Web.Util.UrlPath.ReduceVirtualPath(String path) 
    at System.Web.Util.UrlPath.Reduce(String path) 
    at System.Web.VirtualPath.Combine(VirtualPath relativePath) 
    at System.Web.VirtualPathUtility.Combine(String basePath, String relativePath) 
    at System.Web.Mvc.PathHelpers.GenerateClientUrlInternal(HttpContextBase httpContext, String contentPath) 
    at System.Web.Mvc.PathHelpers.GenerateClientUrl(HttpContextBase httpContext, String contentPath) 
    at System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues) 

En regardant le RequestContext, il semble que tous les chemins de demande sont corrects (c.-à-ont les valeurs réécrites). Je n'arrive pas à comprendre pourquoi il essaie de sortir du répertoire de premier niveau ... Il n'y a nulle part où nous utilisons ... dans un chemin.

J'ai également vérifié que RewriteModule est au-dessus du module UrlRouting dans IIS. Bien que je puisse entrer dans les méthodes du framework, je ne peux pas examiner les variables locales (que ce soit dans VS ou WinDbg) car il a été optimisé par le compilateur.

Des pensées?

+0

Je suis confronté au même problème et je n'ai pas trouvé de solution. Pour l'instant, je ne fais que coder des liens hypertexte au lieu d'utiliser Html.ActionLink où j'obtiens l'exception. Avez-vous trouvé une solution? –

+0

@Rob: nous n'avons pas trouvé de solution. J'ai été capable de le suivre jusqu'à la présence de l'en-tête X_ORIGINAL_URL dans la requête. IIS place cet en-tête à chaque fois qu'il réécrit une URL. Il utilise cet en-tête pour essayer d'annuler la réécriture de l'url, car vous ne voulez probablement pas que l'URL générée suive le format réécrit. Il se bloque pour nous quand il prend l'URL d'origine en considération. Cela n'a pas beaucoup de sens d'utiliser * toujours * l'URL d'origine - pour nous, nous voulons juste qu'elle génère l'URL et ignore l'URL d'origine. Il n'y a aucun moyen que nous avons trouvé pour remplacer ce comportement. –

+0

J'ai fini par passer d'une réécriture à une redirection et cela a réglé le problème. nos URL contiennent maintenant la zone, ce qui n'est pas idéal, mais il est plus important que le site fonctionne sans trop se soucier du routage de MVC. –

Répondre

0

Je ne sais pas si ça aide, mais voici le code de jeter l'exception:

internal static string ReduceVirtualPath(string path) 
{ 
    int length = path.Length; 
    int startIndex = 0; 
    while (true) 
    { 
     startIndex = path.IndexOf('.', startIndex); 
     if (startIndex < 0) 
     { 
      return path; 
     } 
     if (((startIndex == 0) || (path[startIndex - 1] == '/')) && ((((startIndex + 1) == length) || (path[startIndex + 1] == '/')) || ((path[startIndex + 1] == '.') && (((startIndex + 2) == length) || (path[startIndex + 2] == '/'))))) 
     { 
      break; 
     } 
     startIndex++; 
    } 
    ArrayList list = new ArrayList(); 
    StringBuilder builder = new StringBuilder(); 
    startIndex = 0; 
    do 
    { 
     int num3 = startIndex; 
     startIndex = path.IndexOf('/', num3 + 1); 
     if (startIndex < 0) 
     { 
      startIndex = length; 
     } 
     if ((((startIndex - num3) <= 3) && ((startIndex < 1) || (path[startIndex - 1] == '.'))) && (((num3 + 1) >= length) || (path[num3 + 1] == '.'))) 
     { 
      if ((startIndex - num3) == 3) 
      { 
       if (list.Count == 0) 
       { 
        throw new HttpException(SR.GetString("Cannot_exit_up_top_directory")); 
       } 
       if ((list.Count == 1) && IsAppRelativePath(path)) 
       { 
        return ReduceVirtualPath(MakeVirtualPathAppAbsolute(path)); 
       } 
       builder.Length = (int) list[list.Count - 1]; 
       list.RemoveRange(list.Count - 1, 1); 
      } 
     } 
     else 
     { 
      list.Add(builder.Length); 
      builder.Append(path, num3, startIndex - num3); 
     } 
    } 
    while (startIndex != length); 
    string str = builder.ToString(); 
    if (str.Length != 0) 
    { 
     return str; 
    } 
    if ((length > 0) && (path[0] == '/')) 
    { 
     return "/"; 
    } 
    return "."; 
} 
8

Ceci est une solution de contournement grotesque impliquant les détails de mise en œuvre privée, mais ajouter ceci:

HttpContext.Current.Request.ServerVariables.Remove("IIS_WasUrlRewritten"); 

On évite ainsi l'interne vérifiez dans PathHelper.GenerateClientUrlInternal pour voir si la demande a été réécrite. Il est très probable que cela va casser certains scénarios, comme suggéré par ce commentaire dans les sources de référence:

// Since the rawUrl represents what the user sees in his browser, it is what we want to use as the base 
// of our absolute paths. For example, consider mysite.example.com/foo, which is internally 
// rewritten to content.example.com/mysite/foo. When we want to generate a link to ~/bar, we want to 
// base it from/instead of /foo, otherwise the user ends up seeing mysite.example.com/foo/bar, 
// which is incorrect. 
+0

Pourriez-vous dire où on devrait lancer ça? Dans mon cas, il n'y a pas de variable serveur IIS_WasUrlRewritten ... Mais j'ai essayé de supprimer l'URL X-Original des en-têtes et des variables serveur qui sont censées faire quelque chose avec Url Rewrite, mais ni supprimer cela qui a fonctionné depuis un Http Module (bien que la valeur soit là, mais appeler Remove() ne fait rien avec). – Piedone

+0

Malheureusement, cela n'a pas résolu le problème pour nous. –

Questions connexes