当使用异步调用获取模型时,MVC 中与 ASP.NET WebAPI 和 httpClient 一起使用的做法是什么
What is the practice in MVC used with ASP.NET WebAPI and httpClient when using async calls to get the Model
故事:
我做了一个WebAPI来获取各种信息。我被告知好的做法是作为前端开发人员,只需通过 services/API 向后端发送信息请求并使用 async 和 await 关键字等。
这就是我想要做的:
在我的 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 是响应)。
这在实践中通常是如何完成的?这是我第一次这样做,我确实需要帮助,搜索了一下,到目前为止没有找到任何可以帮助我的东西...
controller需要稍微重构一下才能正常调用
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);
}
}
故事:
我做了一个WebAPI来获取各种信息。我被告知好的做法是作为前端开发人员,只需通过 services/API 向后端发送信息请求并使用 async 和 await 关键字等。
这就是我想要做的:
在我的 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 是响应)。
这在实践中通常是如何完成的?这是我第一次这样做,我确实需要帮助,搜索了一下,到目前为止没有找到任何可以帮助我的东西...
controller需要稍微重构一下才能正常调用
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);
}
}