Helloo everybody. Tell me please. Can I generate a Sample Request in Swagger depending on the model, so as not to write it manually. To see which fields the model has.
Is it even possible?
Because now I have to manually write a description of the request for each api.
I would like to automate this process.
I am using Swashbuckle and ASP.NET Core
There is a place for code examples, you should add /// <example>123</example> on the model instead of the remarks.
Is this close to what you need:
http://swagger-net-test.azurewebsites.net/swagger/ui/index?filter=Company#/Company/Company_Post
The code for that is here:
https://github.com/heldersepu/Swagger-Net-Test/blob/c9b554fde26367418c84fcd3682d308ae1b40d11/Swagger_Test/Models/Company.cs
You can also make dynamic changes with an IDocumentFilter like this:
private class AddExampleDocumentFilter : IDocumentFilter
{
private List<Guid> Guids
{
get
{
return new List<Guid>
{
Guid.Empty, Guid.Empty
};
}
}
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry s, IApiExplorer a)
{
if (swaggerDoc.paths.ContainsKey("/api/Dictionary"))
{
var del = swaggerDoc.paths["/api/Dictionary"].delete;
if (del != null)
{
del.parameters[0].schema.example = Guids;
}
}
}
}
Here is the result of that:
http://swagger-net-test.azurewebsites.net/swagger/ui/index?filter=Dictionary#/Dictionary/Dictionary_DeleteEcho
And once the user executes it with the sample data the UI shows the curl request:
Related
I got an Asp.Net web api project with some controllers, enabled swagger doc with swagger-Net. I have been searching for how to enable vendor extensions or custom swagger doc fields which I can set for each API level. I'm successful at settting vendor extension at swagger doc level/swaggerDoc.Info level. But I can't go further to set them at API level. Any help would be extremely grateful!
I tried adding vendor extensions to swaggerDoc.Info and it works great. But I don't know how to add vendor extension to API level (PathItem) which can be set or ediited for individual APIs. Basically I want to enable setting of a vendor extension x-dev at API level.
[HttpGet]
[x-dev("Myself")]
public async Task<User> GetAllUsers(){
.....................
}
Okay, I found a way.
Suppose I want to add a vendor extension "Squad" to each operation,
first create an Attribute which will be used whenever we want to attribute a particular squad to an operation.
public class SquadAttribute : Attribute
{
public string squadName;
public SquadAttribute(string squadName)
{
this.squadName = squadName;
}
}
then in SwaggerConfig.cs add operation filter which will add our attribute as a vendor extension to operations.
public class SquadOperationFilter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var sq = apiDescription.GetControllerAndActionAttributes<SquadAttribute>().FirstOrDefault();
if (sq != null)
{
operation.vendorExtensions.Add("x-SquadName", sq.squadName);
}
}
}
finally in swagger.config, Apply operationfilter.
c.OperationFilter<SquadOperationFilter>();
Now you can add squad attribute for any openApi operation like this :
[HttpGet]
["Settings"]
[Squad("DevSquad")]
public async Task GetAllSettings()
{
...............................
...............................
}
I have swagger set up but it shows all the controllers for everyone. I'd like to only show controllers based on API key permissions, so they'll have to enter their API key in the Explore section of swagger to see anything. Is this do-able?
If we talk about Swashbuckle package then we need to use implement IDocumentFilter.
Some initial information you can review from this post.
Basic scenario:
Define custom Attribute
Setup this attribute to Controllers / Actions
Implement filtration logic in your DocumentFilter class
Code sample available here:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class LicenseValidatorAttribute : Attribute
{
public FeatureType Feature { get; set; }
}
public class FeatureDocumentFilter : IDocumentFilter
{
private readonly IFeatureService _featureService;
public FeatureDocumentFilter(IFeatureService featureService)
{
_featureService = featureService;
}
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
foreach (var api in context.ApiDescriptions)
{
var attribute = api.CustomAttributes().OfType<FeatureValidatorAttribute>().FirstOrDefault();
if (attribute != null)
{
var success = _featureService.ValidateFeature(attribute.Feature);
if (!success.Valid)
{
var route = "/" + api.RelativePath;
swaggerDoc.Paths.Remove(route);
}
}
}
}
}
I am new the API in general, let me give you the background of the API and what I want it to do.
I have a API have that are external facing and so every incoming request are required to check the signature from header. literality my code in every controller call are checking the signature and created many duplicated code.
my question is how can reduces those duplicated code ? do I use Custom Attributes, or AuthorizeAttribute
here are some of the example code:
[Route("[controller]")]
[ApiController]
public class ExampleController : ControllerBase
{
public async Task<Result> Call_1(Rquest request)
{
string signaturel;
signature = Util.getHeaderSignature(request);
if(unit.IsSinatureValid(signaturel, someVar1, someVar2))
{
(My logic)
}
else{ return "InvalidSinaturemessage" }
}
public async Task<Result> Call_2(Rquest request)
{
string signaturel;
signature = Util.getHeaderSignature(request);
if(unit.IsSinatureValid(signaturel, someVar1, someVar2))
{
(My logic)
}
else{ return "InvalidSinaturemessage" }
}
}
above code is just for showing, the actual Sinature checking logic is around 20 lines of code on every single controller method.
Yes, you can do that using action filters. It's described in documentation
Put your code for checking into OnActionExecuting method. So, you can write Result in the action filter if the signature isn't valid.
In case you need specific result structure you can create your own ObjectResult:
public class ForbiddenObjectResult : ObjectResult
{
public string Message { get; private set; }
public ForbiddenObjectResult(object value, string message)
: base(value)
{
StatusCode = StatusCodes.Status403Forbidden;
Message = message;
}
}
...
string signaturel;
signature = Util.getHeaderSignature(context.HttpContext.Request);
if(!unit.IsSinatureValid(signaturel, someVar1, someVar2))
{
context.Result = new ForbiddenObjectResult(filterContext.ModelState, "InvalidSinaturemessage");
}
And to register it for all your endpoints(if needed):
services.AddControllersWithViews(options =>
{
options.Filters.Add<YourActionFilter>();
});
You can use token based authentication or filter method. For reference
Token based authentication
Custom Filter
I am working with a web api where it should have a request key and depending upon it, the api controller will do
specific task. I am using rest client program in vs code and did the following for testing:
GET http://localhost:PortNo/WeatherForecast/GetAllTeams
test: "12345678910" //Key
So in the controller, I did this to get the key value:
[HttpGet]
public async Task<ActionResult<IEnumerable<TeamDetails>>> GetAllTeams()
{
string Token = Request.Headers["test"]; //Getting the key value here
var teams = _service.GetAllTeams();
return Ok(teams)
}
But I've few things in mind and doing R & D like how can I make the above with an attribute. Say each controller
will have an attribute as follows and make the request invalid if no proper key found:
[InvalidToken] //This is the attribute
[HttpGet]
public async Task<ActionResult<IEnumerable<TeamDetails>>> GetAllTeams()
{
var teams = _service.GetAllTeams();
return Ok(teams)
}
I am not sure if this is going to make the api secure and my plan is to valid every http request (In my case, a simple form submission at the moment), so it should say the request is generated from the web api app.
N.B: I worked with web api earlier in small sections but now a broader thing to implement, so expecting few suggestions that can help me to guide for better design.
try it:
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
..
public class InvalidToken : Attribute, IActionFilter
{
public InvalidToken( )
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
var Authorization = context.HttpContext.Request.Headers["test"];
if ( Authorization != "12345678910")
{
context.ModelState.AddModelError("Authorization", "Authorization failed!");
return;
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
// "OnActionExecuted"
}
}
Startup.cs
services.AddScoped<InvalidToken>();
// add filter to whole api
services.AddControllers(options =>
{
options.Filters.Add<InvalidToken>();
});
I'm using Swashbuckle to generate docs for an API. My controller methods looks like this:
[ResponseType(typeof(CategoryCollectionModel))]
public HttpResponseMessage Get(HttpRequestMessage request, [FromUri]Paging paging)
{
var input = new CategoriesListQuery.Input { Page = paging.Page, Size = paging.Size };
var result = this.queryInvoker.Execute<CategoriesListQuery.Input, CategoriesListQuery.Result>(input);
var items = Mapper.Map<CategoryCollectionModel>(result);
return request.CreateResponse(HttpStatusCode.OK, items);
}
Swashbuckle treats HttpRequestMessage as a parameter in the generated docs. Is there a way to configure Swashbuckle to ignore HttpRequestMessage since it is only included in the signature for testing purposes?
Please refer to the discussion here. In short do not pass in HttpRequestMessage as in input parameter, rather mock the {controller}.Request property.
I found a solution from "http://www.morganskinner.com/2016/02/ignoring-parameters-in-swashbuckle.html"
Summary :
In Swashbuckle you can plug-in operation “filters” that can be used to
alter the emitted data – the filter is passed the context of the
operation being emitted, and you can monkey around with the data that
pops out. All I had to do then was create a filter that would look for
this datatype, and remove the corresponding data from the results. I
ended up with this…
public class IgnoreHttpRequestMessageOperationFilter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry,
ApiDescription apiDescription)
{
apiDescription.ParameterDescriptions
.Where(desc => desc.ParameterDescriptor.ParameterType
== typeof(HttpRequestMessage))
.ToList()
.ForEach(param =>
{
var toRemove = operation.parameters
.SingleOrDefault(p => p.name == param.Name);
if (null != toRemove)
operation.parameters.Remove(toRemove);
});
}
}
With that class in place, I just needed to plug this in to the swagger
config file as follows...
c.OperationFilter<IgnoreHttpRequestMessageOperationFilter>();
Working for me. thanks "Morgan"