【ASP.NET Web API教程】2.4 创建Web API的帮助页面

简介: 原文:【ASP.NET Web API教程】2.4 创建Web API的帮助页面注:本文是【ASP.NET Web API系列教程】的一部分,如果您是第一次看本博客文章,请先看前面的内容。 2.4 Creating a Help Page for a Web API 2.
原文: 【ASP.NET Web API教程】2.4 创建Web API的帮助页面

注:本文是【ASP.NET Web API系列教程】的一部分,如果您是第一次看本博客文章,请先看前面的内容。

2.4 Creating a Help Page for a Web API
2.4 创建Web API帮助页面

本文引自:http://www.asp.net/web-api/overview/creating-web-apis/creating-a-help-page-for-a-web-api

By Mike Wasson | August 3, 2012
作者:Mike Wasson | 日期:2012-8-3

This tutorial shows how to create a help page for a web API, by using the ApiExplorer class.
本教程展示如何运用ApiExplorer类为Web API创建帮助页面。

The ApiExplorer class provides descriptive information about the APIs exposed by a web API. ApiExplorer provides the raw material that you can use to create a help page. The ApiExplorer contains an ApiDescription collection, one for each API that it discovers in your project. For this purpose, an "API" is defined as the combination of HTTP method and relative URI. For example, here are some distinct APIs:
ApiExplorer类对Web API所暴露的每个API提供了描述信息。(因此,)ApiExplorer提供了可以用来创建帮助页面的原始材料。ApiExplorer含有一个ApiDescription集合,一个在你项目中发现的每个API的集合。为此,所谓一个“API”的定义是一个HTTP方法与相关URI的结合。例如,以下是一些不同的API:

  • GET /api/Products(HTTP方法是GET,URI是/api/Products,两者的结合便是一个API。下同 — 译者注)
  • GET /api/Products/{id}
  • POST /api/Products

If a single controller action supports multiple HTTP methods, the ApiExplorer treats each as a distinct API.
如果一个单一的控制器动作支持多个HTTP方法,ApiExplorer会把每一个都作为不同的API看待。

For this tutorial, we will create the help page as an MVC view, using Razor syntax to render the HTML. First, create a new project using the "Web API" project template.
对于本教程,我们将把帮助页面创建成一个MVC视图,用Razor语法来渲染HTML。首先用“Web API”项目模板创建一个新项目(如图2-27)。

WebAPI2-27

图2-27. 创建项目

This template creates a project that contains a Web API controller (ValuesController.cs) and an MVC controller (HomeController.cs).
这个模板会创建含有一个Web API控制器(ValuesController.cs)和一个MVC控制器(HomeController.cs)的项目。

Add a model class:
添加一个模型类:

namespace HelpDemo.Models 
{ 
    public class Product 
    { 
        public string Name { get; set; } 
        public decimal Price { get; set; } 
    } 
}

Add another Web API controller:
添加另一个Web API控制器:

namespace HelpDemo.Controllers 
{ 
    using System.Collections.Generic; 
    using System.Net; 
    using System.Net.Http; 
    using System.Web.Http; 
    using HelpDemo.Models; 
    public class ProductsController : ApiController 
    { 
        public IEnumerable<Product> Get() 
        { 
            return new Product[0]; 
        } 
        public HttpResponseMessage Get(int id) 
        { 
            return Request.CreateResponse(HttpStatusCode.NotFound); 
        } 
        public void Post(Product value) { } 
        public void Put(int id, Product value) { } 
    } 
}

This controller is not really functional, and you don't have to use this exact code. This purpose of this controller is just to give the ApiExplorer something to consume.
这个控制器并不是真正功能性的,而且你不必精确使用这些代码。这个控制器的目的只是为ApiExplorer提供一些可供使用的东西。(这里意在说明,在一个实际应用程序中,可能需要一个类似于这样的控制器,但其内容(代码)需酌情而定 — 译者注)

Next, we'll create a view model that gets data from the ApiExplorer. We could pass the ApiExplorer object directly to the MVC view. However, encapsulating the ApiExplorer in a model gives us more flexibility to manipulate the data.
下一步,我们将创建一个从ApiExplorer获取数据的视图模型,然后可以把ApiExplorer对象直接传递给MVC视图。然而,把ApiExplorer封装在一个模型中,可以让我们能够更灵活性地维护数据。

