2012-02-27 10 views
5

En el AccountController habitual en mi aplicación MVC3, si returnUrl está configurado (en mi caso, lo configuro manualmente), llamará al Redirect(returnUrl).Redirigir (relativeUrl) redireccionando a la ruta incorrecta en IIS

Supongamos que mi URL de retorno es /Admin/HealthCheck (que realmente es). Cuando estoy depurando, obtengo una URL como http://localhost:3279/Admin/HealthCheck de la llamada de redirección.

Luego, implementé mi aplicación en http://localhost/Test. En este caso, Redirect(returnUrl) me redirige a http://localhost/Admin/HealthCheck y no el esperado http://localhost/Test/Admin/HealthCheck.

¿Qué está pasando aquí? ¿Cómo soluciono esto (si es reparable)?

A continuación se muestra un fragmento del MVC3 AccountController (estándar); puede ver dónde obtengo la URL de retorno de la cadena de consulta (por ejemplo, http://localhost/Test/LogOn?ReturnUrl=/Admin/HealthCheck, aunque codificada en URL).

[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."); 
       } 
      } 

Respuesta

2

(en mi caso, ajustarlo manualmente)

No ha mostrado realmente cómo sucede este ajuste manual, pero si usted tiene hardcoded un enlace como /Admin/HealthCheck en lugar de utilizar un url helper para generar esta url como Url.Action("HealthCheck", "Admin") no espera que sucedan milagros.

Su LogOn está bien. Hace lo que se supone que debe hacer => redirige a la url que se pasa como argumento. Su problema radica en la forma en que está configurando esta url.

Conclusión: en una aplicación ASP.NET MVC siempre use los ayudantes de url cuando maneje urls. Nunca los codifique.

+0

Mi caso está redirigiendo a una página protegida después de iniciar sesión. Por lo tanto, el usuario intenta acceder a una página protegida, obtiene la página de inicio de sesión y debe ser redirigido. ¿Cómo puedo hacer eso? Parece que su enfoque sería almacenar el nombre del controlador, el nombre de la acción y otros parámetros, y usarlo en 'Url.Action'. Eso no parece correcto. – ashes999

+1

@ ashes999, si el usuario intenta acceder a una página protegida, escribe esta dirección de página en la barra de direcciones, ¿no es así? Y cuando su aplicación se implementa en IIS, escribe '/ Test/Admin/HealthCheck' en lugar de'/Admin/HealthCheck', ¿no es así? Porque si él escribiera '/ Admin/HealthCheck' hubiera obtenido un 404 de IIS, ¿no? En este caso, todo funciona como se esperaba. No entiendo cuál es tu problema en realidad. –

1

Para su URL Test, debería establecer ReturnUrl para que sea Test/Admin/HealthCheck.

Nota del MSDN Reference on Controller.Redirect():

Crea un objeto RedirectResult que redirige a la URL especificada.

En otras palabras, si pone "/Admin/HealthCheck" como su parámetro, eso es exactamente donde será la redirección.

+1

Eso no tiene sentido, ya que en IIS, la raíz es/Test. Tal vez soy solo yo, pero se supone que las URL relativas son relativas a la URL raíz de la aplicación. – ashes999

0

Si su dominio final va a ser www.domain.com/Test/Admin/HealthCheck es posible que desee cambiar el directorio virtual de su proyecto para que no tenga que realizar cambios en la URL al cambiar entre el servidor local y su servidor real.

Si está utilizando Visual Studio, puede cambiar la ruta virtual asignada a su proyecto haciendo clic en el proyecto en el explorador de soluciones y presionando F4. Esto mostrará la ventana de propiedades del proyecto que tiene una opción para cambiar la ruta virtual. En su caso, le conviene cambiarlo al /Test. Sin embargo, todavía tendrá que cambiar sus direcciones URL para contener el /Test.

Aunque, tal como lo señaló Darin, debería usar los ayudantes de url.

+0

Ver mi comentario a su respuesta. – ashes999

1

Debe usar 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."); 
      } 
     } 
Cuestiones relacionadas