Pregunta

quiero evitar tener un montón de if Request.IsAjaxRequest() en mis controladores. Estaba pensando que si pudiera condensar esta lógica a un ActionFilter sería fácil de adoptar una convención en mi solicitud para proporcionar una segunda acción para cualquier solicitud que pueden utiliza Ajax, al tiempo que proporciona una caída de vuelta si JavaScript está deshabilitada.

public ActionResult Details(int id)
{
  // called normally, show full page
}

public ActionResult Details_Ajax(int id)
{
  // called through ajax, return a partial view
}

Al principio pensé que podía hacer algo como esto:

public class AjaxRenameAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RouteData.Values["action"] = filterContext.RouteData.Values["action"] + "_Ajax";

    }

Pero eso no funcionará porque la acción de invocar se decide y luego se procesan los filtros sobre ella.

No realmente quiero devolver un RedirectResult cada vez que alguien llama a una acción, parece un poco inútil para duplicar la cantidad de peticiones HTTP.

¿Hay una manera diferente de ruta a través de la solicitud a una acción diferente? O es lo que estoy haciendo desaconsejable y que debería buscar una mejor forma de hacer las cosas?

Saludos

¿Fue útil?

Solución

AcceptAjaxAttribute es, probablemente, es lo que se necesita aquí; Sin embargo, me gustaría proponer una manera diferente de pensar sobre este problema.

No todas las peticiones Ajax son iguales. Una petición Ajax podría estar tratando de lograr alguna de las siguientes cosas:

  • Encuadernación datos JSON a una red rica (como jqGrid);
  • Parsing / transformación de los datos XML, como una alimentación de RSS;
  • Cargando HTML parcial en un área de la página;
  • asincrónica alguna secuencia de comandos (google.load puede hacer esto);
  • La manipulación de un mensaje unidireccional desde el cliente;
  • Y, probablemente, un poco más que yo estoy olvidando.

Cuando se "selecciona" una "acción alternativa" específica basada únicamente en el método IsAjaxRequest, usted está atando algo muy genérico - una solicitud asincrónica - a una funcionalidad específica en el servidor. Es en última instancia va a hacer su diseño más frágil y también hacer más difícil su controlador de probar la unidad (aunque hay maneras de hacerlo, puede burlarse del contexto).

Un buen diseño acción debería ser consistentes , sólo se debe cuidar lo de la solicitud era para no ¿Cómo se hizo la solicitud. Uno podría apuntar a otros atributos como AuthorizeAttribute como excepciones, pero me gustaría hacer una distinción para los filtros, que la mayor parte del tiempo describen el comportamiento que tiene que ocurrir ya sea un "antes" o "después" de la acción tiene lugar, no "en lugar de. "

Para llegar al punto aquí, el objetivo declarado en la pregunta es buena; usted debe definitivamente tienen diferentes métodos para lo que se ha descrito correctamente como diferentes acciones:

public ActionResult Details(int id)
{
    return View("Details", GetDetails(id));
}

public ActionResult JsonDetails(int id)
{
    return Json(GetDetails(id));
}

public ActionResult PartialDetails(int id)
{
    return PartialView("DetailTable", GetDetails(id));
}

Y así sucesivamente. Sin embargo, utilizando un selector de acción Ajax que elegir entre estos métodos está siguiendo la práctica de "degradación elegante" , que esencialmente ha sido sustituida (al menos OMI) por mejora progresiva .

Esta es la razón, aunque me encanta ASP.NET MVC, que en su mayoría evito la AjaxHelper, porque yo no encuentro que expresa este concepto que bien; se trata de ocultar demasiado de ti. En lugar de tener el concepto de un "Formulario de Ajax" o una "Acción Ajax", vamos a acabar con la distinción y se adhieren a HTML puro, a continuación, inyectar la funcionalidad Ajax separado una vez que estamos seguros de que el cliente puede manejar .

Este es un ejemplo de jQuery - aunque se puede hacer esto en MS AJAX también:

$(function() {
    $("#showdetails").click(function() {
        $("#details").load("PartialDetails", { id: <%= Record.ID %> });
        return false;
    }
});

Esto es todo lo que necesita para inyectar Ajax en una página MVC. Comience con un enlace HTML simple y llano y anular con una llamada Ajax que va a una acción de un controlador diferente .

Ahora bien, si en algún otro lugar en su sitio usted decide que quiere utilizar una rejilla en su lugar, pero no quieren romper las páginas utilizando la representación parcial, se puede escribir algo como esto (digamos que usted tiene un solo maestro- página de detalles con una lista de "órdenes" en el lado izquierdo y una tabla de detalles a la derecha):

$(".detaillink").click(function() {
    $('#detailGrid').setGridParam({
        url: $(this).attr("href").replace(/\/order\/details/i,
            "/order/jsondetails")
    }); 
    $("#detailGrid").trigger("reloadGrid");  
});

Este enfoque permite separar por completo el comportamiento del cliente del comportamiento del servidor. El servidor está diciendo efectivamente al cliente: Si quieres la versión JSON, piden para la versión JSON, y oh, por cierto, aquí hay un script para convertir sus enlaces si sabes cómo para ejecutarlo. no hay selectores de acción y artimañas con las sobrecargas del método, sin burlarse de lo que tiene que hacer con el fin de realizar una prueba especial simple, no hay confusión sobre qué acción y cuándo. Sólo un par de líneas de JavaScript. Las acciones del controlador son cortos y dulce, exactamente de la manera que debería ser.

Este no es el único enfoque. Obviamente, existen clases como AcceptAjaxAttribute porque esperaban algunos desarrolladores a utilizar el método de la petición de detección. Pero después de haber experimentado un poco con las dos, me parece esta manera más fácil razonar acerca y por lo tanto más fácil de diseñar / código correctamente.

Otros consejos

¿Qué hay de AcceptAjaxAttribute en MvcFutures?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top