Create an account


Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ASP.NET Core 2.20-preview1: Open API Analyzers & Conventions

#1
ASP.NET Core 2.20-preview1: Open API Analyzers & Conventions

<div style="margin: 5px 5% 10px 5%;"><img src="http://www.sickgaming.net/blog/wp-content/uploads/2018/08/asp-net-core-2-20-preview1-open-api-analyzers-conventions.gif" width="730" height="387" title="" alt="" /></div><div><h2 id="what-is-it">What is it?</h2>
<p>Open API (alternatively known as Swagger) is a language-agnostic specification for describing REST APIs. The Open API ecosystem has tools that allows for discovering, testing and producing client code using the specification. Support for generating and visualizing Open API documents in ASP.NET Core MVC is provided via community driven projects such as <a href="https://github.com/RSuter/NSwag">NSwag</a>, and <a href="https://github.com/domaindrivendev/Swashbuckle.AspNetCore">Swashbuckle.AspNetCore</a>. Visit <a href="https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?view=aspnetcore-2.1">https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?view=aspnetcore-2.1</a> to learn more about Open API Swagger and for details on configuring your applications to use it.</p>
<p>For 2.2, we’re investing in tooling and runtime experiences to to allow developers to produce better Open API documents. This work ties in with ongoing work to perform client code SDK generation during build.</p>
<h2 id="how-to-use-it">How to use it?</h2>
<h3 id="analyzer">Analyzer</h3>
<p>For 2.2, we’re introducing a new API-specific analyzers NuGet package – <code>Microsoft.AspNetCore.Mvc.Api.Analyzers</code>. These analyzers work with controllers annotated with <code>ApiController</code> introduced in 2.1, while building on API conventions that we’re also introducing in this release. To start using this, install the package:</p>
<div class="sourceCode" id="cb1">
<pre class="sourceCode xml"><code class="sourceCode xml">
<span class="kw">&lt;PackageReference</span><span class="ot"> Include=</span><span class="st">"Microsoft.AspNetCore.Mvc.Api.Analyzers"</span>
<span class="ot"> Version=</span><span class="st">"2.2.0-preview1-35029"</span>
<span class="ot"> PrivateAssets=</span><span class="st">"All"</span> <span class="kw">/&gt;</span></code></pre>
</div>
<p>Open API documents contain each status code and response type an operation may return. In MVC, you use attributes such as <code>ProducesResponseType</code> and <code>Produces</code> to document these. The analyzer inspects controllers annotated with <code>ApiController</code> and identifies actions that do not entirely document their responses. You should see this as warnings (squiggly lines) highlighting return types that aren’t documented as well as warnings in the output. In Visual Studio, this should additionally appear under the “Warnings” tab in the “Error List” dialog. You now have the opportunity to address these warnings using code fixes.</p>
<p>Let’s look at the analyzer in action:</p>
<h2 id="what-is-it"><a href="http://www.sickgaming.net/blog/wp-content/uploads/2018/08/asp-net-core-2-20-preview1-open-api-analyzers-conventions.gif"><img src="http://www.sickgaming.net/blog/wp-content/uploads/2018/08/asp-net-core-2-20-preview1-open-api-analyzers-conventions.gif" alt="" width="730" height="387" class="alignnone size-full wp-image-14975" /></a></h2>
<p>The analyzer identified that the action returned a <code>404</code> but did not document it using a <code>ProducesResponseTypeAttribute</code>. We used a code fix to document this. The added attributes would now become available for <a href="https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?view=aspnetcore-2.1">Swagger / Open API tools</a> to consume. It’s a great way to identify areas of your application that are lacking swagger documentation and correct it.</p>
<h3 id="conventions">Conventions</h3>
<p>If your controllers follows some common patterns, e.g. they are all primarily CRUD endpoints, and you aren’t already using <code>ProducesResponseType</code> or <code>Produces</code> to document them, you could consider using API conventions. Conventions let you define the most common “conventional” return types and status codes that you return from your action, and apply them to individual actions or controllers, or all controllers in an assembly. Conventions are a substitute to decorating individual actions with <code>ProducesResponseType</code> attributes.</p>
<p>By default, ASP.NET Core MVC 2.2 ships with a set of default conventions – <code>DefaultApiConventions</code> – that’s based on the controller that ASP.NET Core scaffolds. If your actions follow the pattern that scaffolding produces, you should be successful using the default conventions.</p>
<p>At runtime, ApiExplorer understand conventions. ApiExplorer is MVC’s abstraction to communicate with Open API document generators. Attributes from the applied convention get associated with an action and will be included in action’s Swagger documentation. API analyzers also understand conventions. If your action is <em>unconventional</em> i.e. it returns a status code that is not documented by the applied convention, it will produce a warning, encouraging you to document it.</p>
<p>There are 3 ways to apply a convention to a controller action:</p>
<ul>
<li>Applying the <code>ApiConventionType</code> attribute as an assembly level attribute. This applies the specified convention to all controllers in an assembly.</li>
</ul>
<div class="sourceCode" id="cb1">
<pre class="sourceCode c#"><code class="sourceCode cs">[assembly: <span class="fu">ApiConvention</span>(<span class="kw">typeof</span>(DefaultApiConventions))]</code></pre>
</div>
<ul>
<li>Using the <code>ApiConventionType</code> attribute on a controller.</li>
</ul>
<div class="sourceCode" id="cb2">
<pre class="sourceCode c#"><code class="sourceCode cs">[<span class="fu">ApiConvention</span>(<span class="kw">typeof</span>(DefaultApiConventions))]
[ApiController]
[<span class="fu">Route</span>(<span class="st">"/api/[controller]"</span>)]
<span class="kw">public</span> <span class="kw">class</span> PetsController : ControllerBase
{ ...
}</code></pre>
</div>
<ul>
<li>Using <code>ApiConventionMethod</code>. This attributes accepts both the type and the convention method.</li>
</ul>
<div class="sourceCode" id="cb3">
<pre class="sourceCode c#"><code class="sourceCode cs"><span class="co">// PUT: api/Pets/5</span>
[<span class="fu">ApiConventionMethod</span>(<span class="kw">typeof</span>(DefaultApiConventions), <span class="fu">nameof</span>(DefaultApiConventions.<span class="fu">Put</span>))]
[<span class="fu">HttpPut</span>(<span class="st">"{id}"</span>)]
<span class="kw">public</span> async Task&lt;ActionResult&lt;Pet&gt;&gt; <span class="fu">PutPet</span>(<span class="dt">long</span> id, Pet pet)
{ ...
}</code></pre>
</div>
<p>Like many other features in MVC, more specific attributes will supersede less specific ones. An API metadata attribute such as <code>ProducesResponseType</code> or <code>Produces</code> applied to an action will stop applying any convention atributes. The <code>ApiConventionMethod</code> will supersede a <code>ApiConventionType</code> attribute applied to the method’s controller or the assembly; and an <code>ApiConventionType</code> attribute applied to a controller will supersede ones applied to the assembly.</p>
<h4 id="authoring-conventions">Authoring conventions</h4>
<p>A convention is a static type with methods. These methods are annotated with <code>ProducesResponseType</code> or <code>ProducesDefaultResponseType</code> attributes.</p>
<div class="sourceCode" id="cb1">
<pre class="sourceCode c#"><code class="sourceCode cs"><span class="kw">public</span> <span class="kw">static</span> <span class="kw">class</span> MyAppConventions
{ [<span class="fu">ProducesResponseType</span>(<span class="dv">200</span>)] [<span class="fu">ProducesResponseType</span>(<span class="dv">404</span>)] <span class="kw">public</span> <span class="kw">static</span> <span class="dt">void</span> <span class="fu">Find</span>(<span class="dt">int</span> id) {
}
}</code></pre>
</div>
<p>Applying this convention to an assembly would result in the convention method applying to any action with the name <code>Find</code> and having exactly one parameter named <code>id</code>, as long as they do not have other more specific metadata attributes.</p>
<p>In addition to <code>ProducesResponseType</code> and <code>ProducesDefaultResponseType</code>, two additional attributes – <code>ApiConventionNameMatch</code> and <code>ApiConventionTypeMatch</code> – can be applied to the convention method that determines the methods they apply to.</p>
<div class="sourceCode" id="cb2">
<pre class="sourceCode c#"><code class="sourceCode cs">[<span class="fu">ProducesResponseType</span>(<span class="dv">200</span>)]
[<span class="fu">ProducesResponseType</span>(<span class="dv">404</span>)]
[<span class="fu">ApiConventionNameMatch</span>(ApiConventionNameMatchBehavior.<span class="fu">Prefix</span>)]
<span class="kw">public</span> <span class="kw">static</span> <span class="dt">void</span> <span class="fu">Find</span>( [<span class="fu">ApiConventionNameMatch</span>(ApiConventionNameMatchBehavior.<span class="fu">Suffix</span>)] <span class="dt">int</span> id)
{ }</code></pre>
</div>
<p>The <code>ApiConventionNameMatchBehavior.Prefix</code> applied to the method, indicates that the convention can match any action as long as it starts with the prefix “Find”. This will include methods such as <code>Find</code>, <code>FindPet</code> or <code>FindById</code>. The <code>ApiConventionNameMatchBehavior.Suffix</code> applied to the parameter, indicates that the convention can match methods with exactly one parameter that terminate in the suffix <code>id</code>. This will include parameters such as <code>id</code>, or <code>petId</code>. <code>ApiConventionTypeMatch</code> can be similarly applied to types to constrain the type of the parameter. A <code>params[]</code> arguments can be used to indicate remaining parameters that do not need not be explicitly matched.</p>
<p>An easy way to get started authoring a custom convention is to start by copying the body of <code>DefaultApiConventions</code> and modifying it. Here’s a link to the source of the type: <a href="https://raw.githubusercontent.com/aspnet/Mvc/release/2.2/src/Microsoft.AspNetCore.Mvc.Core/DefaultApiConventions.cs">https://raw.githubusercontent.com/aspnet/Mvc/release/2.2/src/Microsoft.AspNetCore.Mvc.Core/DefaultApiConventions.cs</a></p>
<h3 id="feedback">Feedback</h3>
<p>This is one on our earliest forays in trying to use tooling to enhance runtime experiences. We’re interested in any thoughts you have about this as well as your experiences using this in your applications. The best place to provide feedback is by opening issues at <a href="https://github.com/aspnet/Mvc">https://github.com/aspnet/Mvc</a>.</p>
<h3 id="additional-help">Additional help</h3>
<p> </p>
</div>
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

Forum software by © MyBB Theme © iAndrew 2016