2010-07-31 30 views
7

Sto utilizzando il modello post-redirect-get per tutti i miei moduli, ma ora è necessario aggiungere funzionalità AJAX per migliorare l'esperienza dell'utente. I miei pensieri iniziali sono che i due non si mescolano.Il modello PRG non è compatibile con i moduli AJAX?

Nello scenario PRG, avrei la mia azione post che poi reindirizzerà nuovamente alla mia azione di get se c'è un errore di convalida, o reindirizzare al mio successo agire diversamente.

Nello scenario AJAX, ho bisogno di restituire una vista parziale in entrambi i casi. Più tipicamente, vorrei verificare per prima cosa se fosse una richiesta AJAX. In tal caso, restituire la vista parziale, altrimenti restituire la vista.

Qualche idea o suggerimento?

risposta

4

Utilizziamo Post-Redirect-Get nella nostra app. Ecco l'essenza di ciò che facciamo, che gira attorno al metodo Request.IsAjaxRequest() e divide le tue viste in .aspx ciascuna delle quali ospita un .ascx in modo che ciascuna azione possa essere chiamata sia in modo sincrono che asincrono (cioè via Ajax).

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(Foo foo) 
{ 
    try 
    { 
     // Save the changes to the data store 
     unitOfWork.Foos.Attach(foo); 
     unitOfWork.Commit(); 

     if (Request.IsAjaxRequest()) 
     { 
      // The name of the view for Ajax calls will most likely be different to the normal view name 
      return PartialView("EditSuccessAsync"); 
     } 
     else 
     { 
      return RedirectToAction("EditSuccess"); 
     } 
    } 
    catch (Exception e) 
    { 
     if (Request.IsAjaxRequest()) 
     { 
      // Here you probably want to return part of the normal Edit View 
      return PartialView("EditForm", foo); 
     } 
     else 
     { 
      return View(foo); 
     } 
    } 
} 

Abbiamo una leggera variante di questo e dove abbiamo specificamente cattura RulesException 's (dal xVal al fine di trattare gli errori di convalida del modello in modo diverso per le altre 'eccezioni più gravi'.

catch (RulesException re) 
{ 
    re.AddModelStateErrors(ModelState, ""); 

    return View(foo); 
} 

A dire il vero, a volte mi viene un vago sospetto che potremmo commettere un errore leggermente sbagliato

+0

È possibile Estrarre la logica if ajax ... in un metodo AjaxView in una classe base per rimuovere la confusione. Il problema principale del tuo approccio è che stai restituendo una vista dall'azione POST in modo che non sia PRG nel caso di un errore di convalida. Ho reindirizzato all'azione GET originale, utilizzando un'esportazione e un'importazione di ModelState. Il problema principale è che FireFox non conserva il flag ajax tra i reindirizzamenti, quindi nella mia azione GET, IsAjaxRequest è false. Attualmente devo aggirare questo problema con un altro filtro di azione che conserva il flag in tempdata. Tuttavia non è molto elegante. –

3

Bene, parte del motivo per PRG è evitare "Vuoi inviare nuovamente il modulo?" dialogo. In genere AJAX non ha questo problema, dal momento che non si è veramente fare un 'POST' (si sono, ma si cattura la mia deriva).

In ogni caso, Rails supporta ciò che si vorrebbe fare, e non penso che sarebbe così difficile da tradurre in ASP.NET MVC.

In primo luogo, è possibile comunicare al client il codice JavaScript per inviare AJAX come text/javascript. Utilizzo di jQuery:

jQuery.ajaxSetup({ 
    'beforeSend': function(xhr) { xhr.setRequestHeader("Accept", "text/javascript"); } 
}); 

Mettilo da qualche parte prima che venga eseguito AJAX. Ciò influenzerà tutte le altre chiamate AJAX, ma non dovrebbe fare nulla di imprevisto a meno che non lo si stia cercando nel back-end.

Quindi, nel controller, cercare l'intestazione text/javascript e rispondere di conseguenza. Dai un'occhiata a questo SO question, che fa riferimento a this article. Vorrei poter dare maggiori informazioni, ma non ho VS a portata di mano per provarlo in questo momento.

+2

Un buon punto sullo scopo del PRG di evitare invii duplicati, che non ha importanza con AJAX – Acyra