I was refactoring my endpoints in a Minimal WebApi project and faced this situation:
namespace DACRL.API.Endpoints;
public class ApiUserManagementEndpoints : IEndpoints
{
private const string ContentType = "application/json";
private const string Tag = "ApiAccounts";
private const string BaseRoute = "apiAccounts";
public static void DefineEndpoints(IEndpointRouteBuilder app)
{
app.MapPost($"{BaseRoute}/login", LoginAsync)
.WithName("LoginApiUser")
.Accepts<ApiUserModel>(ContentType)
.Produces<string>()
.Produces<ApiAuthResponse>()
.Produces((int)HttpStatusCode.NotFound)
.Produces((int)HttpStatusCode.BadRequest)
.WithTags(Tag);
}
#region Helpers
private static async Task<IResult> LoginAsync(ApiUserModel model, string ipAddress, IApiUserService userService, IOptions<Jwt> jwtConfigRaw, CancellationToken ct)
{
...
return Results.Ok(result);
}
private static string GenerateToken(Jwt jwtConfig, string username)
{
// Token stuff
}
#endregion
public static void AddServices(IServiceCollection services, IConfiguration configuration) =>
services.AddTransient<IApiUserService, ApiUserService>();
}
Now, LoginAsync
needs a parameter value for ipAddress
. How do I pass HttpContext.Connection.RemoteIpAddress.ToString()
from my app.MapPost
?
CodePudding user response:
You can inject HttpContext
and use it:
private static async Task<IResult> LoginAsync(ApiUserModel model,
HttpContext ctx, // here
IApiUserService userService,
IOptions<Jwt> jwtConfigRaw,
CancellationToken ct)
{
var ip = ctx.Connection.RemoteIpAddress;
//...
}
See the special types subsection of Minimal APIs parameter minding docs:
Special types
The following types are bound without explicit attributes:
HttpContext
: The context which holds all the information about the current HTTP request or response.HttpRequest
andHttpResponse
: The HTTP request and HTTP response.CancellationToken
: The cancellation token associated with the current HTTP request.ClaimsPrincipal
: The user associated with the request, bound fromHttpContext.User
.
CodePudding user response:
After a bit of head scratching, I realized exposing the ipAddress parameter made swagger think I had to supply that myself. Here is what I did:
private static async Task<IResult> LoginAsync(ApiUserModel model, IHttpContextAccessor httpContextAccessor, IApiUserService userService, IOptions<Jwt> jwtConfigRaw, CancellationToken ct)
{
...
var ipAddress = httpContextAccessor.HttpContext?.Connection.RemoteIpAddress?.ToString();
...
}
So injecting the IHttpContextAccessor
solved this for me.