namespace HelpDemo.Models 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web.Http.Controllers; 
    using System.Web.Http.Description; 
    public class ApiModel 
    { 
        IApiExplorer _explorer; 
        public ApiModel(IApiExplorer explorer) 
        { 
            if (explorer == null) 
            { 
                throw new ArgumentNullException("explorer"); 
            } 
            _explorer = explorer; 
        } 
        public ILookup<string, ApiDescription> GetApis() 
        { 
            return _explorer.ApiDescriptions.ToLookup( 
                api => api.ActionDescriptor.ControllerDescriptor.ControllerName); 
        } 
    } 
}

The GetApis method converts the collection into an ILookup, grouped by controller name. That makes it easy to group the help page by controller.
GetApis方法将集合转换成一个按控制器名称进行分组的ILookup。这样便于按控制器对帮助页面进行分组。

Open the source file for the MVC controller, HomeController.cs. Add an action to render the help page:
打开MVC控制器源文件HomeController.cs。添加一个渲染帮助页面的动作:

public ActionResult Help() 
{ 
    var explorer = GlobalConfiguration.Configuration.Services.GetApiExplorer(); 
    return View(new ApiModel(explorer)); 
}

Add a view for the Help action:
为这个Help动作添加一个视图:

@model HelpDemo.Models.ApiModel 
@{ 
    ViewBag.Title = "API Help"; 
} 
@section Scripts 
{ 
    @Scripts.Render("~/bundles/jqueryui") 
    <script type="text/javascript"> 
        // Apply jQuery accordion widget.
        // 运用jQuery的可折叠部件
        $(function () { $(".accordion").accordion(); }); 
        </script> 
} 
<div id="body" class="content-wrapper"> 
<h2>API Help</h2> 
@foreach (var group in Model.GetApis()) 
{ 
    <h3>@group.Key</h3> 
    <div class="accordion"> 
    @foreach (var api in group) 
    { 
        <h4><a href="#">@api.HttpMethod @api.RelativePath</a></h4> 
        <div> 
        @foreach (var param in api.ParameterDescriptions) 
        { 
            <p>Parameter: <em>@param.Name</em> (@param.Source)</p> 
        } 
        </div> 
    } 
    </div> 
} 
</div>

If you run the application and navigate to /home/help, it should look similar to the following:
如果运行这个应用程序,并导航到/home/help,页面看上去与下图类似(见图2-28):

WebAPI2-28

图2-28. 帮助页面外观

Adding a Documentation Provider
添加文档提供器

You can provide documentation for your APIs by implementing the IDocumentationProvider interface. Documentation strings can come from any source that you like. For this example, we will define custom attributes that can be applied to the controller. The documentation provider will grab documentation strings from the attributes.
通过实现IDocumentationProvider接口,你可以提供API的文档。文档字符串(用来作为文档内容的字符串 — 译者注)可以是你所喜欢的任何资源(这些资源当然是关于一个API的东西,比如,该API的作用或含义的描述,有哪些参数,这些参数的类型及其作用等等 — 译者注)。对于本例,我们将定义能够运用于控制器的一些自定义注解属性。文档提供器将根据这些注解属性捕获文档字符串(根据注解属性获取关于API的有关内容,并把这些内容送入文档字符串中,以便在帮助页面中显示出来 — 译者注)。

For another approach, see Yao Huang Lin's blog post Generating a Web API help page using ApiExplorer. He shows a documentation provider that pulls from XML documentation comments.
另一种办法参见Yao Huang Lin的博客文章“Generating a Web API help page using ApiExplorer(用ApiExplorer生成一个Web API帮助页面)”。他演示了从XML文档注释进行采集的一个文档提供器。

Here are the custom attributes:
以下是自定义注解属性:

[AttributeUsage(AttributeTargets.Method)] 
public class ApiDocAttribute : Attribute 
{ 
    public ApiDocAttribute(string doc) 
    { 
        Documentation = doc; 
    } 
    public string Documentation { get; set; } 
} 
[AttributeUsage(AttributeTargets.Method)] 
public class ApiParameterDocAttribute : Attribute 
{ 
    public ApiParameterDocAttribute(string param, string doc) 
    { 
        Parameter = param; 
        Documentation = doc; 
    } 
    public string Parameter { get; set; } 
    public string Documentation { get; set; } 
}

