2012-02-27 11 views
5

W zwykłej AccountController w mojej aplikacji MVC3, jeśli ustawiono returnUrl (w moim przypadku ustawię ją ręcznie), zadzwoni ona pod numer Redirect(returnUrl).Przekierowanie (relativeUrl) przekierowanie do niewłaściwej ścieżki w IIS

Załóżmy, że mój URL powrotu to /Admin/HealthCheck (w rzeczywistości tak jest). Podczas debugowania otrzymuję adres URL podobny do http://localhost:3279/Admin/HealthCheck z przekierowania.

Następnie wdrożyłem moją aplikację pod numer http://localhost/Test. W takim przypadku Redirect(returnUrl) przekierowuje mnie do http://localhost/Admin/HealthCheck i , a nie oczekiwanego http://localhost/Test/Admin/HealthCheck.

Co tu się dzieje? Jak mogę to naprawić (jeśli można to naprawić)?

Poniżej znajduje się fragment ze standardowego kontrolera Konto MVC3; możesz zobaczyć, skąd otrzymuję zwrotny adres URL z ciągu zapytania (np. http://localhost/Test/LogOn?ReturnUrl=/Admin/HealthCheck, aczkolwiek URL jest zakodowany).

[HttpPost] 
     public ActionResult LogOn(LogOnModel model, string returnUrl) 
     { 
      if (ModelState.IsValid) 
      { 
       if (Membership.ValidateUser(model.UserName, model.Password)) 
       { 
        returnUrl = Request.Params["ReturnUrl"]; 

        FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); 
        if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") 
         && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) 
        { 
         return Redirect(returnUrl); 
        } 
        else 
        { 
         return RedirectToAction("Index", "Home"); 
        } 
       } 
       else 
       { 
        ModelState.AddModelError("", "The user name or password provided is incorrect."); 
       } 
      } 

Odpowiedz

2

(w moim przypadku, ustawić go ręcznie)

Nie rzeczywiście pokazały, jak to ustawienie ręczne dzieje, ale jeśli ustalony adres url takich jak /Admin/HealthCheck zamiast korzystania pomocnik url do generowania tego adresu URL, takiego jak Url.Action("HealthCheck", "Admin"), nie spodziewaj się cudów.

Twoje zdjęcie LogOn jest w porządku. Robi to, co ma zrobić => przekierowuje do adresu URL, który jest przekazywany jako argument. Twój problem polega na ustawianiu tego adresu URL.

Wniosek: w aplikacji ASP.NET MVC zawsze korzystaj z pomocy adresów URL podczas obsługi adresów URL. Nigdy nie kategoryzuj ich.

+0

Po zalogowaniu, mój przypadek przekierowuje na stronę chronioną. Użytkownik próbuje uzyskać dostęp do chronionej strony, uzyskuje stronę logowania i powinien zostać przekierowany z powrotem. Jak mogę to zrobić? Wygląda na to, że twoim podejściem byłoby przechowywanie nazwy kontrolera, nazwy akcji i innych parametrów i użycie tego w 'Url.Action'. To nie wydaje się właściwe. – ashes999

+1

@ ashes999, jeśli użytkownik próbuje uzyskać dostęp do chronionej strony, wpisuje ten adres strony na pasku adresu, prawda? A kiedy twoja aplikacja jest wdrożona w IIS, wpisuje '/ Test/Admin/HealthCheck' zamiast'/Admin/HealthCheck', czyż nie? Bo gdyby napisał "/ Admin/HealthCheck", dostałby 404 z IIS, prawda? W tym przypadku wszystko działa zgodnie z oczekiwaniami. Nie rozumiem, jaki jest twój problem. –

1

Dla adresu URL Test należy ustawić wartość ReturnUrl na Test/Admin/HealthCheck.

Zanotuj MSDN Reference on Controller.Redirect():

Tworzy RedirectResult obiekt, który przekierowuje do określonego adresu URL.

Innymi słowy, jeśli jako parametr zostanie przypisany "/Admin/HealthCheck", będzie dokładnie tam, gdzie będzie przekierowanie.

+1

To nie ma sensu, ponieważ w IIS root to/Test. Może to tylko ja, ale względne adresy URL powinny być względne względem głównego adresu URL aplikacji. – ashes999

0

Jeśli Twoja domena końcowa ma być www.domain.com/Test/Admin/HealthCheck, możesz chcieć zmienić katalog wirtualny projektu, aby nie zmieniać adresu URL podczas przełączania między localhost a faktycznym serwerem.

Jeśli używasz programu Visual Studio, możesz zmienić ścieżkę wirtualną przypisaną do projektu, klikając projekt w eksploratorze rozwiązań i naciskając klawisz F4. Spowoduje to wyświetlenie okna właściwości projektu, które ma opcję zmiany ścieżki wirtualnej. W twoim przypadku chcesz go zmienić na /Test. Nadal będziesz musiał zmienić adresy URL, aby zawierały kod /Test.

Mimo że Darin wskazał, należy użyć pomocników adresów URL.

+0

Zobacz mój komentarz do jego odpowiedzi. – ashes999

1

Musisz użyć Request.UrlReferrer.AbsoluteUri

[HttpPost] 
    public ActionResult LogOn(LogOnModel model, string returnUrl) 
    { 
     string refUri = Request.UrlReferrer.AbsoluteUri; 

     if (ModelState.IsValid) 
     { 
      if (Membership.ValidateUser(model.UserName, model.Password)) 
      { 
       FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); 
       if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") 
        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) 
       { 
        return Redirect(returnUrl); 
       } 
       else 
       { 
        return Redirect(refUri + "#/account/login"); 
       } 
      } 
      else 
      { 
       ModelState.AddModelError("", "The user name or password provided is incorrect."); 
      } 
     }