Home > Software design >  Passing parameter from MapPost to local function
Passing parameter from MapPost to local function

Time:07-26

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 and HttpResponse: The HTTP request and HTTP response.
  • CancellationToken: The cancellation token associated with the current HTTP request.
  • ClaimsPrincipal: The user associated with the request, bound from HttpContext.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.

  • Related