2010-09-06 16 views
5

I tienen una acción de controlador que hace una vista parcial:ASP.NET MVC representación vista parcial con jQuery ajax

public ActionResult Details(int id) 
{ 
    DetailsViewModel model = 
     ModelBuilder.GetDetailsViewModel(id, _repository); 
    return PartialView("Details", model); 
} 

y estoy de cargar el contenido devuelto en un elemento dinámico de la siguiente manera:

$container = appendContainer(); // adds a div to the dom with the correct id 
$container.load("MyController/Details", function(response, status, xhr) { 
    if (status != "success") { 
     $(container).html('an error has occured'); 
    } 
}); 

por lo que esto crea un div y luego carga el contenido devuelto en ese div.

Quiero modificar esto ligeramente para que el contenedor div solo se cree si la llamada al controlador es exitosa.

Así:

  1. jQuery llama a la acción del controlador del controlador
  2. vuelve PartialView, o null si no encontrado Id
  3. Si se devuelve PartialView, se crea y se carga con el contenido devuelto el contenedor.
  4. Si el controlador no encuentra el Id, no se crea contenido y se muestra una alerta.

Agradecería cualquier sugerencia sobre cómo podría lograr esto.

Respuesta

11

Todo es load devuelve HTML de un servidor, entonces ¿por qué no solo anexar a un div temporal y luego obtener el HTML del mismo en caso de éxito?

var $dummy = $("<div>"); 
$dummy.load("MyController/Details", function(response, status, xhr) { 
    var $container = appendContainer(); 
    if (status != "success") { 
     $container.html('an error has occured'); 
    } 
    else 
    { 
     $container.html($dummy.html()); 
    } 
    $dummy.remove(); 
}); 

ACTUALIZACIÓN:

Si usted está esperando una excepción, entonces debería manejarlo. Si básicamente permites que se produzca el error solo para obtener status != "success", entonces ese es un olor a código grave. Debería detectar el error y devolver un PartialView diferente.

public ActionResult Details(int id) 
{ 
    try 
    { 
     DetailsViewModel model = 
      ModelBuilder.GetDetailsViewModel(id, _repository); 
     return PartialView("Details", model); 
    } 
    catch (SomeException ex) 
    { 
     return PartialView("Error", ex.Message); 
    } 
} 

A continuación, tiene la garantía de obtener siempre una respuesta HTML válido y si no lo hace, entonces su error básico an error occured entrará en juego.

+0

Mis reservas con esto es que estoy usando esencialmente una excepción no capturada en mi opinión para el fin para devolver un no/encontrado estado nulo a la interfaz de usuario. Prefiero devolver un nulo de mi controlador si no se encuentra el elemento, pero no pude ver una manera de hacer que este enfoque funcione con eso. Solo me parece un poco olor a código. – fearofawhackplanet

+0

@fearofawhackplanet - Actualicé mi respuesta. – GenericTypeTea

11

en su caso, lo usaría $ .ajax en lugar de .load() le da más control sobre el flujo + siente más limpia

$.ajax({ 
url: "MyController/Details", 
    type: "GET", 
    success: function (response, status, xhr) 
    { 
     var jqContainer = appendContainer(); 
     jqContainer.html(response); 
    }, 
    error:function(XMLHttpRequest, textStatus, errorThrown) 
    { 
    //show the error somewhere - but this is a bad solution 
    } 
}); 

sobre el estado de error - yo también odio depender de excepciones - fea e ineficiente, tiene varias maneras de manejar esto:

  1. retorno solamente JSON desde su punto de vista y se unen los datos devueltos utilizando algún tipo de solución de plantillas, de esta manera se puede devolver un objeto de error con un mensaje de error específico y manejar todo errar ors de la misma manera (creo que esta es la mejor solución).
  2. devuelve un código de estado de éxito 204 -no respuesta que es como devolver nulo de tu acción- luego verifica el código de estado y aparece el mensaje de error.
  3. un código de estado 278 éxito (no es un código de estado real, pero es el recuento de éxito y le permite también enviar datos) - aquí se envía un objeto JSON con el mensaje de error que tou puede analizar y sembrar un mensaje de error agradable (sierra esta solución 278 aquí en SO hace algún tiempo).
  4. devolver un punto de vista diferente para el error - pero entonces hay que insertarlo en el envase o un recipiente simulado para comprobar si hay un error si se quiere tomar más acciones.

en mi código i utilizar $ (document) .ajaxSend (..) globalmente todas las respuestas Ajax para el 278 de código y mostrar los mensajes de error si hay alguna, o llamar a la función original de éxito enganchado.

Para regresar el error de la acción i utilizar el siguiente resultado

public class AjaxErrorWithDetailsResult : JsonResult 
    { 
    public object ErrorResult { get; set; } 

    public AjaxErrorWithDetailsResult(object errorResult) 
    { 
     this.ErrorResult = errorResult; 
    } 


    public override void ExecuteResult(ControllerContext context) 
    { 
     if (context == null) 
     { 
      throw new ArgumentNullException("context"); 
     } 
     this.Data = ErrorResult; 
     context.HttpContext.Response.StatusCode = 278; 
     base.ExecuteResult(context); 
    } 
} 

donde ErrorResult puede haber un objeto anónimo o un objeto que implementar una interfaz con una propiedad de ErrorMessage para que sepa lo que debe buscar en las JS

+1

¡Estoy de acuerdo contigo! Los $ ajax tienen más control sobre el flujo. –

Cuestiones relacionadas