在使用异步调用来获取模型时,ASP.NET WebAPI和httpClient使用MVC的做法是什么

时间:2017-08-10 16:27:50

标签: asp.net-mvc rest web-services frontend web-frontend

故事:

我已经制作了一个WebAPI来获取各种信息。我被告知,良好的做法是作为前端开发人员,只需通过服务/ API向后端发送信息请求,并使用async和等待关键字等。

这就是我想要做的事情:

在我的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>模型初始化Index页面,但是使用httpClient获取文章,调用WebAPI(这只是对api / ArticleAPI的GET请求,JSON是一个回应)。 这通常是如何在实践中完成的?这是我第一次这样做,我确实需要帮助,并且搜索了一下,发现到目前为止没有任何可以帮助我...

1 个答案:

答案 0 :(得分: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);
    }
}