2013-05-23 9 views
8

Ho un controller AddressBook che restituirà un elenco di "cartelle" (in pratica gruppi/posizioni). Questo può essere chiamato tramite una richiesta AJAX o all'interno di una stessa pagina MVC al momento del rendering.Come creare un ActionController per funzionare sia in fase di esecuzione che con ajax

Come posso creare una funzione che funzioni bene per entrambi gli scenari? Ecco il mio attuale azione di controllo, che mi sembra di lottare con l'utilizzo all'interno della mia pagina MVC

public ActionResult GetFolderList(int? parent) 
{ 
    List<String> folderList = new List<String>(); 
    folderList.Add("East Midlands"); 
    folderList.Add("West Midlands"); 
    folderList.Add("South West"); 
    folderList.Add("North East"); 
    folderList.Add("North West"); 

    return Json(folderList); 
} 

all'interno della pagina (atm non funzionante)

@{ 
    var controller = new My.Controllers.AddressBookController(); 
    var what = controller.GetFolderList(0); 

    foreach(var p in what){ 
     //i want to get the list items here 
    } 
} 

risposta

9

Proprio avere una funzione che restituisce List, quindi chiamarlo in entrambi i metodi di caricamento della pagina e di richiesta AJAX.

Qualcosa di simile:

public List<string> GetFolderList() 
{ 
    List<String> folderList = new List<String>(); 
    folderList.Add("East Midlands"); 
    folderList.Add("West Midlands"); 
    folderList.Add("South West"); 
    folderList.Add("North East"); 
    folderList.Add("North West"); 

    return folderList; 
} 

Poi, il caricamento della pagina, si può attaccare che nel modello:

public ActionResult Index() 
{ 
    var model = new YourViewModel(); //whatever type the model is 

    model.FolderList = GetFolderList(); //have a List<string> called FolderList on your model 

    return View(model); //send model to your view 
} 

Poi a suo avviso si può fare:

@model YourViewModel 

@{ 
    foreach(var item in Model.FolderList){ 
     //do whatever you want 
    } 
} 

Poi , supponendo che la tua richiesta di ajax fosse qualcosa del tipo:

$.ajax({ 
    url: '@Url.Action("GetFolders", "ControllerName")', 
    type: 'POST', 
    datatype: 'json', 
    success: function (result) { 
     for (var i = 0; i < result.length; i++) 
     { 
      //do whatever with result[i] 
     } 
    } 
}); 

tuo metodo di azione GetFolders sarebbe simile:

public ActionResult GetFolders() 
{ 
    return Json(GetFolderList()); 
} 
+0

non dimenticare di decorare il tuo metodo di azione con l'attributo '[HttpPost]' mentre stai effettuando una chiamata POST dal client. – Shyju

+0

@Shyju Non decorarlo con alcun mezzo che accetterà tutti i verbi :) – mattytommo

+1

Perché dovresti POST ottenere un metodo che dovrebbe essere chiaramente un GET? (ha persino il nome di Get in it!) – Joshua

5

Ciò funzionerà:

public ActionResult GetFolderList(int? parent) 
{ 
    List<String> folderList = new List<String>(); 
    folderList.Add("East Midlands"); 
    folderList.Add("West Midlands"); 
    folderList.Add("South West"); 
    folderList.Add("North East"); 
    folderList.Add("North West"); 

    if(Request.IsAjaxRequest()) 
    { 
     return Json(folderList); 
    } 

    return View("someView", folderList); 

} 
2

Prima di tutto, non si dovrebbe mai fare qualcosa di simile a suo avviso:

var controller = new My.Controllers.AddressBookController(); 
var what = controller.GetFolderList(0); 

Questo crea stretto accoppiamento tra la vista e il controller, che viola molto i principi di MVC. Ora, per rispondere alle tue domande.

Come accennato in Mattytomo, ti consigliamo di utilizzare una vista fortemente tipizzata e ottenere il tuo elenco dal modello di visualizzazioni. Qualcosa come il sotto funzionerebbe per il caso semplice. Se questo punto di vista diventa più complesso allora si avrà bisogno di un vero e proprio oggetto vista del modello:

@model List<string> 

@{ 
    foreach (var p in Model) 
    { 
     p; 
    } 
} 

Ora, è possibile utilizzare un metodo di controllo per AJAX o una richiesta normale insieme con l'utilizzo Request.IsAjaxRequest come Maris ha sottolineato. Assumendo che il punto di vista è chiamato "ListaCartelle", l'azione di controllo sarebbe simile a questa:

public ActionResult GetFolderList(int? parent) 
    { 
     List<String> folderList = new List<String>(); 
     folderList.Add("East Midlands"); 
     folderList.Add("West Midlands"); 
     folderList.Add("South West"); 
     folderList.Add("North East"); 
     folderList.Add("North West"); 

     if (Request.IsAjaxRequest()) 
     { 
      return Json(folderList); 
     } 

     return View("FolderList", folderList); 
    } 

Ora, quando si chiama questo metodo tramite la tecnologia AJAX tornerà la rappresentazione JSON del ListaCartelle, l'altro saggio restituirà la visualizzazione ListaCartelle .

0

Una volta ho scritto un ActionFilter che fa proprio questo, sostituisce il ActionResult con JsonResult una volta l'intestazione Accept http contiene json (e si potrebbe limitare ai soli richieste Ajax, passando onAjaxOnly con true):

public class ReturnJsonIfAcceptedAttribute : ActionFilterAttribute 
{ 
    private bool _onAjaxOnly; 
    private bool _allowJsonOnGet; 

    public ReturnJsonIfAcceptedAttribute(bool onAjaxOnly = true, bool allowJsonOnGet = false) 
    { 
     _onAjaxOnly = onAjaxOnly; 
     _allowJsonOnGet = allowJsonOnGet; 
    } 

    public override void OnResultExecuting(ResultExecutingContext filterContext) 
    { 
     var request = filterContext.HttpContext.Request; 

     if (!_allowJsonOnGet && request.HttpMethod.ToUpper() == "GET") 
      return; 

     var isAjax = !_onAjaxOnly || request.IsAjaxRequest(); 

     if (isAjax && request.AcceptTypes.Contains("json", StringComparer.OrdinalIgnoreCase)) 
     { 
      var viewResult = filterContext.Result as ViewResult; 

      if (viewResult == null) 
       return; 

      var jsonResult = new JsonResult(); 
      jsonResult.Data = viewResult.Model; 

      filterContext.Result = jsonResult; 
     } 
    } 

Allora mantenete il vostro Action così com'è, basta aggiungere la nuova ReturnJsonIfAcceptedAttribute:

[ReturnJsonIfAccepted] 
public ActionResult Index() 
{ 
    var model = new Model(); // whatever 
    return View(model); 
} 
Problemi correlati