Here is a controller method with the attributes:
以下是使用这些注解属性的一个控制器方法:

[ApiDoc("Gets a product by ID.")] 
[ApiParameterDoc("id", "The ID of the product.")] 
public HttpResponseMessage Get(int id) 
{ 
    // ... 
}

Now add a class that implements IDocumentationProvider.
现在,添加一个实现IDocumentationProvider的类:

public class DocProvider : IDocumentationProvider 
{ 
    public string GetDocumentation(HttpParameterDescriptor parameterDescriptor) 
    { 
        string doc = ""; 
        var attr = parameterDescriptor.ActionDescriptor 
                    .GetCustomAttributes<ApiParameterDocAttribute>() 
                    .Where(p => p.Parameter == parameterDescriptor.ParameterName) 
                    .FirstOrDefault(); 
        if (attr != null) 
        { 
            doc = attr.Documentation; 
        } 
        return doc; 
    } 
    public string GetDocumentation(HttpActionDescriptor actionDescriptor) 
    { 
        string doc = ""; 
        var attr = actionDescriptor.GetCustomAttributes<ApiDocAttribute>().FirstOrDefault(); 
        if (attr != null) 
        { 
            doc = attr.Documentation; 
        } 
        return doc; 
    } 
}

Open the Global.asax.cs file and add the following code to the Application_Start method:
打开Global.asax.cs文件,并将以下代码添加到Application_Start方法:

GlobalConfiguration.Configuration.Services.Replace(
    typeof(IDocumentationProvider), new DocProvider());

ApiExplorer automatically calls into the IDocumentationProvider interface to get documentation strings for each API. It stores them in the Documentation property of the ApiDescription and ApiParameterDescription objects. The MVC view can access them as follows:
ApiExplorer会自动调用IDocumentationProvider接口,以获取每个API的文档字符串。把它们存储到ApiDescriptionApiParameterDescription对象的Documentation属性。MVC视图像下面这样访问它们:

@foreach (var api in group) 
{ 
    <h4><a href="#">@api.HttpMethod @api.RelativePath</a></h4> 
    <div><p>@api.Documentation</p> 
    <ul> 
    @foreach (var param in api.ParameterDescriptions) 
    {    
        <li><em>@param.Name</em> (@param.Source): @param.Documentation</li> 
    } 
    </ul> 
    </div> 
}

Now when you render the view, it shows the documentation strings:
现在,当渲染这个视图时,便会显示出文档字符串(见图2-29):

WebAPI2-29

图2-29. 显示了文档字符串的帮助页面

Providing Sample Response Bodies
提供例子响应体

One thing that's missing from our help page is examples of the HTTP response body. The ApiExplorer class does not provide any direct support for this. However, it does give you the return type for each action. If the action returns a POCO, we can use this information to create an example response body, as follows:
上述帮助页面缺少的一项内容是HTTP响应体的示例。ApiExplorer类对此未提供任何直接支持。然而,它可以为你提供每个动作的返回类型。如果动作返回的是一个POCO,我们可以运用这个信息来创建一个例子响应体,步骤如下:

  1. 1.
  2. Look up an example instance of the POCO.
    查找一个POCO例子实例。 2.
  3. Use a media-type formatter to serialize the example instance.
    使用一个媒体类型格式化器序列化此例子实例。 3.
  4. Display the result as a string.
    将结果以字符串显示出来。

To see how this can work, add the following code to the ApiModel class:
要明白如何做,添加以下代码到ApiModel类:

// Example instances 
// 例子实例
static Product[] _products = new Product[] 
{ 
    new Product() { Name = "Gizmo", Price = 1.05M }, 
    new Product() { Name = "Gizmo2", Price = 0.995M } 
}; 
// Look-up table based on data type. 
// 基于数据类型查询表
Dictionary<Type, object> _sampleData = new Dictionary<Type, object>() { 
    { typeof(Product), _products[0] }, 
    { typeof(IEnumerable<Product>), _products } 
}; 
Type GetResponseType(HttpActionDescriptor action) 
{ 
    return action.ReturnType; 
} 
public string GetSampleResponseBody(ApiDescription api, string mediaType) 
{ 
    string body = null; 
    Type returnType = GetResponseType(api.ActionDescriptor); 
    object o; 
    if (returnType != null && _sampleData.TryGetValue(returnType, out o)) 
    { 
        var formatters = api.SupportedResponseFormatters; 
        MediaTypeFormatter formatter = formatters.FirstOrDefault( 
            f => f.SupportedMediaTypes.Any(m => m.MediaType == mediaType)); 
        if (formatter != null) 
        { 
            var content = new ObjectContent(returnType, o, formatter); 
            body = content.ReadAsStringAsync().Result; 
        } 
    } 
    return body; 
}

