标签:
现在使用WebAPI来作为实现企业服务化的需求非常常见,不可否认它也是很便于使用的,基于注释可以生成对应的帮助文档(Microsoft.AspNet.WebApi.HelpPage),但是比较便利和可持久化的调试官方却没有相应的集成,虽然我们可以使 用诸如Fiddler、Swagger、PostMan、及其他手写代码的方式等等来调试我们的WebAPI,但是却依然不是很方便,对于公司来说也需要有一种可以统一、可持久化、且行之有效的规范。
调试接口我希望他能达到以下3点:
1:可根据接口定义生成测试数据。
2:测试数据可持久化,便于持续迭代。
3:测试数据可共享。文本主要介绍如何利用PostMan实现这3点。
目前所知道的调试方式有:
1:耳熟能详的Fiddler就不说了,功能非常强大,但不是我们想要的。
2:PostMan,使用方便且满足上面的2和3,这是一个谷歌插件(地址在这),也有App版本(https://www.getpostman.com/)推荐。
3:Swagger,已有人将其结合SwaggerUI集成到WebAPI中,Nuget上安装
- install-package Swashbuckle
即可,项目地址https://github.com/domaindrivendev/Swashbuckle。
4:手写HttpClient来实现,其他的还有https://github.com/wuchang/WebApiTestClient。
以上这几种方法比较推荐的自然是PostMan。
我们先来看看使用PosMan的一些基本操作。
如下所示,我们定义了几个简单的方法来作为我们调试的接口。
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web.Http;
- using WebAPI2PostMan.Models;
- namespace WebAPI2PostMan.Controllers
- {
- /// <summary>
- /// 产品服务
- /// </summary>
- [RoutePrefix("Product")]
- public class ProductController : ApiController
- {
- private static readonly List<Product> Products = new List<Product>
- {
- new Product{Id = Guid.NewGuid(), Description = "产品描述",Name = "产品名称",Price = 123},
- new Product{Id = Guid.NewGuid(), Description = "产品描述",Name = "产品名称",Price = 124},
- new Product{Id = Guid.NewGuid(), Description = "产品描述",Name = "产品名称",Price = 125},
- new Product{Id = Guid.NewGuid(), Description = "产品描述",Name = "产品名称",Price = 126}
- };
- /// <summary>
- /// 获取所有产品
- /// </summary>
- [HttpGet, Route("All")]
- public IEnumerable<Product> Get()
- {
- return Products;
- }
- /// <summary>
- /// 获取产品
- /// </summary>
- /// <param name="id">产品编号</param>
- [HttpGet, Route("{id}")]
- public string Get(Guid id)
- {
- return "value";
- }
- /// <summary>
- /// 添加产品
- /// </summary>
- /// <param name="request">产品请求</param>
- [HttpPost, Route("")]
- public string Post(Product request)
- {
- Products.Add(request);
- return "ok";
- }
- /// <summary>
- /// 编辑产品
- /// </summary>
- /// <param name="id">产品编号</param>
- /// <param name="request">编辑后的产品</param>
- [HttpPut, Route("{id}")]
- public void Put(int id, Product request)
- {
- }
- /// <summary>
- /// 删除产品
- /// </summary>
- /// <param name="id">产品编号</param>
- [HttpDelete, Route("{id}")]
- public string Delete(Guid id)
- {
- var model = Products.FirstOrDefault(x => x.Id.Equals(id));
- Products.Remove(model);
- var result = string.Format("编号为{0}的产品删除成功!", id);
- return result;
- }
- }
- }
在Nuget里添加了Microsoft.AspNet.WebApi.HelpPage之后生成的帮助文档如下图。
接下来,我们使用PostMan来调试我们定义的接口。在这里我使用插件版的PostMan作为演示。
获取所有产品这种其实直接使用浏览器访问就可以达到调试的目的,但是若有特殊Header或身份验证时就不太方便了,如下在PostMan中输入对应地址点击【Send】即可看到返回的数据及消耗的时间和HttpStatus等。
对于我们常用的我们可以点击Add to collection将其加入到Collections中便于下次测试。
接下来,我们对新增产品添加调试。
其余的类似,请求的方法类型与Http请求类型一致。
那么,对于参数较多的接口时第一次添加参数是比较繁琐的,所以我希望能有根据接口定义生成出可以导入到PostMan中的方法,分析Postman下载出来的数据格式可见其实就是一个Json格式的文件。
那既然是Json格式的文件,我们就可以根据它所需要的格式生成。首先我们定义出需要的类,并没有包含全部的属性,APP版本有一些是否同步等属性并没有加进来,有兴趣的朋友可以研究一下。
- public class PostmanCollection
- {
- public string id { get; set; }
- public string name { get; set; }
- public string description { get; set; }
- public List<string> order { get; set; }
- public long timestamp { get; set; }
- public List<PostmanRequest> requests { get; set; }
- }
- public class PostmanRequest
- {
- public string collection { get; set; }
- public string id { get; set; }
- public string name { get; set; }
- public string dataMode { get; set; }
- public List<PostmanData> data { get; set; }
- public string description { get; set; }
- public string descriptionFormat { get; set; }
- public string headers { get; set; }
- public string method { get; set; }
- public Dictionary<string, string> pathVariables { get; set; }
- public string url { get; set; }
- public int version { get; set; }
- public string collectionId { get; set; }
- }
- public class PostmanData
- {
- public string key { get; set; }
- public string value { get; set; }
- public string type {
- get { return "text"; }
- }
- public bool enabled {
- get { return true; }
- }
- }
PostMan支持从地址导入,所以我们可以定义个PostManController要根据接口定义来生成我们的Json数据。
- using System.Collections.Generic;
- using System.Linq;
- using System.Web.Http;
- using System.Web.Http.Description;
- using System.Web.Http.Results;
- using Newtonsoft.Json;
- using WebAPI2PostMan.Areas.HelpPage;
- using WebAPI2PostMan.Models;
- namespace WebAPI2PostMan.Controllers
- {
- /// <summary>
- ///
- /// </summary>
- [RoutePrefix("PostMan")]
- public class PostManController : ApiController
- {
- private const string Host = "http://localhost:11488/";
- /// <summary>
- /// 获取PostMan集合
- /// </summary>
- /// <returns></returns>
- [Route("")]
- public JsonResult<PostmanCollection> GetPostmanCollection()
- {
- var collectionId = PostMan.GetId();
- var apis = Configuration.Services.GetApiExplorer().ApiDescriptions.Where(x => x.Documentation != null);
- var requests = GetPostmanRequests(apis, collectionId);
- var collection = new PostmanCollection
- {
- id = collectionId,
- name = "WebAPI2PostMan",
- description = "",
- order = requests.Select(x => x.id).ToList(),
- timestamp = 0,
- requests = requests
- };
- return Json(collection);
- }
- private List<PostmanRequest> GetPostmanRequests(IEnumerable<ApiDescription> apis, string collectionId)
- {
- return apis.Select(api => new PostmanRequest
- {
- collection = collectionId,
- id = PostMan.GetId(),
- name = api.Documentation,
- dataMode = "urlencoded",
- data = GetPostmanDatas(api),
- description = "",
- descriptionFormat = "html",
- headers = "",
- method = api.HttpMethod.Method,
- pathVariables = new Dictionary<string, string>(),
- url = Host + api.RelativePath,
- version = 2,
- collectionId = collectionId
- }).ToList();
- }
- private List<PostmanData> GetPostmanDatas(ApiDescription api)
- {
- var postmandatas = new List<PostmanData>();
- var apiModel = Configuration.GetHelpPageApiModel(api.GetFriendlyId());
- var raw = apiModel.SampleRequests.Values.FirstOrDefault();
- if (raw == null) return postmandatas;
- var pdata = JsonConvert.DeserializeObject<Dictionary<string,string>>(raw.ToString());
- postmandatas.AddRange(pdata.Select(model => new PostmanData {key = model.Key, value = model.Value}));
- return postmandatas;
- }
- }
- }
主要生成代码就是获取所有接口和接口定义的参数。值得一提的是,我们可以借助Microsoft.AspNet.WebApi.HelpPage来获取SampleRequests,从而使用SampleRequests来填充我们的测试数据。
运行程序访问http://localhost:11488/PostMan 并将其导入到PostMan。
效果还是可以接受的,还有写可以拓展的地方,比如可以直接一键导入到PostMan程序中,用谷歌浏览器审查元素可以发现导入的方法是importCollectionFromUrl,在console中输入
- window.open("chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm/index.html");
- pm.collections.importCollectionFromUrl("http://localhost:11488/postman");
就可以达到一键导入的目的了。但是遗憾的是,必须要在插件内调用才有效,代码匆忙,还有很多地方可以继续拓展,不过本文的目的已经达到了。
标签:
原文地址:http://www.cnblogs.com/jamestuhao/p/4568282.html