2009-06-03 7 views
5

Tengo algunos métodos de acción detrás de una Autorizar como:Más control en ASP.Net MVC's Authorize; para mantener AJAX solicita AJAXy

[AcceptVerbs(HttpVerbs.Post), Authorize] 
public ActionResult Create(int siteId, Comment comment) { 

El problema que tengo es que estoy enviando una solicitud a través de AJAX en comentar/Crear con

X-Requested-With=XMLHttpRequest 

que ayuda a identificar la solicitud como AJAX. Cuando el usuario no está conectado y golpea la pared Autorizar que se le redirecciona a

/Account/LogOn?ReturnUrl=Comment%2fCreate 

que se rompe el flujo de trabajo AJAX. Necesito ser redirigido a

/Account/LogOn?X-Requested-With=XMLHttpRequest 

Alguna idea de cómo eso se puede conseguir? ¿Alguna forma de obtener más control sobre lo que sucede cuando se solicita la autorización?

Respuesta

5

Gracias a los comentarios de Lewis que era capaz de llegar a esta solución (que está lejos de ser perfecto, enviados con mis propias observaciones, si tiene las correcciones no dude en editar y eliminar esta frase), pero funciona:

public class AjaxAuthorizeAttribute : AuthorizeAttribute { 
    override public void OnAuthorization(AuthorizationContext filterContext) { 
     base.OnAuthorization(filterContext); 
     // Only do something if we are about to give a HttpUnauthorizedResult and we are in AJAX mode. 
     if (filterContext.Result is HttpUnauthorizedResult && filterContext.HttpContext.Request.IsAjaxRequest()) { 
      // TODO: fix the URL building: 
      // 1- Use some class to build URLs just in case LoginUrl actually has some query already. 
      // 2- When leaving Result as a HttpUnauthorizedResult, ASP.Net actually does some nice automatic stuff, like adding a ReturnURL, when hardcodding the URL here, that is lost. 
      String url = System.Web.Security.FormsAuthentication.LoginUrl + "?X-Requested-With=XMLHttpRequest"; 
      filterContext.Result = new RedirectResult(url); 
     } 
    } 
} 
+0

Gran ejemplo. Pero cómo probar base.OnAuthorization (filterContext); ¿invocación? – Ofigenn

+0

otro enfoque para este problema es descrito por [Kevin Craft] (http://craftycodeblog.com/2010/05/15/asp-net-mvc-ajax-redirect/) – Towa

1

En lugar de utilizar el atributo authorize, he estado haciendo algo como lo siguiente.

public ActionResult SomeCall(string someData) 
{ 
    if (Request.IsAjaxRequest() == false) 
    { 
     // TODO: do the intended thing. 
    } 
    else 
    { 
     // This should only work with AJAX requests, so redirect 
     // the user to an appropriate location. 
     return RedirectToAction("Action", "Controller", new { id = ?? }); 
    } 
} 
+0

Ya obtuve esa parte. Mi problema es que ese método tiene un Autorizar enfrente y la redirección del Autorizador pierde la capacidad de ser revisado por AJAX como lo hizo. – Pablo

0

Creo que la forma correcta de manejar esto sería en su Javascript que hace la llamada AJAX.

Si el usuario necesita ser autorizado (o autenticado como lo implica su código) y no lo es, debe informarles y tal vez no les permita intentarlo y comentarlo en primer lugar.

Sin embargo, si eso no se ajusta a sus necesidades. Podría intentar escribir su propio filtro de acción autorizar, quizás heredando el que viene con el marco MVC pero redirige cómo quiere. Es bastante sencillo.

+0

Quiero que traten de comentar y participar en el sitio, y solo solicitar el inicio de sesión cuando sea necesario. No hay forma de que en el código JavaScript pueda saber si el usuario está conectado sin hacer una llamada AJAX para verificarlo primero y luego intentar realizar esa función. Me gustó tu idea de hacer otro filtro de acción, pero después de jugar con eso un poco no parece controlar a dónde se redirige al usuario. ¿Sabes con certeza que sí? ¿Alguna otra pista? – Pablo

+0

Malo, ahora lo he encontrado. Gracias por el puntero en la dirección correcta Lewis. – Pablo

3

Recientemente me encontré con exactamente el mismo problema y usé el código publicado por J. Pablo Fernández con una modificación para tener en cuenta las URL de devolución. Aquí está:

public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute 
{ 
    override public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     base.OnAuthorization(filterContext); 
     // Only do something if we are about to give a HttpUnauthorizedResult and we are in AJAX mode. 
     if (filterContext.Result is HttpUnauthorizedResult && filterContext.HttpContext.Request.IsAjaxRequest()) 
     { 
      // TODO: fix the URL building: 
      // 1- Use some class to build URLs just in case LoginUrl actually has some query already. 
      HttpRequestBase request = filterContext.HttpContext.Request; 
      string returnUrl = request.Path; 
      bool queryStringPresent = request.QueryString.Count > 0; 
      if (queryStringPresent || request.Form.Count > 0) 
       returnUrl += '?' + request.QueryString.ToString(); 
      if (queryStringPresent) 
       returnUrl += '&'; 
      returnUrl += request.Form; 
      String url = System.Web.Security.FormsAuthentication.LoginUrl + 
         "?X-Requested-With=XMLHttpRequest&ReturnUrl=" + 
         HttpUtility.UrlEncode(returnUrl); 
      filterContext.Result = new RedirectResult(url); 
     } 
    } 
} 
Cuestiones relacionadas