swagger-api / swagger-api/swagger-codegen

[aspnetcore] Implement c# server through inheritance and abstract override

Open
#9,967 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

Description

I want to write a yaml OpenAPI specification and generate a c# client and server from it (I do not want to generate the yaml for the c# server code.).

The code generator generates something similar to this:

  [ApiController]
    public class PetApiController : ControllerBase, IPetApiController
    { 
        /// <summary>
        /// Deletes a pet
        /// </summary>
        /// <param name="petId">Pet id to delete</param>
        /// <param name="apiKey"></param>
        /// <response code="400">Invalid ID supplied</response>
        /// <response code="404">Pet not found</response>
        [HttpDelete]
        [Route("/v2/pet/{petId}")]
        [ValidateModelState]
        [SwaggerOperation("DeletePet")]
        public virtual IActionResult DeletePet([FromRoute][Required]long? petId, [FromHeader]string apiKey)
        { 
            //TODO: Uncomment the next line to return response 400 or use other options such as return this.NotFound(), return this.BadRequest(..), ...
            // return StatusCode(400);

            //TODO: Uncomment the next line to return response 404 or use other options such as return this.NotFound(), return this.BadRequest(..), ...
            // return StatusCode(404);

            throw new NotImplementedException();
        }
}

What I want to do is to Not touch anything of the generated code, inherit this class and implement it:

    public class TestController : PetApiController
    {
        public override IActionResult DeletePet(long? petId, string apiKey)
        {
            // TODO my new implementation goes here.
            throw new NotImplementedException();
        }
    }

But I will get an error, that the path/route is used twice:

Exception thrown: 'System.IO.FileNotFoundException' in System.Private.CoreLib.dll
'dotnet.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.5\System.Reflection.Emit.dll'. 
'dotnet.exe' (CoreCLR: clrhost): Loaded 'Microsoft.GeneratedCode'. 
'dotnet.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.5\System.Reflection.Extensions.dll'. 
'dotnet.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.5\System.Reflection.TypeExtensions.dll'. 
Exception thrown: 'System.NotSupportedException' in Swashbuckle.AspNetCore.SwaggerGen.dll
Exception thrown: 'System.NotSupportedException' in System.Private.CoreLib.dll
Exception thrown: 'System.NotSupportedException' in System.Private.CoreLib.dll
Exception thrown: 'System.NotSupportedException' in System.Private.CoreLib.dll
Exception thrown: 'System.NotSupportedException' in System.Private.CoreLib.dll
'dotnet.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.5\System.Diagnostics.StackTrace.dll'. 
'dotnet.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.5\System.Reflection.Metadata.dll'. 
Microsoft.AspNetCore.Server.Kestrel:Error: Connection id "0HLSKRN7E1EUJ", Request id "0HLSKRN7E1EUJ:00000002": An unhandled exception was thrown by the application.

System.NotSupportedException: HTTP method "GET" & path "v2/pet/{petId}" overloaded by actions - IO.Swagger.Controllers.TestController.GetPetById (IO.Swagger),IO.Swagger.Controllers.TestController.GetPetById2 (IO.Swagger). Actions require unique method/path combination for Swagger 2.0. Use ConflictingActionsResolver as a workaround
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.CreatePathItem(IEnumerable`1 apiDescriptions, ISchemaRegistry schemaRegistry)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.CreatePathItems(IEnumerable`1 apiDescriptions, ISchemaRegistry schemaRegistry)
   at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwagger(String documentName, String host, String basePath, String[] schemes)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 336.3171ms 500 
The thread 0x5560 has exited with code 0 (0x0).
The thread 0x56cc has exited with code 0 (0x0).
The thread 0x904 has exited with code 0 (0x0).

Now my Question is: How can I properly override those methods without getting this error? If I change the methods from virtual to abstract, remove the (not relevant, generated) "implementation", the error disappears.

Swagger-codegen version

3.0.15 Windows

Command line used for generation
java -jar swagger-codegen-cli-3.0.15.jar generate -i petstore.yaml -l aspnetcore
Suggest a fix/enhancement

There is very likely something I am not aware of yet, but if that is not the case, we could maybe also provide an abstract option to generate. The interface-only option does not contain any path definitions, so that is not a suitable option.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the aspnetcore generator entry point and templates used by the swagger-codegen-cli command, then reproduce the duplicate-route error with petstore.yaml and the generated PetApiController/TestController. Done means the generated server can be inherited and overridden without duplicate routes, or an abstract-generation option is clearly supported and documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, openapi
Domain
backend-api-design, tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.