2015-04-17 25 views
9

Ho un controller WebAPI nella mia soluzione di progetto MVC5. Il WebAPI ha un metodo che restituisce tutti i file in una cartella specifica in una lista JSON:Chiamare l'API Web dal controller MVC

[{"name":"file1.zip", "path":"c:\\"}, {...}]

Dal mio HomeController voglio chiamare questo metodo, convertire la risposta JSON per List<QDocument> e restituire questo elenco a un Vista del rasoio. Questo elenco potrebbe essere vuoto: [] se non ci sono file nella cartella.

Questa è l'APIController:

public class DocumentsController : ApiController 
{ 
    #region Methods 
    /// <summary> 
    /// Get all files in the repository as Json. 
    /// </summary> 
    /// <returns>Json representation of QDocumentRecord.</returns> 
    public HttpResponseMessage GetAllRecords() 
    { 
     // All code to find the files are here and is working perfectly... 

     return new HttpResponseMessage() 
     { 
      Content = new StringContent(JsonConvert.SerializeObject(listOfFiles), Encoding.UTF8, "application/json") 
     }; 
    }    
} 

Ecco il mio HomeController:

public class HomeController : Controller 
{ 
    public Index() 
    { 
     // I want to call APi GetAllFiles and put the result to variable: 
     var files = JsonConvert.DeserializeObject<List<QDocumentRecord>>(API return Json); 
     } 
} 

Infine questo è il modello in caso di necessità:

public class QDocumentRecord 
{ 
     public string id {get; set;} 
     public string path {get; set;} 
    ..... 
} 

Così come posso fare questa chiamata?

+1

Perché non si chiamano come qualsiasi altro metodo? Aggiungi riferimento, avvia e chiama il metodo ... – Kaf

+1

Solo un colpo d'occhio sull'utilizzo di JsonConvert nel tuo ApiController ... Fare questo automaticamente è una delle caratteristiche di punta WebAPI, – spender

risposta

7

Dal mio HomeController voglio chiamare questo metodo e convertire la risposta Json alla lista

No, non è così. Non si vuole davvero aggiungere l'overhead di una chiamata HTTP e la (de) serializzazione quando il codice è a portata di mano. È anche nella stessa assemblea!

L'ApiController va comunque contro (my preferred) convention.Lascia che restituisce un tipo concreto:

public IEnumerable<QDocumentRecord> GetAllRecords() 
{ 
    listOfFiles = ... 
    return listOfFiles; 
} 

Se non si desidera che e siete assolutamente sicuri è necessario restituire HttpResponseMessage, allora ancora non c'è assolutamente alcun need to bother with calling JsonConvert.SerializeObject() yourself:

return Request.CreateResponse<List<QDocumentRecord>>(HttpStatusCode.OK, listOfFiles); 

nuovo Poi, non si vuole la logica di business in un controllore, in modo da estrarre che in una classe che fa il lavoro per voi:

public class FileListGetter 
{ 
    public IEnumerable<QDocumentRecord> GetAllRecords() 
    { 
     listOfFiles = ... 
     return listOfFiles; 
    } 
} 

in entrambi i casi, allora si può chiamare questa classe o la ApiController direttamente dal vostro controller MVC:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var listOfFiles = new DocumentsController().GetAllRecords(); 
     // OR 
     var listOfFiles = new FileListGetter().GetAllRecords(); 

     return View(listOfFiles); 
    } 
} 

Ma se davvero, davvero necessario fare una richiesta HTTP, è possibile utilizzare HttpWebRequest, WebClient, HttpClient o RestSharp, per ognuno dei quali esiste un sacco di tutorial.

5

Perché non spostare semplicemente il codice che si ha nelle chiamate ApiController - DocumentsController in una classe che è possibile chiamare dal proprio HomeController e DocumentController. Tiralo fuori in una classe che chiami da entrambi i controller. Questa roba nella tua domanda:

// Tutto il codice per trovare i file sono qui e sta funzionando perfettamente ...

Non ha senso chiamare un controller di API da un altro controller sullo stesso sito web.

Questo sarà anche semplificare il codice quando si torna ad esso in futuro si avrà una classe comune per trovare i file e di fare che la logica ci ...

+0

"Non ha senso chiamare un controller API da un altro controller sullo stesso sito "+1 – spender

+0

Devo progettare l'API in questo modo. l'API è stata utilizzata da altre app mobili. e voglio mandare i risultati come una lista di Razor view per fare il filtraggio e ... –

+0

spostare la logica interna in cui si genera l'elenco dei file in una classe comune non dovrebbe influire sull'interfaccia del controller reale utilizzata dalle app mobili. Per loro ciò che accade nel controller è una scatola nera. Basta tirare la logica comune per trovare i file in una classe comune utilizzata da entrambi .. – kmcnamee

5

È molto tardi, ma ha pensato di condividere sotto il codice. Se abbiamo il nostro WebAPI come un progetto completamente diverso nella stessa soluzione, allora possiamo chiamare lo stesso dal regolatore MVC come qui di seguito

public class ProductsController : Controller 
    { 
     // GET: Products 
     public async Task<ActionResult> Index() 
     { 
      string apiUrl = "http://localhost:58764/api/values"; 

      using (HttpClient client=new HttpClient()) 
      { 
       client.BaseAddress = new Uri(apiUrl); 
       client.DefaultRequestHeaders.Accept.Clear(); 
       client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); 

       HttpResponseMessage response = await client.GetAsync(apiUrl); 
       if (response.IsSuccessStatusCode) 
       { 
        var data = await response.Content.ReadAsStringAsync(); 
        var table = Newtonsoft.Json.JsonConvert.DeserializeObject<System.Data.DataTable>(data); 

       } 


      } 
      return View(); 

     } 
    } 
Problemi correlati