在构建现代Web应用程序时,异步通信是一个重要的概念,特别是在处理长时间运行的任务或分布式系统(如微服务架构)时。本文将介绍如何使用ASP.NET CoreWeb API实现异步通信,包括创建项目、配置服务、添加控制器、定义模型以及讨论异步通信的实现方式和使用场景。
首先,需要创建一个ASP.NET CoreWeb API项目。在项目中,需要配置服务和中间件以支持MVC。以下是配置服务和中间件的示例代码:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMvcWithDefaultRoute();
}
}
在这段代码中,通过调用services.AddMvc();
来添加MVC服务,并通过app.UseMvcWithDefaultRoute();
来配置默认路由。
接下来,需要添加一个控制器来处理异步请求。以下是控制器的示例代码:
[Route("api/rentals")]
public class RentalsController : BaseController
{
[HttpPost("request-rental", Name = "RequestRental")]
public IActionResult RequestRental([FromBody]RequestRentalInputModel inputModel)
{
return AcceptedAtRoute("CheckStatus", new { queueNo = "q-2" });
}
[HttpGet("check-status/{queueNo}", Name = "CheckStatus")]
public IActionResult CheckStatus(string queueNo)
{
if (queueNo == "q-2")
return Ok(new CheckStatusOutputModel { Status = "Pending" });
else
return SeeOther("GetRental", new { refNo = "r-1" });
}
[HttpGet("get-rental/{refNo}", Name = "GetRental")]
public IActionResult GetRental(string refNo)
{
if (refNo == "r-1")
return Ok(new GetRentalOutputModel { DeliveryEstimate = DateTime.Now.AddDays(2) });
else
return NotFound();
}
}
在这个控制器中,定义了三个动作:RequestRental
用于接收租赁请求,CheckStatus
用于检查请求状态,GetRental
用于获取租赁结果。
为了通过API发送和接收数据,需要定义一些模型。以下是模型的示例代码:
public class RequestRentalInputModel
{
public string Customer { get; set; }
public string Movie { get; set; }
public int Days { get; set; }
}
public class CheckStatusOutputModel
{
public string Status { get; set; }
}
public class GetRentalOutputModel
{
public DateTime DeliveryEstimate { get; set; }
}
这些模型分别用于表示租赁请求、状态检查和租赁结果。
异步通信可以通过同步(RPC)或异步(消息传递)的方式进行。对于异步通信,客户端将:
在服务器端,API将有一个POST端点来接受请求。它通常会将请求消息存储在队列中以供后续处理。这个端点返回202(已接受)状态码以及用于检查请求状态的Location头:
[HttpPost("request-rental", Name = "RequestRental")]
public IActionResult RequestRental([FromBody]RequestRentalInputModel inputModel)
{
return AcceptedAtRoute("CheckStatus", new { queueNo = "q-2" });
}
API将有一个GET端点来检查状态。这个端点将发送200(OK)状态码和状态详情,或者对于已完成的请求发送303(See Other)状态码:
[HttpGet("check-status/{queueNo}", Name = "CheckStatus")]
public IActionResult CheckStatus(string queueNo)
{
if (queueNo == "q-2")
return Ok(new CheckStatusOutputModel { Status = "Pending" });
else
return SeeOther("GetRental", new { refNo = "r-1" });
}
注意,303(See Other)没有在基控制器中内置的方法,但是很容易创建自己的方法:
[NonAction]
protected IActionResult SeeOther(string routeName, object values)
{
var location = Url.Link(routeName, values);
HttpContext.Response.GetTypedHeaders().Location = new System.Uri(location);
return StatusCode(StatusCodes.Status303SeeOther);
}
API将有一个GET端点来获取结果。这个端点将发送200(OK)状态码,对于已完成的请求,或者404(未找到)状态码,对于未完成的请求:
[HttpGet("get-rental/{refNo}", Name = "GetRental")]
public IActionResult GetRental(string refNo)
{
if (refNo == "r-1")
return Ok(new GetRentalOutputModel { DeliveryEstimate = DateTime.Now.AddDays(2) });
else
return NotFound();
}
异步基于消息的通信非常适合长时间运行的过程和分布式系统(例如微服务)。客户端和服务器通常有以下责任: