.Net基础系列(一):在Service层获取HttpConext对象的两种方式

142 阅读1分钟

问题

如果需要在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("");