zoukankan      html  css  js  c++  java
  • WebAPI生成可导入到PostMan的数据

    一、前言

    现在使用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。

    三、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之后生成的帮助文档如下图。

    image

    接下来,我们使用PostMan来调试我们定义的接口。在这里我使用插件版的PostMan作为演示。

    获取所有产品这种其实直接使用浏览器访问就可以达到调试的目的,但是若有特殊Header或身份验证时就不太方便了,如下在PostMan中输入对应地址点击【Send】即可看到返回的数据及消耗的时间和HttpStatus等。

    image

    对于我们常用的我们可以点击Add to collection将其加入到Collections中便于下次测试。

    image

    image

    接下来,我们对新增产品添加调试。

    image

    其余的类似,请求的方法类型与Http请求类型一致。

    image

    四、生成PostMan导入数据

    那么,对于参数较多的接口时第一次添加参数是比较繁琐的,所以我希望能有根据接口定义生成出可以导入到PostMan中的方法,分析Postman下载出来的数据格式可见其实就是一个Json格式的文件。

    image

    image

    那既然是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。

    image

    image

    效果还是可以接受的,还有写可以拓展的地方,比如可以直接一键导入到PostMan程序中,用谷歌浏览器审查元素可以发现导入的方法是importCollectionFromUrl,在console中输入

    window.open("chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm/index.html");
    pm.collections.importCollectionFromUrl("http://localhost:11488/postman");

    就可以达到一键导入的目的了。但是遗憾的是,必须要在插件内调用才有效,代码匆忙,还有很多地方可以继续拓展,不过本文的目的已经达到了。

    示例代码:https://github.com/yanghongjie/WebAPI2PostMan

  • 相关阅读:
    Atitit topic index Abt 150 toic [原]Atitit hi dev eff topic by use dsl sql coll op 提升开发效率sql ds
    Atitit xml转json总结 目录 1.1. XML和JSON之间没有直接映射;元素类型问题 1 1.2. Xml与json的对应关系 2 1.3. 范例 2 2. Jsonlib的问题,,不
    Atitit stomp.js conn连接activemq 目录 1.1. activemq 启动,已经默认开启了stomp ws的接口。。地址是 1 1.2. Js 客户端代码 1 1.3
    Atitit 业务领域体系分类 目录 1. 按照互联网企业类型以及只是体系类的分类 2 2. 电子商务 2 3. **通信类社交 Im类 em 2 4. **信息搜索类爬虫 2 4.1. 媒体
    atitit software sys 软件技术领域工业体系.docx 目录 1. 技术领域一级大类10大类 2 2. 理论与软件设计方法学 2 2.1. 计算机原理 计算机科学导论 2 2.2.
    Atitit api design Usability simple 易用性之简单化设计 目录 1. 理论原则 2 1.1. 概念简单 2 1.2. 切换到了“write less, do more
    Atitit 远程工作的几种办公模式 目录 1. 未来的趋势 远程办公 1 1.1. 遥远的阴影 1 1.2. 一个单中心的团队,是一个团队,每个人都被共处于同一物理位置。 2 1.3. 一个多站
    Atitit 保证产品易用性的方法总结 目录 1. 什么是易用性 易学 易见 三角关系 1 2. 易用性原理 三原则 易见 映射 反馈 2 2.1. 易见 Visibility 可读性 2 2.2.
    Atitit 高级人员要看哪些源码 目录 1. Ati看过的源码 1 1.1. Ui类 1 1.2. Mvc类 1 1.3. 数据库类 1 1.4. 算法类 1 2. 看源码的意义 2 2.1. 一
    Atitit 初级 中级 高级 软件工程师的区别 非功能性需求 目录 1. 初级 业务功能 1 1.1. 中级 独立完成业务功能 已经非常见api功能 更加广阔 1 2. 高级 非功能性需求
  • 原文地址:https://www.cnblogs.com/idoudou/p/WebApi2PostMan.html
Copyright © 2011-2022 走看看