Install-Package Swashbuckle
SwaggerConfig.cs
file that is created with the package installation, we uncomment the line c.IncludeXmlComments(GetXmlCommentsPath());
GetXmlCommentsPath()
method, we write the return string.Format(@"{0}\bin\BookStoreApiService.XML", AppDomain.CurrentDomain.BaseDirectory);
<ExcludeXmlAssemblyFiles>false</ExcludeXmlAssemblyFiles>
in the PropertyGroup of the project and the file will remain in bin/
. // SwaggerConfig.cs c.RootUrl(req => ComputeClientHost(req)); // public static string ComputeClientHost(HttpRequestMessage req) { var authority = req.RequestUri.Authority; var scheme = req.RequestUri.Scheme; // , if (req.Headers.Contains("X-Forwarded-Host")) { // var xForwardedHost = req.Headers.GetValues("X-Forwarded-Host").First(); var firstForwardedHost = xForwardedHost.Split(',')[0]; authority = firstForwardedHost; } // , if (req.Headers.Contains("X-Forwarded-Proto")) { var xForwardedProto = req.Headers.GetValues("X-Forwarded-Proto").First(); xForwardedProto = xForwardedProto.Split(',')[0]; scheme = xForwardedProto; } return scheme + "://" + authority; }
/// <response code="404">Not Found</response> [SwaggerResponse(HttpStatusCode.NotFound, Type = typeof(Model), Description = "Not Found: no such endpoint")]
[SwaggerResponseRemoveDefaults]
attribute. HttpStatusCode[] _codes; // public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) { // if (operation.responses == null) operation.responses = new Dictionary<string, Response>(); foreach (var code in _codes) { var codeNum = ((int)code).ToString(); var codeName = code.ToString(); // if (!operation.responses.ContainsKey(codeNum)) operation.responses.Add(codeNum, new Response { description = codeName }); } }
The text below discusses several options for implementing Basic authorization. But the package supports others.
// Basic Authorization attributes config.Filters.Add(new AuthorizeAttribute()); config.Filters.Add(new BasicAuthenticationFilter()); // IAuthenticationFilter
c.BasicAuth("basic").Description("Basic HTTP Authentication");
string c.BasicAuth("basic").Description("Basic HTTP Authentication");
c.OperationFilter<MarkSecuredMethodsOperationFilter>();
nodes c.OperationFilter<MarkSecuredMethodsOperationFilter>();
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) { var filterPipeline = apiDescription.ActionDescriptor.GetFilterPipeline(); // check if authorization is required var isAuthorized = filterPipeline .Select(filterInfo => filterInfo.Instance) .Any(filter => filter is IAuthorizationFilter); // check if anonymous access is allowed var allowAnonymous = apiDescription.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any(); if (isAuthorized && !allowAnonymous) { if (operation.security == null) operation.security = new List<IDictionary<string, IEnumerable<string>>>(); var auth = new Dictionary<string, IEnumerable<string>> { {"basic", Enumerable.Empty<string>()} }; operation.security.Add(auth); } }
The following two methods should be considered as examples of working with an IOperationFilter and injecting your JavaScript.
operation.parameters.Add(new Parameter { name = "Authorization", @in = "header", // , description = "Basic U3dhZ2dlcjpUZXN0", // Basic Swagger:Test required = true, // type = "string" });
c.InjectJavaScript(thisAssembly, "assembly.namesapce.swagger-basic-auth.js");
swaggerUi.api.clientAuthorizations.add("basic", new SwaggerClient.ApiKeyAuthorization("Authorization", "Basic U3dhZ2dlcjpUZXN0", "header"));
swaggerUi.api.clientAuthorizations.add("custom1", new SwaggerClient.ApiKeyAuthorization("X-Header-1", "value1", "header")); swaggerUi.api.clientAuthorizations.add("custom2", new SwaggerClient.ApiKeyAuthorization("X-Header-2", "value2", "header")); swaggerUi.api.clientAuthorizations.add("custom3", new SwaggerClient.ApiKeyAuthorization("X-Header-3", "value3", "header"));
config.MessageHandlers.Add(new MandatoryHeadersHandler());
. In this case, Swagger will stop showing something, because requests to him will not pass, because Handler forbids them. Out of the box, this is not solved at all, so it is necessary to provide this case in your handler. Those. in case of request to the swagger URL, skip it. And further, adding headers with JS, as described above, will help. [ResponseType(typeof (IList<Model>))] public IHttpActionResult Get() {...} [ResponseType(typeof (IList<Model>))] public IHttpActionResult Get(int count, bool descending) {...}
c.ResolveConflictingActions(Func<IEnumerable<ApiDescription>, ApiDescription> conflictingActionsResolver)
. The essence of the method is to take several conflicting methods and return one. return apiDescriptions => { var descriptions = apiDescriptions as ApiDescription[] ?? apiDescriptions.ToArray(); var first = descriptions.First(); // var parameters = descriptions.SelectMany(d => d.ParameterDescriptions).ToList(); first.ParameterDescriptions.Clear(); // foreach (var parameter in parameters) if (first.ParameterDescriptions.All(x => x.Name != parameter.Name)) { first.ParameterDescriptions.Add(new ApiParameterDescription { Documentation = parameter.Documentation, Name = parameter.Name, ParameterDescriptor = new OptionalHttpParameterDescriptor((ReflectedHttpParameterDescriptor) parameter.ParameterDescriptor), Source = parameter.Source }); } return first; }; // , .. IsOptional getter public class OptionalHttpParameterDescriptor : ReflectedHttpParameterDescriptor { public OptionalHttpParameterDescriptor(ReflectedHttpParameterDescriptor parameterDescriptor) : base(parameterDescriptor.ActionDescriptor, parameterDescriptor.ParameterInfo) { } public override bool IsOptional => true; }
c.CustomProvider(defaultProvider => new NewSwaggerProvider(defaultProvider));
. To do this, you can do this: private readonly IApiExplorer _apiExplorer; private readonly IDictionary<string, Info> _apiVersions; private readonly JsonSerializerSettings _jsonSerializerSettings; private readonly SwaggerGeneratorOptions _options; public MultiOperationSwaggerGenerator(ISwaggerProvider sp) { var sg = (SwaggerGenerator) sp; var privateFields = sg.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic); _apiExplorer = privateFields.First(pf => pf.Name == "_apiExplorer").GetValue(sg) as IApiExplorer; _jsonSerializerSettings = privateFields.First(pf => pf.Name == "_jsonSerializerSettings").GetValue(sg) as JsonSerializerSettings; _apiVersions = privateFields.First(pf => pf.Name == "_apiVersions").GetValue(sg) as IDictionary<string, Info>; _options = privateFields.First(pf => pf.Name == "_options").GetValue(sg) as SwaggerGeneratorOptions; }
var paths = GetApiDescriptionsFor(apiVersion)....
This is where the paths are created. For example, to get what in the example, you need to replace GroupBy () with .GroupBy(apiDesc => apiDesc.RelativePath)
.Source: https://habr.com/ru/post/317338/
All Articles