-
Notifications
You must be signed in to change notification settings - Fork 25.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add docs for api conventions and analyzers (#9453)
* Add docs for api conventions and analyzers Fixes #8332 * Edit pass on API conventions and analyzers content (#9574) * Edit pass on 2.2 API docs (#9578) * Scottaddie/open api patch (#9582) * Edit pass on 2.2 API docs * Resolve build warning * Fix list formatting
- Loading branch information
1 parent
d9d1173
commit 78b9850
Showing
14 changed files
with
479 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
--- | ||
title: Use web API analyzers | ||
author: pranavkm | ||
description: Learn about the web API analyzers in Microsoft.AspNetCore.Mvc.Api.Analyzers. | ||
monikerRange: '>= aspnetcore-2.2' | ||
ms.author: pranavkm | ||
ms.custom: mvc | ||
ms.date: 11/13/2018 | ||
uid: web-api/advanced/analyzers | ||
--- | ||
# Use web API analyzers | ||
|
||
ASP.NET Core 2.2 introduces the [Microsoft.AspNetCore.Mvc.Api.Analyzers](https://www.nuget.org/packages/Microsoft.AspNetCore.Mvc.Api.Analyzers) NuGet package containing analyzers for web APIs. The analyzers work with controllers annotated with <xref:Microsoft.AspNetCore.Mvc.ApiControllerAttribute>, while building on [API conventions](xref:web-api/advanced/conventions). | ||
|
||
## Package installation | ||
|
||
`Microsoft.AspNetCore.Mvc.Api.Analyzers` can be added with one of the following approaches: | ||
|
||
### [Visual Studio](#tab/visual-studio) | ||
|
||
* From the **Package Manager Console** window: | ||
* Go to **View** > **Other Windows** > **Package Manager Console**. | ||
* Navigate to the directory in which the *ApiConventions.csproj* file exists. | ||
* Execute the following command: | ||
|
||
```powershell | ||
Install-Package Microsoft.AspNetCore.Mvc.Api.Analyzers | ||
``` | ||
* From the **Manage NuGet Packages** dialog: | ||
* Right-click the project in **Solution Explorer** > **Manage NuGet Packages**. | ||
* Set the **Package source** to "nuget.org". | ||
* Enter "Microsoft.AspNetCore.Mvc.Api.Analyzers" in the search box. | ||
* Select the "Microsoft.AspNetCore.Mvc.Api.Analyzers" package from the **Browse** tab and click **Install**. | ||
### [Visual Studio for Mac](#tab/visual-studio-mac) | ||
* Right-click the *Packages* folder in **Solution Pad** > **Add Packages...**. | ||
* Set the **Add Packages** window's **Source** drop-down to "nuget.org". | ||
* Enter "Microsoft.AspNetCore.Mvc.Api.Analyzers" in the search box. | ||
* Select the "Microsoft.AspNetCore.Mvc.Api.Analyzers" package from the results pane and click **Add Package**. | ||
### [Visual Studio Code](#tab/visual-studio-code) | ||
Run the following command from the **Integrated Terminal**: | ||
```console | ||
dotnet add ApiConventions.csproj package Microsoft.AspNetCore.Mvc.Api.Analyzers | ||
``` | ||
|
||
### [.NET Core CLI](#tab/netcore-cli) | ||
|
||
Run the following command: | ||
|
||
```console | ||
dotnet add ApiConventions.csproj package Microsoft.AspNetCore.Mvc.Api.Analyzers | ||
``` | ||
|
||
--- | ||
|
||
## Analyzers for API conventions | ||
|
||
Open API documents contain status codes and response types that an action may return. In ASP.NET Core MVC, attributes such as <xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute> and <xref:Microsoft.AspNetCore.Mvc.ProducesAttribute> are used to document an action. <xref:tutorials/web-api-help-pages-using-swagger> goes into further detail on documenting your API. | ||
|
||
One of the analyzers in the package inspects controllers annotated with <xref:Microsoft.AspNetCore.Mvc.ApiControllerAttribute> and identifies actions that don't entirely document their responses. Consider the following example: | ||
|
||
[!code-csharp[](conventions/sample/Controllers/ContactsController.cs?name=missing404docs&highlight=9)] | ||
|
||
The preceding action documents the HTTP 200 success return type but doesn't document the HTTP 404 failure status code. The analyzer reports the missing documentation for the HTTP 404 status code as a warning. An option to fix the problem is provided. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
--- | ||
title: Use web API conventions | ||
author: pranavkm | ||
description: Learn about web API conventions in ASP.NET Core. | ||
monikerRange: '>= aspnetcore-2.2' | ||
ms.author: pranavkm | ||
ms.custom: mvc | ||
ms.date: 11/13/2018 | ||
uid: web-api/advanced/conventions | ||
--- | ||
# Use web API conventions | ||
|
||
ASP.NET Core 2.2 introduces a way to extract common [API documentation](xref:tutorials/web-api-help-pages-using-swagger) and apply it to multiple actions, controllers, or all controllers within an assembly. Web API conventions are a substitute for decorating individual actions with [[ProducesResponseType]](xref:Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute). It allows you to define the most common "conventional" return types and status codes that you return from your action with a way to select the convention method that applies to an action. | ||
|
||
By default, ASP.NET Core MVC 2.2 ships with a set of default conventions, `Microsoft.AspNetCore.Mvc.DefaultApiConventions`. The conventions are 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. | ||
|
||
At runtime, <xref:Microsoft.AspNetCore.Mvc.ApiExplorer> understands conventions. `ApiExplorer` is MVC's abstraction to communicate with Open API document generators. Attributes from the applied convention get associated with an action and are included in the action's Swagger documentation. API analyzers also understand conventions. If your action is unconventional (for example, it returns a status code that isn't documented by the applied convention), it produces a warning, encouraging you to document it. | ||
|
||
[View or download sample code](https://github.com/aspnet/Docs/tree/master/aspnetcore/web-api/advanced/conventions/sample) ([how to download](xref:index#how-to-download-a-sample)) | ||
|
||
## Apply web API conventions | ||
|
||
There are three ways to apply a convention. Conventions don't compose, each action may be associated with exactly one convention. More specific conventions (detailed below) take precedence over less specific ones. The selection is non-deterministic when two or more conventions of the same priority apply to an action. The following options exist to apply a convention to an action, from the most specific to the least specific: | ||
|
||
1. `Microsoft.AspNetCore.Mvc.ApiConventionMethodAttribute` — Applies to individual actions and specifies the convention type and the convention method that applies. In the following sample, the convention method `Microsoft.AspNetCore.Mvc.DefaultApiConventions.Put` is applied to the `Update` action: | ||
|
||
[!code-csharp[](conventions/sample/Controllers/ContactsConventionController.cs?name=apiconventionmethod&highlight=2-3)] | ||
|
||
1. `Microsoft.AspNetCore.Mvc.ApiConventionTypeAttribute` applied to a controller — Applies the convention type to all actions on the controller. Convention methods are decorated with hints that determine which actions it would apply to (details as part of authoring conventions). For example: | ||
|
||
[!code-csharp[](conventions/sample/Controllers/ContactsConventionController.cs?name=apiconventiontypeattribute)] | ||
|
||
1. `Microsoft.AspNetCore.Mvc.ApiConventionTypeAttribute` applied to an assembly — Applies the convention type to all controllers in the current assembly. For example: | ||
|
||
[!code-csharp[](conventions/sample/Startup.cs?name=apiconventiontypeattribute)] | ||
|
||
## Create web API conventions | ||
|
||
A convention is a static type with methods. These methods are annotated with `[ProducesResponseType]` or `[ProducesDefaultResponseType]` attributes. | ||
|
||
```csharp | ||
public static class MyAppConventions | ||
{ | ||
[ProducesResponseType(200)] | ||
[ProducesResponseType(404)] | ||
public static void Find(int id) | ||
{ | ||
} | ||
} | ||
``` | ||
|
||
Applying this convention to an assembly results in the convention method applying to any action with the name `Find` and having exactly one parameter named `id`, as long as they don't have other more specific metadata attributes. | ||
|
||
In addition to `[ProducesResponseType]` and `[ProducesDefaultResponseType]`, `[ApiConventionNameMatch]` and `[ApiConventionTypeMatch]` can be applied to the convention method that determines the methods they apply to. For example: | ||
|
||
```csharp | ||
[ProducesResponseType(200)] | ||
[ProducesResponseType(404)] | ||
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Prefix)] | ||
public static void Find( | ||
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Suffix)] | ||
int id) | ||
{ } | ||
``` | ||
|
||
* The `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionNameMatchBehavior.Prefix` option applied to the method, indicates that the convention can match any action as long as it's prefixed with "Find". This includes methods such as `Find`, `FindPet`, or `FindById`. | ||
* The `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionNameMatchBehavior.Suffix` applied to the parameter indicates that the convention can match methods with exactly one parameter ending in the suffix identifier. This includes parameters such as `id` or `petId`. `ApiConventionTypeMatch` can be similarly applied to types to constrain the type of the parameter. A `params[]` argument can be used to indicate remaining parameters that don't need to be explicitly matched. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions
13
aspnetcore/web-api/advanced/conventions/sample/ApiConventions.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netcoreapp2.2</TargetFramework> | ||
<RuntimeFrameworkVersion>2.2.0-preview3-27014-02</RuntimeFrameworkVersion> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0-preview3-35497" /> | ||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Api.Analyzers" PrivateAssets="All" Version="2.2.0-preview3-35497" /> | ||
</ItemGroup> | ||
|
||
</Project> |
87 changes: 87 additions & 0 deletions
87
aspnetcore/web-api/advanced/conventions/sample/Controllers/ContactsController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Mvc; | ||
using ApiConventions.Models; | ||
using Microsoft.AspNetCore.Http; | ||
|
||
namespace ApiConventions.Controllers | ||
{ | ||
[ApiController] | ||
[Route("api/[controller]")] | ||
public class ContactsController : Controller | ||
{ | ||
public ContactsController(IContactRepository contacts) | ||
{ | ||
Contacts = contacts; | ||
} | ||
public IContactRepository Contacts { get; set; } | ||
|
||
|
||
// GET api/contacts | ||
[HttpGet] | ||
public IEnumerable<Contact> Get() | ||
{ | ||
return Contacts.GetAll(); | ||
} | ||
|
||
#region missing404docs | ||
// GET api/contacts/{guid} | ||
[HttpGet("{id}")] | ||
[ProducesResponseType(typeof(Contact), StatusCodes.Status200OK)] | ||
public IActionResult Get(string id) | ||
{ | ||
var contact = Contacts.Get(id); | ||
if (contact == null) | ||
{ | ||
return NotFound(); | ||
} | ||
return Ok(contact); | ||
} | ||
#endregion | ||
|
||
// POST api/contacts | ||
[HttpPost] | ||
public IActionResult Post(Contact contact) | ||
{ | ||
if (ModelState.IsValid) | ||
{ | ||
Contacts.Add(contact); | ||
return CreatedAtRoute("Get", new { id = contact.ID }, contact); | ||
} | ||
return BadRequest(); | ||
} | ||
|
||
// PUT api/contacts/{guid} | ||
[HttpPut("{id}")] | ||
public IActionResult Put(string id, Contact contact) | ||
{ | ||
if (ModelState.IsValid && id == contact.ID) | ||
{ | ||
var contactToUpdate = Contacts.Get(id); | ||
if (contactToUpdate != null) | ||
{ | ||
Contacts.Update(contact); | ||
return new NoContentResult(); | ||
} | ||
return NotFound(); | ||
} | ||
return BadRequest(); | ||
} | ||
|
||
// DELETE api/contacts/{guid} | ||
[HttpDelete("{id}")] | ||
public IActionResult Delete(string id) | ||
{ | ||
var contact = Contacts.Get(id); | ||
if (contact == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
Contacts.Remove(id); | ||
return NoContent(); | ||
} | ||
} | ||
} |
83 changes: 83 additions & 0 deletions
83
aspnetcore/web-api/advanced/conventions/sample/Controllers/ContactsConventionController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Mvc; | ||
using ApiConventions.Models; | ||
using Microsoft.AspNetCore.Http; | ||
|
||
namespace ApiConventions.Controllers | ||
{ | ||
[ApiController] | ||
#region apiconventiontypeattribute | ||
[ApiConventionType(typeof(DefaultApiConvention))] | ||
#endregion | ||
[Route("api/[controller]")] | ||
public class ContactsConventionController : Controller | ||
{ | ||
public ContactsConventionController(IContactRepository contacts) | ||
{ | ||
Contacts = contacts; | ||
} | ||
public IContactRepository Contacts { get; set; } | ||
|
||
|
||
// GET api/contacts | ||
[HttpGet] | ||
public IEnumerable<Contact> Get() | ||
{ | ||
return Contacts.GetAll(); | ||
} | ||
|
||
// GET api/contacts/{guid} | ||
[HttpGet("{id}")] | ||
public ActionResult<Contact> Get(string id) | ||
{ | ||
var contact = Contacts.Get(id); | ||
if (contact == null) | ||
{ | ||
return NotFound(); | ||
} | ||
return Ok(contact); | ||
} | ||
|
||
// POST api/contacts | ||
[HttpPost] | ||
public IActionResult Post(Contact contact) | ||
{ | ||
Contacts.Add(contact); | ||
return CreatedAtRoute("Get", new { id = contact.ID }, contact); | ||
} | ||
|
||
#region apiconventionmethod | ||
// PUT api/contacts/{guid} | ||
[HttpPut("{id}")] | ||
[ApiConventionMethod(typeof(DefaultApiConventions), nameof(DefaultApiConventions.Put))] | ||
public IActionResult Update(string id, Contact contact) | ||
{ | ||
var contactToUpdate = Contacts.Get(id); | ||
if (contactToUpdate == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
Contacts.Update(contact); | ||
return new NoContentResult(); | ||
} | ||
#endregion | ||
|
||
// DELETE api/contacts/{guid} | ||
[HttpDelete("{id}")] | ||
public IActionResult Delete(string id) | ||
{ | ||
var contact = Contacts.Get(id); | ||
if (contact == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
Contacts.Remove(id); | ||
return NoContent(); | ||
} | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
aspnetcore/web-api/advanced/conventions/sample/Models/Contact.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
namespace ApiConventions.Models | ||
{ | ||
public class Contact | ||
{ | ||
public string ID { get; set; } | ||
public string FirstName { get; set; } | ||
public string LastName { get; set; } | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
aspnetcore/web-api/advanced/conventions/sample/Models/ContactRepository.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
namespace ApiConventions.Models | ||
{ | ||
public class ContactRepository : IContactRepository | ||
{ | ||
private static ConcurrentDictionary<string, Contact> _contacts = | ||
new ConcurrentDictionary<string, Contact>(); | ||
|
||
public ContactRepository() | ||
{ | ||
Add(new Contact() { FirstName = "Nancy", LastName = "Davolio" }); | ||
} | ||
|
||
public void Add(Contact contact) | ||
{ | ||
contact.ID = Guid.NewGuid().ToString(); | ||
_contacts[contact.ID] = contact; | ||
} | ||
|
||
public Contact Get(string id) | ||
{ | ||
Contact contact; | ||
_contacts.TryGetValue(id, out contact); | ||
return contact; | ||
} | ||
|
||
public IEnumerable<Contact> GetAll() | ||
{ | ||
return _contacts.Values; | ||
} | ||
|
||
public Contact Remove(string id) | ||
{ | ||
Contact contact; | ||
_contacts.TryRemove(id, out contact); | ||
return contact; | ||
} | ||
|
||
public void Update(Contact contact) | ||
{ | ||
_contacts[contact.ID] = contact; | ||
} | ||
} | ||
} |
Oops, something went wrong.