问题
如果需要在service层获取到网络请求的的某些数据,比如cookie等,该如何实现呢?
前置条件
- 基于
donet 6.0创建的C#Demo - 引入
MediatR.Extensions.Microsoft.DependencyInjection以便支持IMediator操作
// demo.csproj
<ItemGroup>
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="10.0.1" />
</ItemGroup>
方式一:层层传入HttpConext
从Controller层传递HttpConext到Service层
相互之间的调用关系
flowchart LR
A --> |inherted| A2[ControllerBase]
A2 --> |included| A3[HttpContext]
A[Controller] -->|call| B[CommandHander]
B -->|call| C[Service]
B --> |use| B1[entity class or record]
C --> |implemented| D(Service Interface)
Controller继承了ControllerBase, 所以拥有了HttpContext对象- 在这里
Controller通过CommandHander调用Service层的服务
代码部分
// Controller.cs
[ApiController]
public class Controller : ControllerBase
{
private readonly IMediator _mediator;
public Controller(IMediator mediator)
{
_mediator = mediator;
}
[HttpGet("api")]
public async Task<IActionResult> Api()
{
// 这里,将 HttpContext作为参数传入
return Ok(await _mediator.Send(new Command(HttpContext)));
}
}
- Command.cs 文件中,初始化时注入了IService,因此可以调用Service中的服务
- 可以从
Handle方法的参数中获取Command对象,得到Command对象中的context
// Command.cs
public record Command(HttpContext Context) : IRequest<string>;
public class CommandHandler : IRequestHandler<Command, string>
{
private readonly Service _service;
public LoginCommandHandler(IService service)
{
_service = service;
}
public Task<string> Handle(Command request, CancellationToken cancellationToken)
{
// 这里,
_service.doSomeThing(request.context)
...
}
}
IService.cs的定义
// IService.cs
public interface IService
{
string doSomeThing(HttpContext context);
}
Service.cs的实现
//Service.cs
public void doSomeThing(HttpContext context)
{
// 最终的使用的地方
context.Response.Cookies.Append()
...
}
方式二: 使用HttpContextAccessor
直接使用HttpContextAccessor
- 在
Program.cs中增加单例IHttpContextAccessor
// Program.cs
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
- 在
command.cs或者service.cs中直接使用,对请求中的内容做处理
private readonly IHttpContextAccessor _httpContextAccessor;
_httpContextAccessor.HttpContext.DeleteCookie("");