I have the next two methods in a controller from which I generate an API client.
[ApiController]
[Route("users")]
public sealed class UsersController(UsersService usersService) : ControllerBase
{
private readonly UsersService usersService = usersService;
[HttpPost]
[Route("login", Name = "LoginUserAsync")]
[ProducesResponseType(StatusCodes.Status200OK, "text/plain")]
[ProducesResponseType(StatusCodes.Status401Unauthorized, "text/plain")]
public async Task> LoginUserAsync([FromBody, Required] UserLoginDto user, CancellationToken cancellationToken)
{
Result tokenResult = await usersService.GenerateTokenAsync(user, cancellationToken);
if (tokenResult.IsFailed)
{
return Unauthorized(tokenResult.Errors[0].Message);
}
return Ok(tokenResult.Value);
}
[HttpGet]
[Route("{userId:long}/picture", Name = "GetUserPictureAsync")]
[Produces("image/jpeg", "image/png", "application/octet-stream")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task GetUserPictureAsync([Required] long userId, CancellationToken cancellationToken)
{
(byte[] photo, string type) = await usersService.GetUserPictureAsync(userId, cancellationToken);
return File(photo, type);
}
}
I need the first method to be wrapped since I want to handle 403, and the second one to be unwrapped since I always get 200 (for non existing users it returns a default picture).
Here is the options list I use:
Here is json for the methods:
"/users/login": {
"post": {
"tags": [
"Users"
],
"operationId": "LoginUserAsync",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserLoginDto"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/UserLoginDto"
}
},
"application/*+json": {
"schema": {
"$ref": "#/components/schemas/UserLoginDto"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/users/{userId}/picture": {
"get": {
"tags": [
"Users"
],
"operationId": "GetUserPictureAsync",
"parameters": [
{
"name": "userId",
"in": "path",
"required": true,
"schema": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"image/jpeg": { },
"image/png": { },
"application/octet-stream": { }
}
}
}
}
}
NSwag either generates all methods with wrapper (if I delete /WrapResponseMethods:LoginUserAsync, which makes it worse because it won't compile the file methods due to generation errors) or everything with no wrapper at all.
What I already tried:
Changing LoginUserAsync to {generated client class name}.LoginUserAsync
Changing LoginUserAsync to UsersController.LoginUserAsync
There were other changing attempts, if I am not mistaken, but nothing seemed to work
I would greatly appreciate any help.
On a side note, is it possible for NSwag to generate a client for getting a file, wrapped into SwaggerWrapper. For example, what if I want to return 404 or 204 if there are no profile pictures for a user?