I have had no problem getting a json
file in my Web API project using Microsoft's tutorial.
Due to some requirement I would like to be able to retrieve a yaml
file. But the problem is there is no hook I could find to make this possible.
Does anyone know any workaround for this problem?
V 5.6 supports producing YAML files. How to use it:
app.UseSwaggerUI(x => { x.SwaggerEndpoint("/swagger/v1/swagger.yaml", "Zeipt Dashboard API"); });
An option will be to add an IDocumentFilter to your project, here are a couple of samples:
private class YamlDocumentFilter : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
string file = AppDomain.CurrentDomain.BaseDirectory + "swagger_yaml.txt";
if (!File.Exists(file))
{
var serializer = new YamlSerializer();
serializer.SerializeToFile(file, swaggerDoc);
}
}
}
...
private class YamlDocumentFilter : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
string file = AppDomain.CurrentDomain.BaseDirectory + "swagger.yaml";
if (!File.Exists(file))
{
var serializer = new YamlDotNet.Serialization.Serializer();
using (var writer = new StringWriter())
{
serializer.Serialize(writer, swaggerDoc);
var stream = new StreamWriter(file);
stream.WriteLine(writer.ToString());
}
}
}
}
but that depends on your project if adding an additional reference to YamlSerializer or YamlDotNet is acceptable.
Based on idea given by @HelderSepu I managed to get Swashbuckle.AspNetCore together with YamlDotNet generate the following YAML passing validation on https://bigstickcarpet.com/swagger-parser/www/index.html.
I know this solution is not ideal, but might be some starting point in case someone has the same problem:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using YamlDotNet.Core;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.TypeInspectors;
namespace SwaggerPhun
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info
{
Version = "v1",
Title = "File Comment API",
Description = "A simple example ASP.NET Core Web API",
//TermsOfService = "None",
Contact = new Contact
{
Name = "Pawel",
Email = "[email protected]",
},
License = new License
{
Name = "Use under LICX",
Url = "https://example.com/license"
},
});
c.DocumentFilter<YamlDocumentFilter>();
// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
}
private class YamlDocumentFilter : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
{
var builder = new SerializerBuilder();
builder.WithNamingConvention(new HyphenatedNamingConvention());
builder.WithTypeInspector(innerInspector => new PropertiesIgnoreTypeInspector(innerInspector));
var serializer = builder.Build();
using (var writer = new StringWriter())
{
serializer.Serialize(writer, swaggerDoc);
var file = AppDomain.CurrentDomain.BaseDirectory + "swagger_yaml.txt";
using (var stream = new StreamWriter(file))
{
var result = writer.ToString();
stream.WriteLine(result.Replace("2.0", "\"2.0\"").Replace("ref:", "$ref:"));
}
}
}
}
private class PropertiesIgnoreTypeInspector : TypeInspectorSkeleton
{
private readonly ITypeInspector _typeInspector;
public PropertiesIgnoreTypeInspector(ITypeInspector typeInspector)
{
this._typeInspector = typeInspector;
}
public override IEnumerable<IPropertyDescriptor> GetProperties(Type type, object container)
{
return _typeInspector.GetProperties(type, container).Where(p => p.Name != "extensions" && p.Name != "operation-id");
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With