Workaround for using type parameter in attribute for using ProducesResponseType with a generic type argument?

c# generic attribute
producesresponsetypeattribute

I have a generic ASP.NET Core WebApi controller like:

public abstract class EntityController<TEntity> 
{
    public IActionResult Get(string id)
    {
        var entity = ... //load from database by id
        if (entity != null) 
            return new JsonResult(value, this.SerializerSettings()) {StatusCode  200};
        return NotFound();
    }
}

and I want to apply following attributes on the Get() method:

[ProducesResponseType(typeof(TEntity), 200)] //this causes compilation error.
[ProducesResponseType(typeof(Object), 404)]

For now, the only work around is to override each method in derived controller and add attributes there:

public class DerivedController :EntityController<MyEntity>
{
    [ProducesResponseType(typeof(TEntity), (int) HttpStatusCode.OK)]
    [ProducesResponseType(typeof(Object), (int) HttpStatusCode.NotFound)]
    public IActionResult Get(string id)
    {
        return base.Get(id);
    }
}

Ihis is very inconvenient that I should override every REST methods in every controller, just for use the concrete TEntity type in attributes. :-(

Any better work arounds?


Althrough I found no way to use generic type parameter in ProducesResponseTypeAttribute, I found another way to make swagger work:

Use IApplicationModelConvention to update ApplicationModel, which is used by swagger.

public class EntityControllerConversion : IApplicationModelConvention
{
    public void Apply(ApplicationModel application)
    {
        ActionModel action = ... // finds the controller action 
        Type viewModelType = ... // get the view type by reflection from the controller
        SetResponseUsingHack(action, viewModelType, HttpStatusCode.OK);
    }

    private void SetResponseUsingHack(ActionModel actionModel, Type responseType, HttpStatusCode statusCode)
    {
        if (actionModel == null) throw new ArgumentNullException(nameof(actionModel));
        if (responseType == null) throw new ArgumentNullException(nameof(responseType));

        var writable = (IList<object>)(actionModel.Attributes);
        var attribute = FindResponseAttributeUsingHack(writable, statusCode);
        if (attribute != null)
        {
            attribute.Type = responseType;
        }
    }

    private ProducesResponseTypeAttribute FindResponseAttributeUsingHack(IList<object> attributes, HttpStatusCode statusCode)
    {
        if (attributes == null) return null;
        var result = attributes.OfType<ProducesResponseTypeAttribute>()
            .Where(x => x.Type == typeof(ProducesResponseStub))
            .FirstOrDefault(x => x.StatusCode == (int) statusCode);
        return result;
    }
}

public abstract class EntityController<TEntity> 
{
    [HttpGet]
    [ProducesResponseType(typeof(ProducesResponseStub), 200)]
    public IActionResult Get(string id)
    {
    }
}

public static class ProducesResponseStub
{
}

NOTE: Swagger won't work correctly if you just add a new ProducesResponseTypeAttribute instance to ActionModel.Attributes, may be it's a bug in swagger or in asp.net core. That why I use ProducesResponseStub in decorating action methods in EntityController and replace them with correct types in EntityControllerConversion.

Workaround for using type parameter in attribute for using , Workaround for using type parameter in attribute for using ProducesResponseType with a generic type argument? c# generic attribute An attribute is applied using an argument that is either a type parameter or is constructed using a type parameter. Visual Basic and the .NET Framework do not currently support any combination of attributes and generic types. This means the following limitations apply: An attribute cannot be a generic type or be declared within a generic type.


Since .NET Core 2.1 instead of using IActionResult, you can use ActionResult<TEntity> as returntype (or Task<ActionResult<TEntity>>) and then swagger will also know the returntype for 200 calls!

ProducesResponseType doesn't infer the type from ActionResult<T , The ProducesResponseType attribute's Type property can be excluded the same behavior as using the return type for actions without any attributes, Fix Api Explorer not returning type with ActionResult<T> and no type … Because there are multiple return types and paths in this type of action, liberal use of the [ProducesResponseType] attribute is necessary. This attribute produces more descriptive response details for web API help pages generated by tools like Swagger. [ProducesResponseType] indicates the known types and HTTP status codes to be returned by the


The DefaultApiDescriptionProvider in package Microsoft.AspNetCore.Mvc.ApiExplorer has been improved so that it will pick up method return type.

Note that the [ProducesResponseType(StatusCodes.Status200OK)] attribute is required when other [ProducesResponseType] attributes are specified as shown below:

    [HttpGet, Route("")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ProblemDetailsResponse))]
    [ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(ProblemDetailsResponse))]
    public async Task<IEnumerable<TResponse>> GetAll(int imoNo)
    {
        var parameters = await _parameterService.GetAllAsync(imoNo);

        return parameters.Select(x => MapToResponse(x));
    }

Confirmed to work in Microsoft.AspNetCore.Mvc.ApiExplorer v2.2.0.

Also work with StatusCodes.Status201Created.

Controller action return types in ASP.NET Core web API, Learn about using the various controller action method return types in an ASP. The preceding action accepts no parameters, so parameter constraints in this type of action, liberal use of the [ProducesResponseType] attribute is necessary. One option to fix the preceding code is to return _repository. I don't see ProducesResponse in ASP.NET Core 2.1 even though the last comment said it would be in 1.1. ProducesResponseType is still there. What happened to this? Is there a better way to specify the expected Response Codes like 404 w/o specifying a type. Did people just not think it was useful?


Why does C# forbid generic attribute types?, Workaround for using type parameter in attribute for using ProducesResponseType with a generic type argument?. I have a generic ASP.​NET Core WebApi  Custom attributes are only permitted to reference open generic types, which are generic types for which no type arguments are supplied, and closed constructed generic types, which supply arguments for all type parameters. The following examples use this custom attribute: class CustomAttribute : System.Attribute { public System.Object info; } An


Hot Linked Questions, Workaround for using type parameter in attribute for using ProducesResponseType with a generic type argument? c# asp.net · Sep 24 '19 at 10:16 ArunPratap. For each type argument, determine whether it is a type parameter (for example, in a generic type definition) or a type that has been specified for a type parameter (for example, in a constructed type), using the IsGenericParameter property.


Generic controllers in ASP.Net Core, 31 questions linked to/from Why does C# forbid generic attribute types? Hot Newest Votes Active Workaround for using type parameter in attribute for using ProducesResponseType with a generic type argument? I have a generic ASP. Ignore my previous comment (now deleted). The generic type arguments for a generic attribute type can be encoded in the MemberRef metadata table, by representing the "Class" field as a TypeSpec. — Reply to this email directly or view it on GitHub #953 (comment).