Adding Swagger to a C# WebApi

About Swagger

Swagger (https://swagger.io/) is a free open-source tool that enables easy documentation and testing of APIs. It is language agnostic.

Swashbuckle (https://github.com/domaindrivendev/Swashbuckle) is a .Net specific tool that adds Swagger to a .Net Web Api.

Installation

Install from Nuget

Install-Package Swashbuckle

Register Swagger

The Swashbuckle install should create a SwaggerConfig.cs file in the App_start Directory. This will allow you to configure Swagger in various ways.

Enable XML document generation

Open the project properties for your WebApi project, select the build tab and change the setting below:

Annotation 2019-02-20 111835

Update swagger config to use the XML comments

In the SwaggerConfig.cs file uncomment the line below:

c.IncludeXmlComments(GetXmlCommentsPath());

and add the method :

private static string GetXmlCommentsPath()
{
   var filepath = System.String.Format(@"{0}\bin\documentation.XML", System.AppDomain.CurrentDomain.BaseDirectory);
   return filepath;
}

Adding XML comments to code

On your controller and individual endpoints add the /// triple slash comments, for example

///
/// Search returns a paged, filterd list of events
///

///filters for the search ///number of entries to return per page ///page number to return ///name of column to sort by ///direction of sort /// A list of Events /// Success /// No Data Found /// Internal Server Error [Route(“Search”)] [HttpGet] [SwaggerResponse(200)] [ResponseType(typeof(IQueryable))] public IHttpActionResult GetList([FromUri] EventArguments parameters, [FromUri] int pageSize = 25, [FromUri] int pageNumber = 1, [FromUri] string sortColumn = “Id”, [FromUri] bool sortForward = true) { … }

 

Creating a multi project solution in VS2013

Ok, so this is probably a bit out of date as VS2019 is due out soon, but one of my clients is still using VS2013 as their main IDE, as they can’t update one of their projects for various reasons.

The project I’m working on them with is an AngularJS front-end to a micro-services architecture with around 20 micro-services. Creating a new service can be a bit of a pain, especially keeping them in line with internal standards, therefore I created a multi-project template to create a new service, and it does it in around 5 minutes from scratch to a working WebApi service.

I followed the guide here: https://docs.microsoft.com/en-us/visualstudio/ide/how-to-create-multi-project-templates?view=vs-2017, but there are a couple of gotchas.

    1. Take a working solution and copy it into a new folder, remember to remove source control bindings.
      folder structure
    2. Strip the solution to a bare bones solution that provides a working example of what you want do do. For this project, I have one data model, one DTO, one repository & interface, one service and interface and one WebAPI controller with one endpoint.solution Explorer
    3. Check that it still runs.
    4. Clean the solution, delete contents of bin and obj directories  in each project.
    5. In the File menu choose Export Template, and export each project. These will be exported to a folder like C:\Users\XXX\Documents\Visual Studio 2013\My Exported Templates
      Export Template Menu Item
      Export Template Page 1

      Export Template Page 2
    6. Copy each of them into the respective project folders and rename them to match the project name.
      Project contents
    7. Create a root.vsTemplate file – Refer to the guide for more info on this.
    8. Select the project folder and the root.vsTemplate (exclude the solution file, packages folder and .nuget folder) and right click –> Send to –>Compressed (zip) file.
    9. Rename the zip file and copy it to C:\Users\XXX\Documents\Visual Studio 2013\Templates\ProjectTemplates.
    10. Open a new copy of Visual Studio and select File\Create a new project, search for your template and create a new project.
    11. You should have a fully working WebApi.
    12. You can now add the package to a VSIX project and make that available for everyone to use.

 

 

WebApi2, CORS & HTTP 401 Unauthorized error

I got caught out with this issue again today, and it took me ages to find/remember the fix. Whilst using VS2013 to debug a website & web service running on separate ports on localhost, I kept getting a 401 error. I checked and rechecked that I had CORS set up properly, but the error just wouldn’t go away.

At last I remembered to set the default credentials on the WebClient instance:

        public User GetUser(string userName)
        {
            User model = null;
            string json = string.Empty;
            using (WebClient client = new WebClient())
            {
                client.UseDefaultCredentials = true;

                try
                {
                    string url = this.Url + "/"  + HttpUtility.UrlEncode(userName);

                    json = client.DownloadString(url);
                }
                catch (WebException)
                {
                    json = string.Empty;
                }
            }
            if (json.Length > 0)
            {
                model = JsonConvert.DeserializeObject(json);
            }
            return model;
        }

Web Dev Gotchas–Personal

This post is just for me, because I’ve forgotten more than once.

1. Until I update my scaffolding to work with VS2103, it doesn’t. Create the projects in Vs2012

2. WebApi – Json camelCase and serialising child objects :

var jsonFormatter = GlobalConfiguration.Configuration.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

3. Repositories – including child objects

using System.Collections.Generic;
using System.Linq;
using System.Data.Objects;
public override ICollection<Book> GetAll()
{     BookReviewsContext context = (BookReviewsContext)DataContext;     var books = context         .Books         .Include("Authors")         .Where(x => !x.IsDeleted)         .ToList<Book>();     return books;
 
}