Coding is all about not repeating yourself and standing on the shoulders of giants. These two properties can be really seen working for you when you build an ASP.NET Core app and utilize something like Swagger to automate the generation of technical API documentation and client code schemas.
With a toolset like NSwag, it's incredibly easy to simple write your backend code and have an auto-generated documentation, along with a nice web frontend to make first steps with the API and even generated schemas for all your models. For example, I'm using it for AVACloud to generate clients for various languages and environments, such as TypeScript.
However, my data model had one catch: Inheritance. As soon as you leave the golden path, you're about to encounter problems. For me, I noticed that the generated swagger.json document did not treat inheritance correctly, thus my generated clients had incomplete data models.
I've followed the documentation for setting up inheritance and got good-looking results at first, but noticed that the generated clients did not include any properties for derived classes. That was not optimal, so I dug a bit further.
The NSwag docs work with this example:
Which should lead to a Swagger definition like the following:
However, after reading the official Swagger documentation about inheritance, or the allOf property, you'll see this schema given:
Which, besides being in YAML, has one distinct difference: The Dog class does not define a properties list itself, but keeps both a reference to the base class as well as all its own properties in its allOf list.
So what we need to do is somehow configure the NSwag generator on our server to follow this behavior.
The fix is actually quite easy, but took me some time to figure out. You can supply your own ISchemaProcessor on the server side when generating swagger.json documents, so that's what we do:
The InheritanceSchemaProcessor just checks if the current schema has entries in its allOf property. If it has, we simply add its own properties there, too.
Now, in your Startup you just have to add your ISchemaProcessor to the NSwag UseSwagger configuration. Your schema processor will be called for every individual model schema in your API.
Finally, your Swagger output should look like the following: