Search code examples
c#genericsasp.net-corereflectionasp.net-core-mvc

Accessing generic class parameter T from a method Attribute in ASP.NET Core


Is it possible to somehow access the type argument T of a generic class from a method attribute that is attached to a method in this generic class?

Example:

Let's say I have a generic Controller MyBaseController handling a certain resource type T that is extended by a child controller MyChildController.

public class MyChildController : MyBaseController<BlogPost>
{
  // ...
}

Now I am using Swagger to document my API, more specifically Swashbuckle, hence, I am annotating my action with ProducesResponseType to specifiy the return type of the action. This is where it get's complicated because ProducesResponseType expects a Type argument denoting the class of the value returned by the action.

public abstract class MyBaseController<T> : Controller where T : IResource
{
   [HttpGet, ProducesResponseType(T)] // <-- DOESN'T WORK!
   public async Task<IActionResult> doSomething()
   {
     // ...
   }
 }

In the example above I need T to somehow resolve to typeof(BlogPost)

Any ideas, or is this impossible?


Solution

  • Accessing generics in attributes is not available.

    Consider an alternative approach

    Reference Controller action return types in ASP.NET Core Web API

    ASP.NET Core 2.1 introduces the ActionResult<T> return type for Web API controller actions. It enables you to return a type deriving from ActionResult or return a specific type.

    public abstract class MyBaseController<T> : Controller where T : IResource {
        [HttpGet]
        public async Task<ActionResult<T>> doSomething() {
            // ...
        }
    }
    

    It was create for that very purpose

    ActionResult<T> offers the following benefits over the IActionResult type:

    • The [ProducesResponseType] attribute's Type property can be excluded.
    • Implicit cast operators support the conversion of both T and ActionResult to ActionResult<T>. T converts to ObjectResult, which means return new ObjectResult(T); is simplified to return T;.