admin管理员组文章数量:1302328
I use Fastendpoints in an ASP.NET Core 9 Web API project.
The endpoint uses dependency injection for several services, in the example a logger.
In another service, I want to make a call to this endpoint. I would prefer it to call the endpoint directly and not using an HttpClient
for it.
For this to happen, I either have to
- use DI in my service for every service that gets injected into the endpoint - which seems unreasonable
- register every endpoint manually in the setup via
builder.Services.AddScoped<MyEndpoint>()
- then some internals of the endpoint are null (HttpContext
member) - use the
FastEndpoints.Factory.Create<>()
also requires every service to be explicitly instantiated
public class MyWorkerService
{
public async Task HandleInit()
{
// how to call the endpoint?
await (new GetTestEndpoint()).HandleAsync(new EmptyRequest(), CancellationToken.None);
var response = GetTestEndpoint.Response;
}
}
public abstract class GetTestEndpoint : Endpoint<EmptyRequest, TestResponse>
{
protected readonly SomeService _someService;
protected readonly ILogger _logger;
protected GetTestEndpoint(SomeService someService, ILogger logger)
{
_someService = someService;
_logger = logger;
}
public override void Configure()
{
Get("api/" + RoutePattern);
AllowAnonymous();
}
public override async Task HandleAsync(EmptyRequest emptyRequest, CancellationToken ct)
{
await SendAsync(new TestResponse());
}
}
So how do I make internal calls to the fast-endpoint route (with the request class and getting back a response object?)
I use Fastendpoints in an ASP.NET Core 9 Web API project.
The endpoint uses dependency injection for several services, in the example a logger.
In another service, I want to make a call to this endpoint. I would prefer it to call the endpoint directly and not using an HttpClient
for it.
For this to happen, I either have to
- use DI in my service for every service that gets injected into the endpoint - which seems unreasonable
- register every endpoint manually in the setup via
builder.Services.AddScoped<MyEndpoint>()
- then some internals of the endpoint are null (HttpContext
member) - use the
FastEndpoints.Factory.Create<>()
also requires every service to be explicitly instantiated
public class MyWorkerService
{
public async Task HandleInit()
{
// how to call the endpoint?
await (new GetTestEndpoint()).HandleAsync(new EmptyRequest(), CancellationToken.None);
var response = GetTestEndpoint.Response;
}
}
public abstract class GetTestEndpoint : Endpoint<EmptyRequest, TestResponse>
{
protected readonly SomeService _someService;
protected readonly ILogger _logger;
protected GetTestEndpoint(SomeService someService, ILogger logger)
{
_someService = someService;
_logger = logger;
}
public override void Configure()
{
Get("api/" + RoutePattern);
AllowAnonymous();
}
public override async Task HandleAsync(EmptyRequest emptyRequest, CancellationToken ct)
{
await SendAsync(new TestResponse());
}
}
So how do I make internal calls to the fast-endpoint route (with the request class and getting back a response object?)
Share edited Feb 10 at 17:03 marc_s 755k184 gold badges1.4k silver badges1.5k bronze badges asked Feb 10 at 14:23 nonsensationnonsensation 3031 silver badge6 bronze badges 3- 2 You shouldn't need to call a method on your endpoint, as those methods should be as slim as possible and only concern themselves with HTTP Specifics. Instead you should (and easily can) call the same service your endpoint is calling and operate on the return value of it directly. – MindSwipe Commented Feb 10 at 14:30
- 2 Endpoints are a gateway for the outside world; if you have code that needs to be used multiple times, make it a function so both endpoints can call it. – SoftwareDveloper Commented Feb 10 at 19:38
- as others have mentioned, don't do it. calling endpoints from other endpoints is one of the easiest ways to create a big ball of mud, unmaintainable tangled mess. if a piece of logic needs to be called from multiple places, abstract it out into a service class and inject it via DI container to the consumers. or use the FE command bus to encapsulate that logic into a command+handler combo. – Dĵ ΝιΓΞΗΛψΚ Commented Feb 15 at 6:06
1 Answer
Reset to default 0You can access the service endpoint via the IServiceProvider
and user the GetRequiredService
method.
Refer to the following sample:
Add the request and response class:
public class MyRequest { public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } } public class MyResponse { public string FullName { get; set; } public bool IsOver18 { get; set; } }
Add an internal service (your SomeService) and use it in Fastendpoint,
public interface IInternalServices { string SayHello(string name); } public class InternalServices : IInternalServices { public string SayHello(string name) { return $"Hello {name}!"; } }
Add my Fastendpoint:
public class MyEndpoint : Endpoint<MyRequest, MyResponse> { private readonly IServiceProvider _serviceProvider; protected readonly ILogger<MyEndpoint> _logger; public MyEndpoint(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; _logger = _serviceProvider.GetRequiredService<ILogger<MyEndpoint>>(); ; } public override void Configure() { Post("/api/user/create"); AllowAnonymous(); } public override async Task HandleAsync(MyRequest req, CancellationToken ct) { var _internalService = _serviceProvider.GetRequiredService<IInternalServices>(); _logger.LogInformation(_internalService.SayHello(req.FirstName + " " + req.LastName)); await SendAsync(new() { FullName = req.FirstName + " " + req.LastName, IsOver18 = req.Age > 18 }, StatusCodes.Status200OK, ct); } public async Task<MyResponse> HandleInternalAsync(MyRequest req, CancellationToken ct) { var _internalService = _serviceProvider.GetRequiredService<IInternalServices>(); _logger.LogInformation(_internalService.SayHello(req.FirstName + " " + req.LastName)); var response = new MyResponse() { FullName = req.FirstName + " " + req.LastName, IsOver18 = req.Age > 18 }; return await Task.FromResult(response); } }
Add a worker service, which will access the Fastendpoint and call the internal method:
public class MyWorkerService { private readonly IServiceProvider _serviceProvider; public MyWorkerService(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public async Task<MyResponse> HandleInit() { // how to call the endpoint? using var scope = _serviceProvider.CreateScope(); var endpoint = scope.ServiceProvider.GetRequiredService<MyEndpoint>(); var request = (new MyRequest() { FirstName="Marlon", LastName="Brando", Age=49 }); var response = await endpoint.HandleInternalAsync(request, CancellationToken.None); return response; } }
Register these services in the Progarm.cs file:
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddFastEndpoints(); builder.Services.AddScoped<IInternalServices,InternalServices>(); builder.Services.AddScoped<MyWorkerService>(); builder.Services.AddSingleton<ILogger<MyEndpoint>, Logger<MyEndpoint>>(); builder.Services.AddScoped<MyEndpoint>(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseFastEndpoints(); app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
Add an API controller to inject the worker service and call the HandleInit method.
[Route("api/[controller]")] [ApiController] public class TodoController : ControllerBase { private readonly MyWorkerService _myworkservice; public TodoController(MyWorkerService myWorkerService) { _myworkservice=myWorkerService; } // GET: api/<TodoController> [HttpGet] public IActionResult Get() { var response = _myworkservice.HandleInit(); return Ok(response); }
After running the application, the result as below:
Fastendpoint result:
Todo controllers result as below:
And in the console window the logger also works well:
本文标签: cInternal call to FastEndpoints endpointrouteStack Overflow
版权声明:本文标题:c# - Internal call to FastEndpoints endpointroute - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741711850a2393890.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论