In this post, we will look at how to update Swagger in an Azure API Management service. Let’s continue from this previous example, where we created an Azure App Service.
Our Swagger for this app service looks like this:
If we go to our APIM in Azure, let’s add in this code.
Click on swagger.json:
We see the JSON. Get the URL:
Paste it into the APIM Open Specification:
We see our API:
And selecting each one gives us more information:
Now what happens if we update our code to include new operations? In our controller, let’s update the code.
Let’s add Swashbuckle.AspNetCore.Annotations:
And let’s add some new functionality, including a method to GetCustomersByLastName and some additional PostCustomer functions. We will add SwaggerResponse to the operations as well, which will implement HTTP Status Codes such as HttpStatusCode.OK, HttpStatusCode.NotFound, HttpStatusCode.Created, HttpStatusCode.NotImplemented etc.
The code:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; using Carl.CRM.API.Models; using Microsoft.AspNetCore.Mvc; using Swashbuckle.AspNetCore.Annotations; namespace Carl.CRM.API.Controllers { [Route("api/[controller]")] [ApiController] public class CustomersController : ControllerBase { // GET api/values [HttpGet] [SwaggerOperation("GetCustomers")] [SwaggerResponse((int)HttpStatusCode.OK)] [SwaggerResponse((int)HttpStatusCode.NotFound)] public ActionResult<IEnumerable<string>> Get() { Customer bob = new Customer { Id = 1, FirstName = "Bob", LastName = "Smith" }; Customer david = new Customer { Id = 2, FirstName = "David", LastName = "Johnson" }; Customer alice = new Customer { Id = 3, FirstName = "Alice", LastName = "Carter" }; Customer bill = new Customer { Id = 4, FirstName = "Bill", LastName = "James" }; List<Customer> customers = new List<Customer>(); customers.Add(bob); customers.Add(david); customers.Add(alice); customers.Add(bill); return new JsonResult(customers); } // GET api/values [HttpGet("GetCustomersByLastName/{lastname}")] [SwaggerOperation("GetCustomers")] [SwaggerResponse((int)HttpStatusCode.OK)] [SwaggerResponse((int)HttpStatusCode.NotFound)] public ActionResult<IEnumerable<string>> GetCustomers(string lastname) { Customer bob = new Customer { Id = 1, FirstName = "Bob", LastName = "Smith" }; Customer david = new Customer { Id = 2, FirstName = "David", LastName = "Johnson" }; Customer alice = new Customer { Id = 3, FirstName = "Alice", LastName = "Carter" }; Customer bill = new Customer { Id = 4, FirstName = "Bill", LastName = "James" }; List<Customer> customers = new List<Customer>(); customers.Add(bob); customers.Add(david); customers.Add(alice); customers.Add(bill); return new JsonResult(customers.Where(c => c.LastName.Contains(lastname))); } // GET api/values/5 [HttpGet("{id}")] [SwaggerOperation("GetCustomer")] [SwaggerResponse((int)HttpStatusCode.OK)] [SwaggerResponse((int)HttpStatusCode.NotFound)] public ActionResult<string> Get(int id) { Customer bob = new Customer { Id = 1, FirstName = "Bob", LastName = "Smith" }; Customer david = new Customer { Id = 2, FirstName = "David", LastName = "Johnson" }; Customer alice = new Customer { Id = 3, FirstName = "Alice", LastName = "Carter" }; Customer bill = new Customer { Id = 4, FirstName = "Bill", LastName = "James" }; if (id ==1) { return Ok(bob); } else if (id == 2) { return Ok(david); } else if (id == 3) { return Ok(alice); } else if (id == 4) { return Ok(bill); } else { return NotFound(); } } // POST api/values [HttpPost("{id}")] [SwaggerOperation("PostCustomer")] [SwaggerResponse((int)HttpStatusCode.OK)] [SwaggerResponse((int)HttpStatusCode.NotFound)] [SwaggerResponse((int)HttpStatusCode.Created)] public void PostCustomer([FromBody] string value) { } // POST api/values [HttpPost("PostCustomer2")] [SwaggerOperation("PostCustomer2")] [SwaggerResponse((int)HttpStatusCode.NotImplemented)] public void PostCustomer2([FromBody] string value) { } // POST api/values [HttpPost("PostCustomer3/{id}")] [SwaggerOperation("PostCustomer3")] [SwaggerResponse((int)HttpStatusCode.OK)] [SwaggerResponse((int)HttpStatusCode.NotFound)] public void PostCustomer3([FromBody] string value) { } // PUT api/values/5 [HttpPut("{id}")] [SwaggerOperation("PutCustomer")] [SwaggerResponse((int)HttpStatusCode.OK)] [SwaggerResponse((int)HttpStatusCode.NotFound)] public void Put(int id, [FromBody] string value) { } // DELETE api/values/5 [HttpDelete("{id}")] [SwaggerOperation("DeleteCustomer")] [SwaggerResponse((int)HttpStatusCode.OK)] [SwaggerResponse((int)HttpStatusCode.NotFound)] public void Delete(int id) { } } }
Now let’s deploy our changes up to Azure first using Visual Studio. Right-click and Publish:
Now let’s Publish:
Now if we go to the Swagger for our deployed service, we see this has updated it. This also happens if we deploy by copying the files to the service using the Kudu SCM:
However, our APIM has not updated:
To update this, first go to the Swagger JSON and copy it:
Now in the APIM click on Frontend:
We see the old JSON:
Paste over this with the new JSON and Save:
We now see our new operations appearing:
I AM SPENDING MORE TIME THESE DAYS CREATING YOUTUBE VIDEOS TO HELP PEOPLE LEARN THE MICROSOFT POWER PLATFORM.
IF YOU WOULD LIKE TO SEE HOW I BUILD APPS, OR FIND SOMETHING USEFUL READING MY BLOG, I WOULD REALLY APPRECIATE YOU SUBSCRIBING TO MY YOUTUBE CHANNEL.
THANK YOU, AND LET'S KEEP LEARNING TOGETHER.
CARL
Hello,
On quick question. Is there a way to do this swagger update automatic?
I mean, when new code is deployed, trigger some action or link the swagger definition to keep it up to date?
Thanks!
@Leonardo, Probably this could help https://medium.com/@raswinraaj/automatic-update-of-api-in-azure-api-management-using-terraform-d761dbea9f91