Add the following code to the MVC view:
将以下代码添加到MVC视图:

    @{  
        string response = @Model.GetSampleResponseBody(api, "application/json"); 
    } 
    @if (response != null) { 
        <p>Sample response body:</p> 
        <p><code>@Model.GetSampleResponseBody(api, "application/json")</code></p> 
    }

Here is the resulting help page:
以下是帮助页面的结果(见图2-30):

WebAPI2-30

图2-30. 显示了示例的帮助页面

This approach is not perfect. If an action returns an HttpResponseMessage, there is no way to deduce the format of the message body from the static API description. The same is true for an action that returns loosely-structure JSON (see Anonymous and Weakly-Typed Objects).
这种办法不太完美。如果一个动作返回HttpResponseMessage,则没有办法根据静态API描述来推断该消息体的格式。同样,返回松散结构JSON的动作也是这样(参见Anonymous and Weakly-Typed Objects(匿名类型与弱类型对象) — 本系列教程的第6章)。

One way to work around this problem is to use the API ID to look up the response type. The API ID is a concatenation of the HTTP method and the relative URI path (for example, "GETapi/Products/{id}").
解决这一问题的一种办法是使用API ID来查找响应体类型。API ID是HTTP方法与相对URI路径的串联(例如,“GETapi/Products/{id}”)。

// Response types 
// 响应类型
static Dictionary<string, Type> _responseTypes = new Dictionary<string, Type>() 
    { 
        { @"GETapi/Products/{id}", typeof(Product) } 
    }; 
Type GetResponseType(ApiDescription api) 
{ 
    Type t; 
    if (_responseTypes.TryGetValue(api.ID, out t)) 
    { 
        return t; 
    } 
    return api.ActionDescriptor.ReturnType; 
}

Custom attributes are another option.
自定义注解属性是(针对这一问题的)另一种选择。

Excluding an API
排除一个API

To hide an API from the ApiExplorer, add the ApiExplorerSettings attribute to the action and set IgnoreApi to true.
为了从ApiExplorer中隐藏一个API,将ApiExplorerSettings注解属性添加到该动作,并将IgnoreApi设置为true:

[ApiExplorerSettings(IgnoreApi=true)] 
public HttpResponseMessage Get(int id) 
{ 
}

You can also add this attribute to the controller, to exclude the entire controller.
你也可以把这个注解属性添加到控制器,以排除整个控制器(的所有API)。

看完此文如果觉得有所收获,恳请给个推荐

