Building APIs with C# and ASP.NET Core

Configuring Controllers for OpenAPI

Spencer Schneidenbach

Spencer Schneidenbach

Aviron Software, Microsoft MVP
Building APIs with C# and ASP.NET Core

Check out a free preview of the full Building APIs with C# and ASP.NET Core course

The "Configuring Controllers for OpenAPI" Lesson is part of the full, Building APIs with C# and ASP.NET Core course featured in this preview video. Here's what you'd learn in this lesson:

Spencer adds documentation for the API. XML comments are also introduced and added to the API. The project settings are adjusted so the XML comments will appear, and warnings for uncommented classes will not prevent the build from running.

Preview
Close

Transcript from the "Configuring Controllers for OpenAPI" Lesson

[00:00:00]
>> Spencer Schneidenbach: I wanna talk about our docs, the docs that we get out of this, because I am a believer that an API lives and dies by its documentation. So that's my way of saying I think documentation is super important. So I wanna enhance this because right now, these docs are fairly anemic.

[00:00:18]
You can look at our GET Employees, our POST Employees. It does have our request body, but it doesn't have a nice little descriptor. We can spruce these up a little bit. It doesn't even tell us what are all the different success codes. For example, in our PUT request, in our POST request, we should be able to say, you could expect a 400 bad request back if you give a 400 bad request.

[00:00:37]
And then describe the shape of the object that we would expect. So minimal APIs have their way of doing it. What you do is you just chain off of the map get and then you start calling more methods to add more OpenAI metadata. We are going to add in some attributes to basically better describe to open API what's going on.

[00:01:01]
So let's update our endpoints to have some descriptions and have some tags. We're gonna start with the ProducesResponseType attribute. So let's take a look at that. Okay, GetAllEmployees. So we pasted that in. And you can see that of this, we should expect to see a 200 okay. Here's the shape of the object that you can expect to get back, or a 500 internal server error if something went wrong.

[00:01:30]
On our GetEmployeeById, we could expect the same, except we should also expect that we will be able to get back a 404 if we request an employee ID for an employee that does not exist. And in our posted output,
>> Spencer Schneidenbach: We can do much of the same. We know that if our POST request is successful, that we'll send back a 201 we created with a GetEmployeeResponse.

[00:02:01]
And we could also send back a 400 bad request. And our PUT request can also have all of those things plus a 404 not found in case we don't have that employee in our system. So let's take a look at what that does for our API. We're gonna hit play, and we're gonna see now when we scroll down, we actually get what we expect back.

[00:02:24]
We get this 201 created. The media type, okay, text/plain, I don't exactly expect that. We'll address that in one second. This is the good stuff, 400 bad request. And here's exactly what you can expect the shape of that object to be. This is really useful, especially for developers on the frontend or developers that are consuming your API in any way.

[00:02:45]
It will create the document for you as long as you give it enough metadata in order to be able to create that documentation. So it'll send back, you know what, you will give back a possible validation problem details. Here's what that looks like, or a server error, as we expect.

[00:03:02]
Let's address this media type thing real quick. We know that this is a JSON API. We know that we just wanna send JSON back and forth. We can do that by going up to our base controller, and we can add a produces, if I could spell produces right, there we go.

[00:03:18]
And we can give it a content type. You can see that content type is one of the arguments. And typically, I just write produces application JSON. I don't use any of the other arguments. And when you play that and refresh, you'll see now that the content type is indeed application JSON, which is what you would expect.

[00:03:37]
So that's already really great. We've already done actually quite a bit of it. With very little work, we've actually provided a huge amount of rich documentation, which is really useful. But we can do even better, and that's where XML comments come in. So XML comments are a really neat language feature that I highly recommend that if you're defining APIs that other people will use.

[00:03:59]
APIs being JSON APIs, or even just methods and functions, I highly recommend that you use XML comments. So it's a good way to add documentation to your code. So here's how you do it. I'm gonna hit stop. I'm gonna go to my EmployeesController, and I'm gonna go to the blank line above and hit Enter, and I'm gonna go slash, slash, slash.

[00:04:21]
And what it's gonna do is create XML comments. So you see up here, there's a little XML bracket where we can say gets all of the employees in the system, returns the employee in a JSON array. So what you could do is actually teach OpenAPI how to interpret these XML comments, which is really neat.

[00:04:48]
So let me show you how that works. First things first, in your csproj file, we'll go ahead and open that up real quick, right here, and we're gonna add in this GenerateDocumentationFile. And what that's going to instruct the build system to do is it's going to instruct it to generate a .xml file that contains all of the methods and all of the properties that we've added XML comments for.

[00:05:14]
And it's going to put them inside of that XML file. And then we can pick that XML file up and read it. You are going to start getting a lot of warnings, things like this, where you're saying missing XML comment for publicly visible or type member EmployeesController. And this will prevent build, right?

[00:05:33]
This will prevent build because we said treat warnings as errors, which is mostly a good thing if you get a warning. Most of the warnings actually mean something. But we can turn those off, and that's what we're going to do, because we don't necessarily need to XML comment everything.

[00:05:47]
I don't know that it's super valuable that we add an XML comment to EmployeesController or even the constructor. So we're just going to bypass and ignore that by adding in this NoWarn directive. And basically, it's gonna say, hey, turn off the warnings for this particular error code. And you can see that our problem space in our IDE, our squiggly lines are gone and our problems are like, okay, well, all right, we'll just trust you know what you're doing.

[00:06:13]
And then lastly, in our builder.Services call, we're gonna add this IncludeXmlComments, so we're just gonna copy and paste this in. And we're gonna read from the base directory. And then we're gonna say, read this TheEmployeeAPI.xml file. So we can do that here. When we go to our Program.cs, we can go to our AddSwaggerGen.

[00:06:39]
>> Spencer Schneidenbach: And then we're gonna say options.IncludeXmlComments. And it's gonna read through all of those XML comments and then apply them to our Swagger documentation. So I only did it on one endpoint, which is our GET endpoint right here. But you can see that we can add it and say gets all the employees in our system.

[00:06:57]
So let's go ahead and apply them to the rest of the endpoints. Because XML comments can also include data on the parameters to that method, which is actually really valuable. So we're gonna go ahead and do that on our update employees call. We're gonna go here. We're gonna go down to updateEmployee, paste that in.

[00:07:20]
We're gonna go down to our,
>> Spencer Schneidenbach: Create and paste that in.
>> Spencer Schneidenbach: And we're gonna go to this, GetEmployeeById.
>> Spencer Schneidenbach: Paste that in. And then you see when we rerun the project that our nice XML comments get copied over, as well as a nice description of each of the parameters, which is really cool.

[00:07:48]
The reason I like this a lot is that it's developer friendly, so it's integrated in with the language. It gives the developer a natural way to create comments in a way that makes sense to them. But it also gives enough metadata back to Swagger such that our OpenAPI UI can actually use this information.

[00:08:12]
And you can't do this with minimal APIs. You have to go through and define it. It's a little bit messier, but it is possible to do this. But XML comments, I like it because it's language integrated. It's very natural.
>> Spencer Schneidenbach: So we made our documentation much better, and I think that's a good thing.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now