2017-08-10 77 views
1

故事:什麼是ASP.NET的WebAPI的HttpClient和使用MVC中的實踐使用異步調用時獲得型號

我已經做了的WebAPI獲得各種信息。我被告知,最好的做法是作爲前端開發人員,通過服務/ API向後端發送信息請求,並使用異步並等待關鍵字等。

這就是我想做的事:

在我的HomeController我有這樣的:

namespace NHibernateMVC.Controllers 
{ 
    public class HomeController : Controller 
    { 
     static HttpClient client = new HttpClient(); 

     static async Task RunAsync() 
     { 
      // New code: 
      client.BaseAddress = new Uri("http://localhost:64498/"); 
      client.DefaultRequestHeaders.Accept.Clear(); 
      client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 
     } 

     static async Task<IEnumerable<Article>> GetArticleAsync(string path) 
     { 
      IEnumerable<Article> art = null; 
      HttpResponseMessage response = await client.GetAsync(path); 
      if (response.IsSuccessStatusCode) 
      { 
       art = await response.Content.ReadAsAsync<IEnumerable<Article>>(); 
      } 
      return art; 
     } 

     public ActionResult Index() 
     { 
      // This is where I am supposed to make a call to get the Articles to return a View who's model is of type IEnumerable<Article> 
     } 

的底線是,我想用一個IEnumerable<Article>模型來初始化索引頁,但得到的使用httpClient的文章,調用WebAPI(這只是對api/ArticleAPI的GET請求,JSON是響應)。 這在實踐中通常如何完成?這是我第一次這樣做,我確實需要幫助,並且搜索了一下,發現了什麼可以幫助我到目前爲止...

+2

爲什麼您的MVC代碼調用運行在同一主機上的WebAPI代碼?這會增加不必要的開銷,除非您希望API在不同的主機上運行。然後,您應該讓客戶端代碼直接調用API,而不是僅僅作爲代理。 – CodeCaster

回答

1

控制器需要重構一點點,以便它可以被調用正確

public class HomeController : Controller { 
    const string ARTICLE_API_PATH = "api/ArticleAPI"; 
    static HttpClient client; = new HttpClient(); 
    static HomeController() { 
     // New code: 
     client.BaseAddress = new Uri("http://localhost:64498/"); 
     client.DefaultRequestHeaders.Accept.Clear(); 
     client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 
    } 

    async Task<IEnumerable<Article>> GetArticleAsync() { 
     IEnumerable<Article> articles = new List<Article>(); 
     HttpResponseMessage response = await client.GetAsync(ARTICLE_API_PATH); 
     if (response.IsSuccessStatusCode) { 
      articles = await response.Content.ReadAsAsync<List<Article>>(); 
     } 
     return articles; 
    } 

    public async Task<ActionResult> Index() { 
     //call service method above. 
     var articles = await GetArticleAsync(); 
     //pass the list as the model to the view 
     return View(articles); 
    } 
} 

上述工作作爲一個開始,但也可以提高可維護性。

獲得的物品可以提取到一個服務抽象

public interface IArticleService { 
    Task<IEnumerable<Article>> GetArticleAsync(); 
} 

public class ArticleService : IArticleService { 
    const string ARTICLE_API_PATH = "api/ArticleAPI"; 
    static HttpClient client; = new HttpClient(); 

    static ArticleService() { 
     client.BaseAddress = new Uri("http://localhost:64498/"); 
     client.DefaultRequestHeaders.Accept.Clear(); 
     client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 
    } 

    public async Task<IEnumerable<Article>> GetArticleAsync() { 
     IEnumerable<Article> articles = new List<Article>(); 
     HttpResponseMessage response = await client.GetAsync(ARTICLE_API_PATH); 
     if (response.IsSuccessStatusCode) { 
      articles = await response.Content.ReadAsAsync<List<Article>>(); 
     } 
     return articles; 
    } 
} 

以至於現在控制器可以簡化爲

public class HomeController : Controller { 
    private readonly IArticleService articleService; 

    public HomeController() { 
     articleService = new ArticleService(); 
    } 

    public async Task<ActionResult> Index() { 
     //call service method above. 
     var articles = await articleService.GetArticleAsync(); 
     //pass the list as the model to the view 
     return View(articles); 
    } 
} 

在更高級的情況下,您可以顛倒服務的創建通過將其注入到控制器中,但該主題不在此問題的範圍之內。

它看起來像這樣。

public class HomeController : Controller { 
    private readonly IArticleService articleService; 

    public HomeController(IArticleService articleService) { 
     this.articleService = articleService; 
    } 

    public async Task<ActionResult> Index() { 
     //call service method above. 
     var articles = await articleService.GetArticleAsync(); 
     //pass the list as the model to the view 
     return View(articles); 
    } 
} 
相關問題