目录
相关文章
|
13天前
|
安全 API 开发者
Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
在当前的Web开发中,Python因能构建高效简洁的RESTful API而备受青睐,大大提升了开发效率和用户体验。本文将介绍RESTful API的基本原则及其在Python中的实现方法。以Flask为例,演示了如何通过不同的HTTP方法(如GET、POST、PUT、DELETE)来创建、读取、更新和删除用户信息。此示例还包括了基本的路由设置及操作,为开发者提供了清晰的API交互指南。
55 6
|
12天前
|
存储 JSON API
实战派教程!Python Web开发中RESTful API的设计哲学与实现技巧,一网打尽!
在数字化时代,Web API成为连接前后端及构建复杂应用的关键。RESTful API因简洁直观而广受欢迎。本文通过实战案例,介绍Python Web开发中的RESTful API设计哲学与技巧,包括使用Flask框架构建一个图书管理系统的API,涵盖资源定义、请求响应设计及实现示例。通过准确使用HTTP状态码、版本控制、错误处理及文档化等技巧,帮助你深入理解RESTful API的设计与实现。希望本文能助力你的API设计之旅。
36 3
|
13天前
|
JSON API 数据库
从零到英雄?一篇文章带你搞定Python Web开发中的RESTful API实现!
在Python的Web开发领域中,RESTful API是核心技能之一。本教程将从零开始,通过实战案例教你如何使用Flask框架搭建RESTful API。首先确保已安装Python和Flask,接着通过创建一个简单的用户管理系统,逐步实现用户信息的增删改查(CRUD)操作。我们将定义路由并处理HTTP请求,最终构建出功能完整的Web服务。无论是初学者还是有经验的开发者,都能从中受益,迈出成为Web开发高手的重要一步。
36 4
|
11天前
|
开发框架 JSON 缓存
震撼发布!Python Web开发框架下的RESTful API设计全攻略,让数据交互更自由!
在数字化浪潮推动下,RESTful API成为Web开发中不可或缺的部分。本文详细介绍了在Python环境下如何设计并实现高效、可扩展的RESTful API,涵盖框架选择、资源定义、HTTP方法应用及响应格式设计等内容,并提供了基于Flask的示例代码。此外,还讨论了版本控制、文档化、安全性和性能优化等最佳实践,帮助开发者实现更流畅的数据交互体验。
32 1
|
13天前
|
JSON API 开发者
惊!Python Web开发新纪元,RESTful API设计竟能如此性感撩人?
在这个Python Web开发的新纪元里,RESTful API的设计已经超越了简单的技术实现,成为了一种追求极致用户体验和开发者友好的艺术表达。通过优雅的URL设计、合理的HTTP状态码使用、清晰的错误处理、灵活的版本控制以及严格的安全性措施,我们能够让RESTful API变得更加“性感撩人”,为Web应用注入新的活力与魅力。
30 3
|
15天前
|
JSON API 数据格式
深度剖析!Python Web 开发中 RESTful API 的每一个细节,你不可不知的秘密!
在 Python Web 开发中,RESTful API 是构建强大应用的关键,基于 Representational State Transfer 架构风格,利用 HTTP 卞性能。通过 GET、POST、PUT 和 DELETE 方法分别实现资源的读取、创建、更新和删除操作。示例代码展示了如何使用 Flask 路由处理这些请求,并强调了状态码的正确使用,如 200 表示成功,404 表示未找到资源等。
38 5
|
2月前
|
存储 消息中间件 前端开发
Web2py框架下的神秘力量:如何轻松集成第三方API,让你的应用不再孤单!
【8月更文挑战第31天】在开发现代Web应用时,常需集成第三方服务如支付网关、数据存储等。本文将指导你使用Web2py框架无缝接入第三方API。通过实例演示从注册获取API密钥、创建控制器、发送HTTP请求到处理响应的全过程。利用`requests`库与Web2py的内置功能,轻松实现API交互。文章详细介绍了如何编写RESTful控制器,处理API请求及响应,确保数据安全传输。通过本教程,你将学会如何高效整合第三方服务,拓展应用功能。欢迎留言交流心得与建议。
37 1
|
2月前
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
68 0
|
2月前
|
Java 缓存 数据库连接
揭秘!Struts 2性能翻倍的秘诀:不可思议的优化技巧大公开
【8月更文挑战第31天】《Struts 2性能优化技巧》介绍了提升Struts 2 Web应用响应速度的关键策略,包括减少配置开销、优化Action处理、合理使用拦截器、精简标签库使用、改进数据访问方式、利用缓存机制以及浏览器与网络层面的优化。通过实施这些技巧,如懒加载配置、异步请求处理、高效数据库连接管理和启用GZIP压缩等,可显著提高应用性能,为用户提供更快的体验。性能优化需根据实际场景持续调整。
49 0
|
2月前
|
JSON API 数据库
探索FastAPI:不仅仅是一个Python Web框架,更是助力开发者高效构建现代化RESTful API服务的神器——从环境搭建到CRUD应用实战全面解析
【8月更文挑战第31天】FastAPI 是一个基于 Python 3.6+ 类型提示标准的现代 Web 框架,以其高性能、易用性和现代化设计而备受青睐。本文通过示例介绍了 FastAPI 的优势及其在构建高效 Web 应用中的强大功能。首先,通过安装 FastAPI 和 Uvicorn 并创建简单的“Hello, World!”应用入门;接着展示了如何处理路径参数和查询参数,并利用类型提示进行数据验证和转换。
42 0
下一篇
无影云桌面