2010-09-29 9 views
15

Używam modułu IIS 7 Rewrite przepisać przychodzące url podobny:ASP.NET MVC UrlHelper.GenerateUrl wyjątek: "Nie można użyć czołowym .. aby wyjść powyżej górnej katalogu"

http://server/year/all

do

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

Wszystko działa poprawnie, z wyjątkiem sytuacji, gdy przetwarzanie przepisany wniosek, używam UrlHelper.GenerateUrl metody MVC jest():

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

Wywołanie tej metody wyniki w 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) 

Patrząc na RequestContext, wydaje się, że wszystkie ścieżki są poprawne żądanie (czyli mają przepisane wartości). Nie mogę się domyślić, dlaczego próbuje wyjść z katalogu najwyższego poziomu ... Nigdzie nie używamy ... na ścieżce.

Upewniłem się również, że RewriteModule znajduje się powyżej modułu UrlRouting w IIS.

Chociaż mogę wejść do metod ramowych, nie mogę zbadać żadnej ze zmiennych lokalnych (w VS lub WinDbg), ponieważ jest ona zoptymalizowana pod kątem kompilacji.

Jakieś myśli?

+0

Mam do czynienia z tym samym problemem i nie znalazłem rozwiązania. Na razie jestem po prostu twardym kodowaniem hiperłącza zamiast używania Html.ActionLink, gdzie dostaję wyjątek. Znalazłeś rozwiązanie? –

+0

@Rob: nie znaleźliśmy rozwiązania. Udało mi się go znaleźć w nagłówku X_ORIGINAL_URL w żądaniu. IIS umieszcza ten nagłówek tam, gdzie przepisuje adres URL. Używa tego nagłówka, aby spróbować cofnąć przepisanie adresu URL, ponieważ prawdopodobnie nie chcesz, aby wygenerowany adres URL był zgodny z zapisanym formatem. Odkłada się na nas, gdy bierze pod uwagę oryginalny adres URL. Nie ma większego sensu, aby * zawsze * używać oryginalnego adresu URL - dla nas, chcemy tylko, aby wygenerował URL i zignorował oryginalny. Nie ma sposobu, abyśmy uznali to zachowanie za nadrzędne. –

+0

Skończyło się przejście z przepisywania na przekierowanie i to naprawiło problem. nasze adresy URL zawierają teraz obszar, który nie jest idealny, ale ważniejsze jest to, aby strona działała bez zbytniego wkręcania w routing MVC. –

Odpowiedz

0

Nie jestem pewien, czy to pomaga, ale tutaj jest kod rzuca wyjątek:

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

Jest to groteskowa obejście udziałem prywatnych szczegóły implementacji, ale dodać to:

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

ten sposób unika wewnętrzny sprawdź to w PathHelper.GenerateClientUrlInternal, aby sprawdzić, czy żądanie zostało przepisane. Jest całkiem prawdopodobne, że złamie to pewne scenariusze, o czym wspomniał ten komentarz w źródłach odniesienia:

// 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

Czy możesz powiedzieć, gdzie należy to uruchomić? W moim przypadku nie ma właściwie żadnej zmiennej serwerowej IIS_WasUrlRewritten ... Ale próbowałam usunąć X-Original-URL z nagłówków i zmiennych serwera, który powinien również coś zrobić z Urr Rewrite, ale nie usunął tego, który działał z Http Moduł (chociaż jest tam wartość, ale wywołanie metody Remove() nic z nią nie robi). – Piedone

+0

Niestety to nie rozwiązało problemu. –

Powiązane problemy