I have an Action that consumes application/x-www-form-urlencoded:
[HttpPost("~/connect/token"), Consumes("application/x-www-form-urlencoded")]
public async Task<IActionResult> Exchange([FromBody]OpenIdConnectRequest request)
{
   ..
}
But Swashbuckle generates empty array for Consumes property. If I change it to application/json, consumes array is generated properly.
Is it a bug related to application/x-www-form-urlencoded or I need to configure Swashbuckle additionally to support this application type?
That 'consumes' is not catered for out-of-the-box for Swashbuckle, a custom extension is required like the ones in this part of @domaindrivendev's GitHub project
There are three steps:
I'll add more instructions in my fork of the repo, but here is the code:
using System;
using System.Collections.Generic;
using System.Net.Http.Formatting;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Validation;
/// <summary>
/// FromFormDataBody Attribute
/// This attribute is used on action parameters to indicate
/// they come only from the content body of the incoming HttpRequestMessage.
/// </summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
public sealed class FromFormDataBodyAttribute : ParameterBindingAttribute
{
    /// <summary>
    /// GetBinding
    /// </summary>
    /// <param name="parameter">HttpParameterDescriptor</param>
    /// <returns>HttpParameterBinding</returns>
    public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
    {
        if (parameter == null)
            throw new ArgumentNullException("parameter");
        IEnumerable<MediaTypeFormatter> formatters = parameter.Configuration.Formatters;
        IBodyModelValidator validator = parameter.Configuration.Services.GetBodyModelValidator();
        return parameter.BindWithFormatter(formatters, validator);
    }
}
using Swashbuckle.Swagger;
using System.Linq;
using System.Web.Http.Description;
/// <summary>
/// Add UrlEncoded form data support for Controller Actions that have FromFormDataBody attribute in a parameter
/// usage: c.OperationFilter<AddUrlFormDataParams>();
/// </summary>
public class AddUrlFormDataParams : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
        var fromBodyAttributes = apiDescription.ActionDescriptor.GetParameters()
            .Where(param => param.GetCustomAttributes<FromFormDataBodyAttribute>().Any())
        .ToArray();
        if (fromBodyAttributes.Any())
            operation.consumes.Add("application/x-www-form-urlencoded");
        foreach (var headerParam in fromBodyAttributes)
        {
            if (operation.parameters != null)
            {
                // Select the capitalized parameter names
                var parameter = operation.parameters.Where(p => p.name == headerParam.ParameterName).FirstOrDefault();
                if (parameter != null)
                {
                    parameter.@in = "formData";//NB. ONLY for this 'complex' object example, as it will be passed as body JSON.
//TODO add logic to change to "query" for string/int etc. as they are passed via query string.
                }
            }
        }
    }
}
 //Add UrlEncoded form data support for Controller Actions that have FromBody attribute in a parameter
c.OperationFilter<AddUrlFormDataParams>();
[FromFormDataBody]OpenIdConnectRequest request
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