2015-04-17 11 views
9

Posiadam kontroler WebAPI w ramach mojego rozwiązania projektowego MVC5. WebAPI ma metodę, która zwraca wszystkie pliki w określonym folderze jako listę Json:Wywołanie interfejsu API WWW z kontrolera MVC

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

Z mojego HomeController Chcę wywołać tej metody, konwersja odpowiedź JSON do List<QDocument> i powrót listę Widok brzytwy. Ta lista może być pusta: [], jeśli w folderze nie ma plików.

To 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") 
     }; 
    }    
} 

Oto moja 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); 
     } 
} 

W końcu jest to model w przypadku trzeba go:

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

więc jak mogę wykonać to połączenie?

+1

Dlaczego nie nazwać jak każdej innej metody? Dodaj odwołanie, zainicjuj i wywołaj metodę ... – Kaf

+1

Wystarczy jedno kliknięcie, aby użyć JsonConvert w swoim ApiControllerze ... Wykonanie tego automatycznie jest jedną z flagowych funkcji WebAPI, – spender

Odpowiedz

7

Z mojego HomeController chcę zadzwonić ta metoda i przekonwertuj odpowiedź Json na listę:

Nie, ty nie. Naprawdę nie chcesz dodawać narzutów wywołania HTTP i (de) serializacji, gdy kod jest w zasięgu. Nawet w tym samym zespole!

W każdym razie Twój ApiController jest niezgodny z (my preferred) convention.Niech zwróci rodzaj betonu:

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

Jeśli nie chcesz, i jesteś absolutnie pewien, że trzeba powrócić HttpResponseMessage, to nadal nie ma absolutnie żadnego need to bother with calling JsonConvert.SerializeObject() yourself:

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

Potem znowu, nie chcesz logikę biznesową w kontrolerze, więc można wyodrębnić, że do klasy, która wykonuje pracę dla Ciebie:

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

tak czy inaczej, to można nazwać tę klasę lub temu ApiController bezpośrednio z kontrolera MVC:

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

     return View(listOfFiles); 
    } 
} 

Ale jeśli naprawdę musi zrobić żądania HTTP, można użyć HttpWebRequest, WebClient, HttpClient lub RestSharp dla wszystkich, których mnóstwo tutoriali istnieje.

5

Po prostu przenieś kod, który masz w wywołaniach ApiController - DocumentsController, do klasy, do której możesz zadzwonić zarówno z HomeController, jak i DocumentController. Wyciągnij to do klasy, do której dzwonisz z obu kontrolerów. Te rzeczy w swoim pytaniu:

// Wszystko kod, aby znaleźć pliki są tutaj i działa doskonale ...

To nie ma sensu, aby zadzwonić do API kontroler z innym kontrolerem na tej samej stronie internetowej.

Będzie to również uproszczenie kodu, gdy wrócisz do niego w przyszłości będzie mieć jedną wspólną klasę do znalezienia pliki i tam robi, że logika ...

+0

"Nie ma sensu wywoływać kontrolera API z innego kontroler na tej samej stronie "+1 – spender

+0

Muszę zaprojektować API w ten sposób. API jest używane przez inne aplikacje mobilne. i chciałbym wysłać wyniki w postaci listy do widoku Razor, aby wykonać filtrowanie i ... –

+0

Przeniesienie wewnętrznej logiki, w której generowana jest lista plików do wspólnej klasy, nie powinno mieć wpływu na rzeczywisty interfejs kontrolera używany przez aplikacje mobilne. Dla nich to, co dzieje się w kontrolerze, to czarna skrzynka. Wystarczy przeciągnąć wspólną logikę, aby znaleźć pliki do wspólnej klasy używanej przez oba .. – kmcnamee

5

Jest to bardzo późno, ale myśli o udostępnieniu poniżej kodu. Jeśli mamy WebAPI jako zupełnie innego projektu w tym samym roztworze wtedy możemy nazwać tego samego od kontrolera MVC jak poniżej

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(); 

     } 
    } 
Powiązane problemy