Ultimate ASP.NET Core Web API 23 ROOT DOCUMENT

23 ROOT DOCUMENT
23 根文档

In this section, we are going to create a starting point for the consumers of our API. This starting point is also known as the Root Document. The Root Document is the place where consumers can learn how to interact with the rest of the API.‌
在本节中,我们将为 API 的使用者创建一个起点。此起点也称为根文档。根文档是使用者可以学习如何与 API 的其余部分进行交互的地方。

23.1 Root Document Implementation

23.1 根文档实现

This document should be created at the api root, so let’s start by creating‌ a new controller:
这个文档应该在 api 根目录下创建,所以让我们从创建一个新的控制器开始:

[Route("api")] [ApiController] public class RootController : ControllerBase { }

We are going to generate links towards the API actions. Therefore, we have to inject LinkGenerator:
我们将生成指向 API作的链接。因此,我们必须注入 LinkGenerator:

[Route("api")] [ApiController] public class RootController : ControllerBase { private readonly LinkGenerator _linkGenerator; public RootController(LinkGenerator linkGenerator) => _linkGenerator = linkGenerator; }

In this controller, we only need a single action, GetRoot, which will be executed with the GET request on the /api URI.
在此控制器中,我们只需要一个作 GetRoot,该作将使用 /api URI 上的 GET 请求执行。

There are several links that we are going to create in this action. The link to the document itself and links to actions available on the URIs at the root level (actions from the Companies controller). We are not creating links to employees, because they are children of the company — and in our API if we want to fetch employees, we have to fetch the company first.
我们将在此作中创建多个链接。指向文档本身的链接,以及指向根级别 URI 上可用作的链接(来自 Companies 控制器的作)。我们不会创建指向员工的链接,因为他们是公司的子公司 — 在我们的 API 中,如果我们想获取员工,我们必须先获取公司。

If we inspect our CompaniesController, we can see that GetCompanies and CreateCompany are the only actions on the root URI level (api/companies). Therefore, we are going to create links only to them.
如果我们检查 CompaniesController,我们可以看到 GetCompanies 和 CreateCompany 是根 URI 级别 (api/companies) 上的唯一作。因此,我们将仅创建指向它们的链接。

Before we start with the GetRoot action, let’s add a name for the CreateCompany and GetCompanies actions in the CompaniesController:
在开始 GetRoot作之前,让我们在 CompaniesController 中为 CreateCompany 和 GetCompanies作添加一个名称:

[HttpGet(Name = "GetCompanies")] public async Task<IActionResult> GetCompanies()
[HttpPost(Name = "CreateCompany")] [ServiceFilter(typeof(ValidationFilterAttribute))] public async Task<IActionResult> CreateCompany([FromBody]CompanyForCreationDto company)

We are going to use the Link class to generate links:
我们将使用 Link 类来生成链接:

public class Link { public string Href { get; set; } public string Rel { get; set; } public string Method { get; set; } … }

This class contains all the required properties to describe our actions while creating links in the GetRoot action. The Href property defines the URI to the action, the Rel property defines the identification of the action type, and the Method property defines which HTTP method should be used for that action.
此类包含描述 GetRoot作中创建链接时的作所需的所有属性。Href 属性定义作的 URI,Rel 属性定义作类型的标识,Method 属性定义应使用哪个 HTTP 方法执行该作。

Now, we can create the GetRoot action:
现在,我们可以创建 GetRoot作:

[HttpGet(Name = "GetRoot")] public IActionResult GetRoot([FromHeader(Name = "Accept")] string mediaType) { if(mediaType.Contains("application/vnd.codemaze.apiroot")) { var list = new List<Link> { new Link { Href = _linkGenerator.GetUriByName(HttpContext, nameof(GetRoot), new {}), Rel = "self", Method = "GET" }, new Link { Href = _linkGenerator.GetUriByName(HttpContext, "GetCompanies", new {}), Rel = "companies", Method = "GET" }, new Link{ Href = _linkGenerator.GetUriByName(HttpContext, "CreateCompany", new {}), Rel = "create_company", Method = "POST" } }; return Ok(list); } return NoContent(); }

In this action, we generate links only if a custom media type is provided from the Accept header. Otherwise, we return NoContent(). To generate links, we use the GetUriByName method from the LinkGenerator class.
在此作中,仅当 Accept 标头提供了自定义媒体类型时,我们才会生成链接。否则,我们将返回 NoContent()。要生成链接,我们使用 LinkGenerator 类中的 GetUriByName 方法。

That said, we have to register our custom media types for the json and xml formats. To do that, we are going to extend the AddCustomMediaTypes extension method:
也就是说,我们必须为 json 和 xml 格式注册自定义媒体类型。为此,我们将扩展 AddCustomMediaTypes 扩展方法:

public static void AddCustomMediaTypes(this IServiceCollection services) { services.Configure<MvcOptions>(config => { var systemTextJsonOutputFormatter = config.OutputFormatters .OfType<SystemTextJsonOutputFormatter>()?.FirstOrDefault(); if (systemTextJsonOutputFormatter != null) { systemTextJsonOutputFormatter.SupportedMediaTypes .Add("application/vnd.codemaze.hateoas+json"); systemTextJsonOutputFormatter.SupportedMediaTypes .Add("application/vnd.codemaze.apiroot+json"); } var xmlOutputFormatter = config.OutputFormatters .OfType<XmlDataContractSerializerOutputFormatter>()? .FirstOrDefault(); if (xmlOutputFormatter != null) { xmlOutputFormatter.SupportedMediaTypes .Add("application/vnd.codemaze.hateoas+xml"); xmlOutputFormatter.SupportedMediaTypes .Add("application/vnd.codemaze.apiroot+xml"); } }); }

We can now inspect our result:
我们现在可以检查我们的结果:
https://localhost:5001/api

alt text

This works great.
这效果很好。

Let’s test what is going to happen if we don’t provide the custom media type:
让我们测试一下如果不提供自定义媒体类型会发生什么情况:

https://localhost:5001/api

alt text

Well, we get the 204 No Content message as expected. Of course, you can test the xml request as well:
好吧,我们如预期的那样收到了 204 No Content 消息。当然,您也可以测试 xml 请求:

https://localhost:5001/api

alt text

Great.
伟大。

Now we can move on to the versioning chapter.
现在我们可以继续进行版本控制章节。

Leave a Reply

Your email address will not be published. Required fields are marked *