I have an ASP.NET Core Web API that contains the following endpoint.
[HttpGet]
[Route("models/{ids}")]
[Produces(typeof(IEnumerable<Model>))]
public IActionResult Get
(
    [ModelBinder(typeof(CsvModelBinder<string>))] IEnumerable<string> ids
)
{
    // Get models
    return Ok(models);
}
This endpoint takes a CSV list of Ids (e.g. /models/a,b,c) and returns a JSON array of the corresponding Model objects.  CsvModelBinder<string> is a custom implementation of IModelBinder I wrote that splits the CSV list of Ids into an IEnumerable<string> that I can use in my query to go find the objects.  This all works great.
What I'm now trying to do is generate a client library using NSwag, but this is proving problematic because Swashbuckle is generating Swagger that describes the ids parameter as an IEnumerable<string>, not a string.
Option A: Is there a way to tell Swashbuckle to describe the parameter as a string instead of as an IEnumerable<string>?
Option B: Is there a way to tell NSwag that this IEnumerable<string> parameter should be marshalled into a CSV when generating the request URL?
I figured it out. I needed to create a custom model use MapType() in Startup.cs
public class Csv<T> : List<T> where T : IConvertible
{
    public Csv<T> Append(string delimitedValues)
    {
        var splitValues = delimitedValues
            .Split(',', StringSplitOptions.RemoveEmptyEntries)
            .Cast<string>();
        var convertedValues = splitValues
            .Select(str => Convert.ChangeType(str, typeof(T)))
            .Cast<T>();
        this.AddRange(convertedValues);
        return this;
    }
    public override string ToString()
    {
        return this.Aggregate("", (a,s) => $"{a},{s}").Trim(',');
    }
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddSwaggerGen(c =>
    {
        c.IncludeXmlComments(() => new XPathDocument(new FileStream(Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "MyApi.xml"), FileMode.Open)));
        c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1"});
        c.MapType<Csv<string>>(() => new Schema { Type = "string", Format = "string" });
    });
}
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