I need to know if it's possible to set up custom operationid, or a naming convention, I mean I know that operation filter can be overwritten the way how operationId is generated
using Swashbuckle.Swagger;
using System.Web.Http.Description;
namespace Something
{
public class MultipleOperationsWithSameVerbFilter : IOperationFilter
{
public void Apply(
Operation operation,
SchemaRegistry schemaRegistry,
ApiDescription apiDescription)
{
if (operation.parameters != null)
{
operation.operationId += "By";
foreach (var parm in operation.parameters)
{
operation.operationId += string.Format("{0}",parm.name);
}
}
}
}
}
in SwaggerConfig.cs
c.OperationFilter<MultipleOperationsWithSameVerbFilter>();
Now this is helpful transforming swagger description, check bellow:
All good, now I endup in a darker place, example similar with may cases: on same controller I have two endpoints
- Post: /customer boddy: {email, location....}
- Post: /customer/search boddy: {a filter, whatever}
The example is not quite correct (last post should be a get) but still le assume that webapi cannot be changed (new controller for separation) for this particular case I will try to figure out a way to generate operationId diffrent for each action somehow, but my question is this:
Is it possible to decorate somehow the controller actions similar with [JsonIgnore] or with [Route("customer/delete")], to be explicit about the operationId.
You can use the SwaggerOperationAttribute
provided by Swashbuckle for that.
[SwaggerOperation("get")]
public IEnumerable<Contact> Get()
{
....
}
[SwaggerOperation("getById")]
public IEnumerable<Contact> Get(string id)
{
...
}
You can use that attribute to add tags and schemes to your operation as well by the way. Have a look at the source code
UPDATE: to have functional rest API import in visual studio without a lot of refactoring (adding by hand operation name)
I've updated a bit the custom operation filter, this one generates unique ids in 99% cases. The remaining percent came from unfortunate API implementation.
public class MultipleOperationsWithSameVerbFilter : IOperationFilter
{
public void Apply(
Operation operation,
SchemaRegistry schemaRegistry,
ApiDescription apiDescription)
{
string refsSwaggerIds = string.Empty;
operation.parameters?.ForEach(x =>
{
if (!string.IsNullOrEmpty(x.schema?.@ref) &&
!string.IsNullOrEmpty(x.schema?.@ref.Split('/').LastOrDefault()))
{
refsSwaggerIds += x.schema?.@ref.Split('/').LastOrDefault();
}
else
{
refsSwaggerIds += x.name;
}
});
operation.operationId += !string.IsNullOrEmpty(refsSwaggerIds)
? refsSwaggerIds
: apiDescription.RelativePath?.Replace("/", "_").Replace("{", "").Replace("}", "");
}
}
public class HandleComplexTypesFromUri : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
//this is incorect form swager helper pov, but for rest api import in visual studio is the only way for GET with complex type to be imported
if (operation.parameters == null || apiDescription.HttpMethod.Method != "GET")
return;
var models = schemaRegistry.Definitions;
var apiParams = apiDescription.ParameterDescriptions;
if (apiParams.Count == operation.parameters.Count) return;
foreach (var apiParameterDescription in apiParams)
{
if (!models.ContainsKey(apiParameterDescription.ParameterDescriptor.ParameterType.Name))
continue;
operation.parameters =
operation.parameters.Where(
x =>
x.@in != "query" ||
(x.@in == "query" && !x.name.StartsWith(apiParameterDescription.Name + "."))).ToList();
if (operation.parameters.Count(x => x.name == apiParameterDescription.Name) == 0)
{
//var t = Type.GetType(apiParameterDescription.ParameterDescriptor.ParameterType.Name);
operation.parameters.Add(new Parameter
{
name = apiParameterDescription.Name.ToLowerInvariant(),
//type = apiParameterDescription.ParameterDescriptor.ParameterType.Name,
@in = "query",
required = true,
schema = schemaRegistry.GetOrRegister(apiParameterDescription.ParameterDescriptor.ParameterType)
//schema = models[apiParameterDescription.ParameterDescriptor.ParameterType.Name]
});
}
}
}
In swagger config use
GlobalConfiguration.Configuration
.EnableSwagger(c =>
// at some point
c.OperationFilter<HandleComplexTypesFromUri>();
c.OperationFilter<MultipleOperationsWithSameVerbFilter>();
})// the rest ...
来源:https://stackoverflow.com/questions/39412998/swashbuckle-set-manualy-operationid