PageRenderTime 81ms CodeModel.GetById 17ms app.highlight 59ms RepoModel.GetById 1ms app.codeStats 0ms

/articles/app-service-api/app-service-api-dotnet-swashbuckle-customize.md

https://gitlab.com/yeah568/azure-content
Markdown | 251 lines | 178 code | 73 blank | 0 comment | 0 complexity | 9547d30cda1607e78530148b16089f82 MD5 | raw file
  1
  2<properties 
  3	pageTitle="Customize Swashbuckle-generated API definitions" 
  4	description="Learn how to customize Swagger API definitions that are generated by Swashbuckle for an API app in Azure App Service." 
  5	services="app-service\api" 
  6	documentationCenter=".net" 
  7	authors="bradygaster" 
  8	manager="wpickett" 
  9	editor="jimbe"/>
 10
 11<tags 
 12	ms.service="app-service-api" 
 13	ms.workload="web" 
 14	ms.tgt_pltfrm="dotnet" 
 15	ms.devlang="na" 
 16	ms.topic="article" 
 17	ms.date="02/22/2016" 
 18	ms.author="rachelap"/>
 19
 20# Customize Swashbuckle-generated API definitions 
 21
 22## Overview
 23
 24This article explains how to customize Swashbuckle to handle common scenarios where you may want to alter the default behavior:
 25
 26* Swashbuckle generates duplicate operation identifiers for overloads of controller methods
 27* Swashbuckle assumes that the only valid response from a method is HTTP 200 (OK) 
 28 
 29## Customize operation identifier generation
 30
 31Swashbuckle generates Swagger operation identifiers by concatenating controller name and method name. This pattern creates a problem when you have multiple overloads of a method: Swashbuckle generates duplicate operation ids, which is invalid Swagger JSON.
 32
 33For example, the following controller code causes Swashbuckle to generate three Contact_Get operation ids.
 34
 35![](./media/app-service-api-dotnet-swashbuckle-customize/multiplegetsincode.png)
 36
 37![](./media/app-service-api-dotnet-swashbuckle-customize/multiplegetsinjson.png)
 38
 39You can solve the problem manually by giving the methods unique names, such as the following for this example:
 40
 41* Get
 42* GetById
 43* GetPage
 44
 45The alternative is to extend Swashbuckle to make it automatically generate unique operation ids.
 46
 47The following steps show how to customize Swashbuckle by using the *SwaggerConfig.cs* file that is included in the project by the Visual Studio API Apps Preview project template.  You can also customize Swashbuckle in a Web API project that you configure for deployment as an API app.
 48
 491. Create a custom `IOperationFilter` implementation 
 50
 51	The `IOperationFilter` interface provides an extensibility point for Swashbuckle users who want to customize various aspects of the Swagger metadata process. The following code demonstrates one method of changing the operation-id-generation behavior. The code appends parameter names to the operation id name.  
 52
 53		using Swashbuckle.Swagger;
 54		using System.Web.Http.Description;
 55		
 56		namespace ContactsList
 57		{
 58		    public class MultipleOperationsWithSameVerbFilter : IOperationFilter
 59		    {
 60		        public void Apply(
 61		            Operation operation,
 62		            SchemaRegistry schemaRegistry,
 63		            ApiDescription apiDescription)
 64		        {
 65		            if (operation.parameters != null)
 66		            {
 67		                operation.operationId += "By";
 68		                foreach (var parm in operation.parameters)
 69		                {
 70		                    operation.operationId += string.Format("{0}",parm.name);
 71		                }
 72		            }
 73		        }
 74		    }
 75		}
 76
 772. In *App_Start\SwaggerConfig.cs* file, call the `OperationFilter` method to cause Swashbuckle to use the new `IOperationFilter` implementation.
 78
 79		c.OperationFilter<MultipleOperationsWithSameVerbFilter>();
 80
 81	![](./media/app-service-api-dotnet-swashbuckle-customize/usefilter.png)
 82
 83	The *SwaggerConfig.cs* file that is dropped in by the Swashbuckle NuGet package contains many commented-out examples of extensibility points. The additional comments are not shown here. 
 84
 85	After you make this change, your `IOperationFilter` implementation is used and causes unique operation ids to be generated.
 86 
 87	![](./media/app-service-api-dotnet-swashbuckle-customize/uniqueids.png)
 88
 89<a id="multiple-response-codes" name="multiple-response-codes"></a>
 90	
 91## Allow response codes other than 200
 92
 93By default, Swashbuckle assumes that an HTTP 200 (OK) response is the *only* legitimate response from a Web API method. In some cases, you may want to return other response codes without causing the client to raise an exception.  For example, the following Web API code demonstrates a scenario in which you would want the client to accept either a 200 or a 404 as valid responses.
 94
 95	[ResponseType(typeof(Contact))]
 96    public HttpResponseMessage Get(int id)
 97    {
 98        var contacts = GetContacts();
 99
100        var requestedContact = contacts.FirstOrDefault(x => x.Id == id);
101
102        if (requestedContact == null)
103        {
104            return Request.CreateResponse(HttpStatusCode.NotFound);
105        }
106        else
107        {
108            return Request.CreateResponse<Contact>(HttpStatusCode.OK, requestedContact);
109        }
110    }
111
112In this scenario, the Swagger that Swashbuckle generates by default specifies only one legitimate HTTP status code, HTTP 200.
113
114![](./media/app-service-api-dotnet-swashbuckle-customize/http-200-output-only.png)
115
116Since Visual Studio uses the Swagger API definition to generate code for the client, it creates client code that raises an exception for any response other than an HTTP 200. The code below is from a C# client generated for this sample Web API method.
117
118	if (statusCode != HttpStatusCode.OK)
119    {
120        HttpOperationException<object> ex = new HttpOperationException<object>();
121        ex.Request = httpRequest;
122        ex.Response = httpResponse;
123        ex.Body = null;
124        if (shouldTrace)
125        {
126            ServiceClientTracing.Error(invocationId, ex);
127        }
128        throw ex;
129    } 
130
131Swashbuckle provides two ways of customizing the list of expected HTTP response codes that it generates, using XML comments or the `SwaggerResponse` attribute. The attribute is easier, but it is only available in Swashbuckle 5.1.5 or later. The API Apps preview new-project template in Visual Studio 2013 includes Swashbuckle version 5.0.0, so if you used the template and don't want to update Swashbuckle, your only option is to use XML comments. 
132
133### Customize expected response codes using XML comments
134
135Use this method to specify response codes if your Swashbuckle version is earlier than 5.1.5.
136
1371. First, add XML documentation comments over the methods you wish to specify HTTP response codes for. Taking the sample Web API action shown above and applying the XML documentation to it would result in code like the following example. 
138
139		/// <summary>
140		/// Returns the specified contact.
141		/// </summary>
142		/// <param name="id">The ID of the contact.</param>
143		/// <returns>A contact record with an HTTP 200, or null with an HTTP 404.</returns>
144		/// <response code="200">OK</response>
145		/// <response code="404">Not Found</response>
146		[ResponseType(typeof(Contact))]
147		public HttpResponseMessage Get(int id)
148		{
149		    var contacts = GetContacts();
150		
151		    var requestedContact = contacts.FirstOrDefault(x => x.Id == id);
152		
153		    if (requestedContact == null)
154		    {
155		        return Request.CreateResponse(HttpStatusCode.NotFound);
156		    }
157		    else
158		    {
159		        return Request.CreateResponse<Contact>(HttpStatusCode.OK, requestedContact);
160		    }
161		}
162
1631. Add instructions in the *SwaggerConfig.cs* file to direct Swashbuckle to make use of the XML documentation file.
164
165	* Open *SwaggerConfig.cs* and create a method on the *SwaggerConfig* class to specify the path to the documentation XML file. 
166
167			private static string GetXmlCommentsPath()
168			{
169			    return string.Format(@"{0}\XmlComments.xml", 
170			        System.AppDomain.CurrentDomain.BaseDirectory);
171			}
172
173	* Scroll down in the *SwaggerConfig.cs* file until you see the commented-out line of code resembling the screen shot below. 
174
175		![](./media/app-service-api-dotnet-swashbuckle-customize/xml-comments-commented-out.png)
176	
177	* Uncomment the line to enable the XML comments processing during Swagger generation. 
178	
179		![](./media/app-service-api-dotnet-swashbuckle-customize/xml-comments-uncommented.png)
180	
1811. In order to generate the XML documentation file, go into the project's properties and enable the XML documentation file as shown in the screenshot below. 
182
183	![](./media/app-service-api-dotnet-swashbuckle-customize/enable-xml-documentation-file.png) 
184
185Once you perform these steps, the Swagger JSON generated by Swashbuckle will reflect the HTTP response codes that you specified in the XML comments. The screenshot below demonstrates this new JSON payload. 
186
187![](./media/app-service-api-dotnet-swashbuckle-customize/swagger-multiple-responses.png)
188
189When you use Visual Studio to regenerate the client code for your REST API, the C# code accepts both the HTTP OK and Not Found status codes without raising an exception, allowing your consuming code to make decisions on how to handle the return of a null Contact record. 
190
191		if (statusCode != HttpStatusCode.OK && statusCode != HttpStatusCode.NotFound)
192		{
193		    HttpOperationException<object> ex = new HttpOperationException<object>();
194		    ex.Request = httpRequest;
195		    ex.Response = httpResponse;
196		    ex.Body = null;
197		    if (shouldTrace)
198		    {
199		        ServiceClientTracing.Error(invocationId, ex);
200		    }
201        	    throw ex;
202		}
203
204The code for this demonstration can be found in [this GitHub repository](https://github.com/Azure-Samples/app-service-api-dotnet-swashbuckle-swaggerresponse). Along with the Web API project marked up with XML documentation comments is a Console Application project that contains a generated client for this API. 
205
206### Customize expected response codes using the SwaggerResponse attribute
207
208The [SwaggerResponse](https://github.com/domaindrivendev/Swashbuckle/blob/master/Swashbuckle.Core/Swagger/Annotations/SwaggerResponseAttribute.cs) attribute is available in Swashbuckle 5.1.5 and later. In case you have an earlier version in your project, this section starts by explaining how to update the Swashbuckle NuGet package so that you can use this attribute.
209
2101. In **Solution Explorer**, right-click your Web API project and click **Manage NuGet Packages**. 
211
212	![](./media/app-service-api-dotnet-swashbuckle-customize/manage-nuget-packages.png)
213
2141. Click the *Update* button next to the *Swashbuckle* NuGet package. 
215
216	![](./media/app-service-api-dotnet-swashbuckle-customize/update-nuget-dialog.png)
217
2181. Add the *SwaggerResponse* attributes to the Web API action methods for which you want to specify valid HTTP response codes. 
219
220		[SwaggerResponse(HttpStatusCode.OK)]
221		[SwaggerResponse(HttpStatusCode.NotFound)]
222		[ResponseType(typeof(Contact))]
223		public HttpResponseMessage Get(int id)
224		{
225		    var contacts = GetContacts();
226
227		    var requestedContact = contacts.FirstOrDefault(x => x.Id == id);
228		    if (requestedContact == null)
229		    {
230		        return Request.CreateResponse(HttpStatusCode.NotFound);
231		    }
232		    else
233		    {
234		        return Request.CreateResponse<Contact>(HttpStatusCode.OK, requestedContact);
235		    }
236		}
237
2382. Add a `using` statement for the attribute's namespace:
239
240		using Swashbuckle.Swagger.Annotations;
241		
2421. Browse to the */swagger/docs/v1* URL of your project and the various HTTP response codes will be visible in the Swagger JSON. 
243
244	![](./media/app-service-api-dotnet-swashbuckle-customize/multiple-responses-post-attributes.png)
245
246The code for this demonstration can be found in [this GitHub repository](https://github.com/Azure-Samples/API-Apps-DotNet-Swashbuckle-Customization-MultipleResponseCodes-With-Attributes). Along with the Web API project decorated with the *SwaggerResponse* attribute is a Console Application project that contains a generated client for this API. 
247
248## Next steps
249
250This article has shown how to customize the way Swashbuckle generates operation ids and valid response codes. For more information, see [Swashbuckle on GitHub](https://github.com/domaindrivendev/Swashbuckle).
251