I'm making a Core 3.1 web API and using JsonPatch to create a PATCH action. I have an action named Patch which has a JsonPatchDocument parameter. Here is the action's signature:
[HttpPatch("{id}")]
public ActionResult<FileRecordDto> Patch(int id, [FromBody] JsonPatchDocument<FileRecordQueryParams> patchDoc)
As I understand, the parameter needs to receive JSON data in the following structure, which I've successfully tested with the action:
[
{
"op": "operationName",
"path": "/propertyName",
"value": "newPropertyValue"
}
]
However, the action's documentation generated by Swagger has a different structure:
I'm not familiar with this structure and even "value" property is missing from it, which a JsonPatchDocument object has. Every example of patching with the replace operation I've seen has had the first structure.
Why is Swagger generating an alternate structure for a JsonPatchDocument object in the request body for the PATCH endpoint? How do I fix this?
The NuGet package installed for Swagger:
Swashbuckle.AspNetCore doesn't work propertly with this type JsonPatchDocument<UpdateModel>, which doesn’t represent the expected patch request doument.
You need to custome a document filter to modify the generated specification.
public class JsonPatchDocumentFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
var schemas = swaggerDoc.Components.Schemas.ToList();
foreach (var item in schemas)
{
if (item.Key.StartsWith("Operation") || item.Key.StartsWith("JsonPatchDocument"))
swaggerDoc.Components.Schemas.Remove(item.Key);
}
swaggerDoc.Components.Schemas.Add("Operation", new OpenApiSchema
{
Type = "object",
Properties = new Dictionary<string, OpenApiSchema>
{
{"op", new OpenApiSchema{ Type = "string" } },
{"value", new OpenApiSchema{ Type = "string"} },
{"path", new OpenApiSchema{ Type = "string" } }
}
});
swaggerDoc.Components.Schemas.Add("JsonPatchDocument", new OpenApiSchema
{
Type = "array",
Items = new OpenApiSchema
{
Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "Operation" }
},
Description = "Array of operations to perform"
});
foreach (var path in swaggerDoc.Paths.SelectMany(p => p.Value.Operations)
.Where(p => p.Key == Microsoft.OpenApi.Models.OperationType.Patch))
{
foreach (var item in path.Value.RequestBody.Content.Where(c => c.Key != "application/json-patch+json"))
path.Value.RequestBody.Content.Remove(item.Key);
var response = path.Value.RequestBody.Content.Single(c => c.Key == "application/json-patch+json");
response.Value.Schema = new OpenApiSchema
{
Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "JsonPatchDocument" }
};
}
}
}
Register the filter:
services.AddSwaggerGen(c => c.DocumentFilter<JsonPatchDocumentFilter>());
Result:
Related
I have an API project and I need to develop a web project using the API I wrote some code but not able to find the exception and problem and not getting data from the link.
Here is my Service Code:
public async Task<IEnumerable<AgentReadDto>> GetAgent()
{
IEnumerable<AgentReadDto> agents = new List<AgentReadDto>();
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://localhost:44331/api/");
var response = client.GetAsync("Agent/GetAllAgent");
response.Wait();
var result = response.Result;
if (result.IsSuccessStatusCode)
{
var readTask =JsonConvert.DeserializeObject<IList<AgentReadDto>>(await result.Content.ReadAsStringAsync());
agents = readTask;
}
}
return agents;
}
And my controller code is look like this:
public IActionResult AgentLists()
{
var agentsList = _agentRespositoryWeb.GetAgent();
if (agentsList != null )
{
ViewBag.Message = "There was a problem retrieving agent from the database or no agents exists";
}
ViewBag.SuccessMessage = TempData["SuccessMessage"];
return View(agentsList);
}
My api return the value following:
{
"agentDetail": [
{
"usersId": 85,
"firstName": "Amit",
"lastName": "One",
"gender": "Male",
"informationTips": [
{
"video": "https://www.w3schools.com/html/movie.mp4"
},
{
"video": "https://www.w3schools.com/html/movie.mp4"
},
]
},
{
"usersId": 86,
"firstName": "Amit",
"lastName": "Two",
"gender": "Male",
"informationTips": [
{
"video": "https://www.w3schools.com/html/movie.mp4"
}
]
}
]
}
For exception I added image there is three image that take screen on the different steps:
Your model is set to IEnumerable<AgentReadDto>, but you've forgotten to await the call to GetAgent inside of the AgentLists action. This means there's a mismatch between what the view expects (IEnumerable<AgentReadDto>) and what it receives (Task<IEnumerable<AgentReadDto>>).
To fix this, convert AgentLists to an async method and then await the call to GetAgent. Here's a fixed version of the AgentLists action:
public async Task<IActionResult> AgentLists()
{
var agentsList = await _agentRespositoryWeb.GetAgent();
if (agentsList != null)
{
ViewBag.Message =
"There was a problem retrieving agent from the database or no agents exists";
}
ViewBag.SuccessMessage = TempData["SuccessMessage"];
return View(agentsList);
}
It looks like you also have a mismatch between the type you expect to be returned and the JSON actually being returned. The JSON represents an object with a list inside of it, but you're attempting to parse it as a simple list. To fix that, create a wrapper class that matches the structure of the response. For example, create the following class:
public class ApiResponse
{
public IEnumerable<AgentReadDto> AgentDetail { get; set; }
}
Update the deserialization logic to use this new type:
var apiResponse = JsonConvert.DeserializeObject<ApiResponse>(...);
var agentsLit = apiResponse.AgentDetail;
I have an ASP.NET Core 2.2 WebApi and want to upload large files with some additional metadata. The request is a multipart/form-data. Because the files to upload can get quite large, I do not want to read it into memory for processing but rather stream it directly to it's desired destination.
I followed the documentation to disable form value model binding and I also adjusted the maximum request size for the endpoint.
I have tested the endpoint with postman and it works as expected:
However, Swagger obviously does not recognize that there should be parameters for the request. How can I add these parameters to the swagger documentation without defining the parameters in the method's signature?
My endpoint looks like the following example:
[HttpPost]
[DisableFormValueModelBinding]
[DisableRequestSizeLimit]
public async Task<IActionResult> Upload() // "department" and "file" needed in the multipart/form-data
{
// var path = await uploader.UploadAsync(Request);
// return Ok(path);
}
Usually, I would bind the parameters like the following example:
public async Task<IActionResult> Upload([FromForm] string department, [FromForm] IFormFile file)
This works as expected in Swagger but as mentioned above, I do not want to bind the parameters.
For Swashbuckle.AspNetCore version 5 and above some things have changed.
To provide the parameters like Alexander did in his answer, the code would look something like the following:
operation.Parameters.Add(new OpenApiParameter()
{
Name = "department",
Schema = new OpenApiSchema { Type = "string", Format = "string" },
Required = true,
});
operation.Parameters.Add(new OpenApiParameter()
{
Name = "file",
Schema = new OpenApiSchema { Type = "string", Format = "binary" },
Required = true,
});
For some reason however (which I did not investigate further), I was not able to perform an call in the Swagger UI with this approach.
In the end, the following example provided me the result I was looking for:
public class AddUnboundParametersOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var descriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor;
if (descriptor != null && descriptor.ControllerTypeInfo == typeof(RemoteUpdateController) && descriptor.ActionName == nameof(RemoteUpdateController.Upload))
{
var openApiMediaType = new OpenApiMediaType
{
Schema = new OpenApiSchema
{
Type = "object",
Required = new HashSet<string> { "department", "file" }, // make the parameter(s) required if needed
Properties = new Dictionary<string, OpenApiSchema>
{
{ "department" , new OpenApiSchema() { Type = "string", Format = "string" } },
{ "file" , new OpenApiSchema() { Type = "string", Format = "binary" } },
}
}
};
operation.RequestBody = new OpenApiRequestBody
{
Content = new Dictionary<string, OpenApiMediaType>
{
{ "multipart/form-data", openApiMediaType }
}
};
}
}
}
You can use IOperationFilter for this. Add the following class, adjust controller and action names
public class AddUnboundParametersOperationFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<IParameter>();
var descriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor;
if (descriptor != null && descriptor.ControllerTypeInfo == typeof(TestController) && descriptor.ActionName == nameof(TestController.Upload))
{
operation.Parameters.Add(new NonBodyParameter()
{
Name = "department",
Type = "string",
Required = true,
In = "formData",
});
operation.Parameters.Add(new NonBodyParameter()
{
Type = "file",
In = "formData",
Name = "file",
Required = true
});
}
}
}
In Startup.cs
services.AddSwaggerGen(c =>
{
c.OperationFilter<AddUnboundParametersOperationFilter>();
//...
});
I want to use an external API which has Swagger. In Swagger I am calling this url:
PATCH /rest/inventory/item/{id}
with parameters: X-Auth-Token, id and patchOperations which looks like this:
[
{
"op": "replace",
"path": "price",
"value": 6.2
}
]
And when I call this method with those parameters, it works. I get success code 200 and afterwards when I call the GET method I see that the price of the item has been updated to 6.2.
Now I want to do this in C#. I am already calling some GET methods from the same API successfully. This is my code for the PATCH method:
var model = new Dictionary<string, object>
{
{"op", "replace"},
{"path", "price"},
{"value", 6}
};
var blabla = await _httpProvider.PatchAsync($"https://{url}/server/rest/inventory/item/{id}", model, null, null, null, connection.Request.HeaderParameters);
public async Task<HttpResponseModel> PatchAsync<T>(string uri, T data, HttpClientHandler httpClientHandler = null, TimeSpan? timeout = null, string contentTypes = null, Dictionary<string, string> headerParameters = null)
{
using (var client = CreateHttpClient(httpClientHandler, timeout, contentTypes, headerParameters))
{
var requestContent = new StringContent(JsonConvert.SerializeObject(data));
var response = await client.PatchAsync(new Uri(uri), requestContent);
var result = new HttpResponseModel
{
Success = response.IsSuccessStatusCode,
ResponseContent = await response.Content.ReadAsStringAsync(),
ResponseTime = sw.Elapsed
};
return result;
}
}
Where is my mistake? I am getting error StatusCode: 500, ReasonPhrase: 'Server Error', Version: 1.1, Content: System.Net.Http.StreamContent
The mistake is that you're not pasting the same content, not quite anyway.
Your PATCH example is an array of a objects that has 3 properties, in your example there is only 1 element in the array, but it is still an array. Your C# is serialized into single object.
It's subtle but your JSON that you are sending is actually:
{
"op": "replace",
"path": "price",
"value": 6
}
So instead you need to send your dictionary or other object inside an array:
var model = new List<object> {
{
new Dictionary<string, object>
{
{ "op", "replace"},
{"path", "price"},
{"value", 6}
}
};
Ideally, in c# you would create a class to represent this DTO (Data Transfer Object), it can work with anonymous types or with dictionaries (a Dictionary<string,object> serializes into a single JSON object) but the code gets harder to manage over time.
public class DTO
{
public string op { get; set; }
public string path { get; set; }
public object value { get; set; }
}
...
var model = new List<DTO>
{
new DTO {
op = "replace",
path = "price",
value = 6
}
};
With asp.net core 2.1 an ApiController will automatically respond with a 400 BadRequest when validation errors occur.
How can I change/modify the response (json-body) that is sent back to the client? Is there some kind of middleware?
I´m using FluentValidation to validate the parameters sent to my controller, but I am not happy with the response that I am get. It looks like
{
"Url": [
"'Url' must not be empty.",
"'Url' should not be empty."
]
}
I want to change the response, cause we have some default values that we attach to responses. So it should look like
{
"code": 400,
"request_id": "dfdfddf",
"messages": [
"'Url' must not be empty.",
"'Url' should not be empty."
]
}
The ApiBehaviorOptions class allows for the generation of ModelState responses to be customised via its InvalidModelStateResponseFactory property, which is of type Func<ActionContext, IActionResult>.
Here's an example implementation:
apiBehaviorOptions.InvalidModelStateResponseFactory = actionContext => {
return new BadRequestObjectResult(new {
Code = 400,
Request_Id = "dfdfddf",
Messages = actionContext.ModelState.Values.SelectMany(x => x.Errors)
.Select(x => x.ErrorMessage)
});
};
The incoming ActionContext instance provides both ModelState and HttpContext properties for the active request, which contains everything I expect you could need. I'm not sure where your request_id value is coming from, so I've left that as your static example.
To use this implementation, configure the ApiBehaviorOptions instance in ConfigureServices:
serviceCollection.Configure<ApiBehaviorOptions>(apiBehaviorOptions =>
apiBehaviorOptions.InvalidModelStateResponseFactory = ...
);
Consider creating of custom action filer, e.g.:
public class CustomValidationResponseActionFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
var errors = new List<string>();
foreach (var modelState in context.ModelState.Values)
{
foreach (var error in modelState.Errors)
{
errors.Add(error.ErrorMessage);
}
}
var responseObj = new
{
code = 400,
request_id = "dfdfddf",
messages = errors
};
context.Result = new JsonResult(responseObj)
{
StatusCode = 400
};
}
}
public void OnActionExecuted(ActionExecutedContext context)
{ }
}
You can register it in ConfigureServices:
services.AddMvc(options =>
{
options.Filters.Add(new CustomValidationResponseActionFilter());
});
I searched for possible ways to add a request header parameter that would be added automatically to every method in my web-api but i couldn't find a clear one.
While searching i found that the method OperationFilter() has to do something about it.
What the user "G T" wrote is correct but it is not working with Swagger 5. We have some new changes:
From: Operation to: OpenApiOperation
From: IParameter to: OpenApiParameter
From: NonBodyParameter to: OpenApiParameter, and the most important is...
From: Type = "string" to: Schema = new OpenApiSchema { Type = "String" }
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace MyAPI
{
public class AuthorizationHeaderParameterOperationFilter: IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);
if (isAuthorized && !allowAnonymous)
{
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter
{
Name = "Authorization",
In = ParameterLocation.Header,
Description = "access token",
Required = true,
Schema = new OpenApiSchema
{
Type = "string",
Default = new OpenApiString("Bearer ")
}
});
}
}
}
}
And in Startup => ConfigureServices => services.AddSwaggerGen()
c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
Yes you can do it via inheriting from IOperationFilter
You can find the answer on GitHub here: AddRequiredHeaderParameter
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
public class AddRequiredHeaderParameter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<IParameter>();
operation.Parameters.Add(new NonBodyParameter
{
Name = "X-User-Token",
In = "header",
Type = "string",
Required = false
});
}
}
Then you go to your SwaggerConfig.cs file and add the following in the AddSwaggerGen section:
c.OperationFilter<AddRequiredHeaderParameter>();
Rebuild, and enjoy.
Another way to add custom headers is by adding parameters into controller action.
The following example will add x-test parameter to the UI:
[HttpPost]
public IActionResult Test([FromHeader(Name="x-test")][Required] string requiredHeader)
{
return Ok();
}
I have improved the respectful Wille Esteche's answer a bit.
If you want to apply headers not to all methods, but only to your selected controller methods, you can use attributes.
[HttpPost]
[Route(nameof(Auth))]
[SwaggerHeader(Constants.HeaderDomainSid, "Encrypted User.Sid got from client", "abc123", true)]
public ActionResult<string> Auth([FromHeader(Name = Constants.HeaderDomainSid)] string headerDomainSid = null)
{ .....
Attribute class:
public class SwaggerHeaderAttribute : Attribute
{
public string HeaderName { get; }
public string Description { get; }
public string DefaultValue { get; }
public bool IsRequired { get; }
public SwaggerHeaderAttribute(string headerName, string description = null, string defaultValue = null, bool isRequired = false)
{
HeaderName = headerName;
Description = description;
DefaultValue = defaultValue;
IsRequired = isRequired;
}
}
Filter:
public class SwaggerHeaderFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
operation.Parameters ??= new List<OpenApiParameter>();
if (context.MethodInfo.GetCustomAttribute(typeof(SwaggerHeaderAttribute)) is SwaggerHeaderAttribute attribute)
{
var existingParam = operation.Parameters.FirstOrDefault(p =>
p.In == ParameterLocation.Header && p.Name == attribute.HeaderName);
if (existingParam != null) // remove description from [FromHeader] argument attribute
{
operation.Parameters.Remove(existingParam);
}
operation.Parameters.Add(new OpenApiParameter
{
Name = attribute.HeaderName,
In = ParameterLocation.Header,
Description = attribute.Description,
Required = attribute.IsRequired,
Schema = string.IsNullOrEmpty(attribute.DefaultValue)
? null
: new OpenApiSchema
{
Type = "String",
Default = new OpenApiString(attribute.DefaultValue)
}
});
}
}
}
For Asp .Net MVC 5 you can use.
Following the need to be done in Swagger Config file.
private class AddAuthorizationHeaderParameter: IOperationFilter // as a nested class in script config file.
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
if (operation.parameters == null)
operation.parameters = new List<Parameter>();
operation.parameters.Add(new Parameter
{
name = "Authorization",
#in = "header",
type = "string",
required = true
});
}
}
c.OperationFilter<AddAuthorizationHeaderParameter>(); // finally add this line in .EnableSwagger
You can also add any no of headers for header implementation in Swagger.
In my case (.NET 5) I have to change some :
using System.Collections.Generic;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
public class AddRequiredHeaderParameter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter()
{
Name = "userNr",
In = ParameterLocation.Header,
Required = true
});
operation.Parameters.Add(new OpenApiParameter()
{
Name = "periodNo",
In = ParameterLocation.Header,
Required = true
});
}
}
and in Startup.cs --> ConfigureServices --> AddSwaggerGen
add
c.OperationFilter<AddRequiredHeaderParameter>();
If swagger is used in ASP.Net MVC5, and required to add headers to get input from swagger UI.
Create a class inherited from IOperationFilter:
using Swashbuckle.Swagger;
using System.Collections.Generic;
using System.Web.Http.Description;
public class AddHeaderParameters : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
if (operation.parameters == null)
operation.parameters = new List<Parameter>();
operation.parameters.Add(new Parameter
{
name = "AccountUserName",
#in = "header",
type = "string",
required = true,
//description = "Account username"
});
}
}
Give reference of this class in SwaggerConfig.cs inside Configuration.EnableSwagger as:
c.OperationFilter<AddHeaderParameters>();
Important thing to note that the header name supposed to match with the actual header you have created for API.
This works for Swashbucke.AspNetCore 5.6.3
Create a new file and add the code below to the file
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace YourNameSpace
{
public class AuthorizationHeaderParameterOperationFilter:IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Security == null)
operation.Security = new List<OpenApiSecurityRequirement>();
var scheme = new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearer" } };
operation.Security.Add(new OpenApiSecurityRequirement
{
[scheme] = new List<string>()
});
}
}
}
In your Startup.cs add the code below to the ConfigureServices under services.AddSwaggerGen()
c.AddSecurityDefinition("bearer", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
In = ParameterLocation.Header,
Scheme = "bearer"
});
c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
All should work fine now
for more information check here
Also you may have a base model class and use attribute [FromHeader] for properties which should be sent in custom headers. Something like this:
public class AuthenticatedRequest
{
[FromHeader(Name = "User-Identity")]
public string UserIdentity { get; set; }
}
At least it works fine for ASP.NET Core 2.1 and Swashbuckle.AspNetCore 2.5.0.
Another customized implementation for:
Web API (.Net 5)
Swashbuckle.AspNetCore.Swagger (6.2.3)
Swashbuckle.AspNetCore.SwaggerGen (6.2.3)
Swashbuckle.AspNetCore.SwaggerUI (6.2.3)
Following some of the answers from this thread did get me a required field for Authorization. However I had run into a different problems. I need to have the followings fixed:
Display a lock sign beside API actions where authentication is required. For anonymous actions there is no point having a required Authorization field.
For every API endpoi I did not want to input the Authorization key. It becomes a redundant work if we are to test couple of APIs at one go. So I needed a single point where I would put the Auth key and execute the APIs from the Swagger UI. The Swagger UI would handle the Auth part where required.
I did not want to add custom filter or codes in the controller actions where I might have to edit many actions.
Last but not the least, I had a problem where I did get the required Authorization field on the Swagger UI but that was not being post back in request header along the other API fields.
To overcome the above issues I have done the followings:
Create a IOperationFilter type filter to indicate which API endpoints requires authentication and which ones are anonymous type
A button on the Swagger UI to bring a popup to input my Auth token that would be used automatically with the API calls from the Swagger UI
Here are the codes:
#Step-1: The custom IOperationFilter type filrer:
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (context.ApiDescription.ActionDescriptor is ControllerActionDescriptor descriptor)
{
// If [AllowAnonymous] is not applied or [Authorize] or Custom Authorization filter is applied on either the endpoint or the controller
if (!context.ApiDescription.CustomAttributes().Any((a) => a is AllowAnonymousAttribute)
&& (context.ApiDescription.CustomAttributes().Any((a) => a is AuthorizeAttribute)
|| descriptor.ControllerTypeInfo.GetCustomAttribute<AuthorizeAttribute>() != null))
{
if (operation.Security == null)
operation.Security = new List<OpenApiSecurityRequirement>();
operation.Security.Add(
new OpenApiSecurityRequirement{
{
new OpenApiSecurityScheme
{
Name = "Authorization",
In = ParameterLocation.Header,
BearerFormat = "Bearer token",
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[]{ }
}
});
}
}
}
Then in the startup.cs file, within the ConfigureServices method add the filter like this:
services.AddSwaggerGen(options =>
{
...
options.OperationFilter<AddRequiredHeaderParameter>();
...
...
}
Doing the above will add an icon to the API endpoints where Authentication is required. Here is the result:
#Step-2: Then we need the Auth token input UI. Add the following code right after the line in the startup.cs where you have added the IOperationFilter filter:
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Name = "Authorization",
Type = SecuritySchemeType.Http,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "JWT Authorization header. \r\n\r\n Enter the token in the text input below.,
});
This will get you a Authorize button at the top of the API descriptor page. Clicking the button will bring a popup window where you can input the Auth token and have it passed down with each API call.
Not sure if it was answered with the 2021 Sep release for .net 5.0 but I took Rami'es answer and adapted it to the following:
namespace PartnerLicense
{
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using Walter.Web.FireWall.Reseller;
public class AddRequiredHeaderParameter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
operation.Parameters.Add(new()
{
Description = "Add your reseller ID here",
Name = HeaderKeys.ResellerId,
In = ParameterLocation.Header,
Required = true
});
}
}
}