Postman是一个可以轻松测试休息的Web服务的工具.
如果Asp.Net项目正在使用WebApi与WebApi Helppages文档,则可以自动为暴露的静态Web服务生成文档.
解决方法
扩展博客帖子“
Using ApiExplorer to export API information to PostMan,a Chrome extension for testing Web APIs”可以生成一个可以导入Postman的JSON文件,用于测试和记录.
首先,您需要设置一个可以导出JSON的控制器
- /// <summary>
- /// Based on
- /// http://blogs.msdn.com/b/yaohuang1/archive/2012/06/15/using-apiexplorer-to-export-api-information-to-postman-a-chrome-extension-for-testing-web-apis.aspx
- /// </summary>
- [RoutePrefix("api/postman")]
- public class PostmanApiController : ApiController
- {
- /// <summary>
- /// Produce [POSTMAN](http://www.getpostman.com) related responses
- /// </summary>
- public PostmanApiController()
- {
- // exists for documentation purposes
- }
- private readonly Regex _pathVariableRegEx = new Regex("\\{([A-Za-z0-9-_]+)\\}",RegexOptions.ECMAScript | RegexOptions.Compiled);
- private readonly Regex _urlParameterVariableRegEx = new Regex("=\\{([A-Za-z0-9-_]+)\\}",RegexOptions.ECMAScript | RegexOptions.Compiled);
- /// <summary>
- /// Get a postman collection of all visible Api
- /// (Get the [POSTMAN](http://www.getpostman.com) chrome extension)
- /// </summary>
- /// <returns>object describing a POSTMAN collection</returns>
- /// <remarks>Get a postman collection of all visible api</remarks>
- [HttpGet]
- [Route(Name = "GetPostmanCollection")]
- [ResponseType(typeof (PostmanCollectionGet))]
- public IHttpActionResult GetPostmanCollection()
- {
- return Ok(this.PostmanCollectionForController());
- }
- private PostmanCollectionGet PostmanCollectionForController()
- {
- var requestUri = Request.RequestUri;
- var baseUri = requestUri.Scheme + "://" + requestUri.Host + ":" + requestUri.Port
- + HttpContext.Current.Request.ApplicationPath;
- var postManCollection = new PostmanCollectionGet
- {
- Id = Guid.NewGuid(),Name = "[Name of your API]",Timestamp = DateTime.Now.Ticks,Requests = new Collection<PostmanRequestGet>(),Folders = new Collection<PostmanFolderGet>(),Synced = false,Description = "[Description of your API]"
- };
- var helpPageSampleGenerator = Configuration.GetHelpPageSampleGenerator();
- var apiExplorer = Configuration.Services.GetApiExplorer();
- var apiDescriptionsByController = apiExplorer.ApiDescriptions.GroupBy(
- description =>
- description.ActionDescriptor.ActionBinding.ActionDescriptor.ControllerDescriptor.ControllerType);
- foreach (var apiDescriptionsByControllerGroup in apiDescriptionsByController)
- {
- var controllerName = apiDescriptionsByControllerGroup.Key.Name.Replace("Controller",string.Empty);
- var postManFolder = new PostmanFolderGet
- {
- Id = Guid.NewGuid(),CollectionId = postManCollection.Id,Name = controllerName,Description = string.Format("Api Methods for {0}",controllerName),CollectionName = "api",Order = new Collection<Guid>()
- };
- foreach (var apiDescription in apiDescriptionsByControllerGroup
- .OrderBy(description => description.HttpMethod,new HttpMethodComparator())
- .ThenBy(description => description.RelativePath)
- .ThenBy(description => description.Documentation.ToString(CultureInfo.InvariantCulture)))
- {
- TextSample sampleData = null;
- var sampleDictionary = helpPageSampleGenerator.GetSample(apiDescription,SampleDirection.Request);
- MediaTypeHeaderValue mediaTypeHeader;
- if (MediaTypeHeaderValue.TryParse("application/json",out mediaTypeHeader)
- && sampleDictionary.ContainsKey(mediaTypeHeader))
- {
- sampleData = sampleDictionary[mediaTypeHeader] as TextSample;
- }
- // scrub curly braces from url parameter values
- var cleanedUrlParameterUrl = this._urlParameterVariableRegEx.Replace(apiDescription.RelativePath,"=$1-value");
- // get pat variables from url
- var pathVariables = this._pathVariableRegEx.Matches(cleanedUrlParameterUrl)
- .Cast<Match>()
- .Select(m => m.Value)
- .Select(s => s.Substring(1,s.Length - 2))
- .ToDictionary(s => s,s => string.Format("{0}-value",s));
- // change format of parameters within string to be colon prefixed rather than curly brace wrapped
- var postmanReadyUrl = this._pathVariableRegEx.Replace(cleanedUrlParameterUrl,":$1");
- // prefix url with base uri
- var url = baseUri.TrimEnd('/') + "/" + postmanReadyUrl;
- var request = new PostmanRequestGet
- {
- CollectionId = postManCollection.Id,Id = Guid.NewGuid(),Name = apiDescription.RelativePath,Description = apiDescription.Documentation,Url = url,Method = apiDescription.HttpMethod.Method,Headers = "Content-Type: application/json",Data = sampleData == null
- ? null
- : sampleData.Text,DataMode = "raw",Time = postManCollection.Timestamp,DescriptionFormat = "markdown",Version = "beta",Responses = new Collection<string>(),PathVariables = pathVariables
- };
- postManFolder.Order.Add(request.Id); // add to the folder
- postManCollection.Requests.Add(request);
- }
- postManCollection.Folders.Add(postManFolder);
- }
- return postManCollection;
- }
- }
- /// <summary>
- /// Quick comparer for ordering http methods for display
- /// </summary>
- internal class HttpMethodComparator : IComparer<HttpMethod>
- {
- private readonly string[] _order =
- {
- "GET","POST","PUT","DELETE"
- };
- public int Compare(HttpMethod x,HttpMethod y)
- {
- return Array.IndexOf(this._order,x.ToString()).CompareTo(Array.IndexOf(this._order,y.ToString()));
- }
- }
并生成正确的模型:
一个用于PostManCollection
- /// <summary>
- /// [Postman](http://getpostman.com) collection representation
- /// </summary>
- public class PostmanCollectionGet
- {
- /// <summary>
- /// Id of collection
- /// </summary>
- [JsonProperty(PropertyName = "id")]
- public Guid Id { get; set; }
- /// <summary>
- /// Name of collection
- /// </summary>
- [JsonProperty(PropertyName = "name")]
- public string Name { get; set; }
- /// <summary>
- /// Collection generation time
- /// </summary>
- [JsonProperty(PropertyName = "timestamp")]
- public long Timestamp { get; set; }
- /// <summary>
- /// Requests associated with the collection
- /// </summary>
- [JsonProperty(PropertyName = "requests")]
- public ICollection<PostmanRequestGet> Requests { get; set; }
- /// <summary>
- /// **unused always false**
- /// </summary>
- [JsonProperty(PropertyName = "synced")]
- public bool Synced { get; set; }
- /// <summary>
- /// folders within the collection
- /// </summary>
- [JsonProperty(PropertyName = "folders")]
- public ICollection<PostmanFolderGet> Folders { get; set; }
- /// <summary>
- /// Description of collection
- /// </summary>
- [JsonProperty(PropertyName = "description")]
- public string Description { get; set; }
- }
一个邮递员
- /// <summary>
- /// Object that describes a [Postman](http://getpostman.com) folder
- /// </summary>
- public class PostmanFolderGet
- {
- /// <summary>
- /// id of the folder
- /// </summary>
- [JsonProperty(PropertyName = "id")]
- public Guid Id { get; set; }
- /// <summary>
- /// folder name
- /// </summary>
- [JsonProperty(PropertyName = "name")]
- public string Name { get; set; }
- /// <summary>
- /// folder description
- /// </summary>
- [JsonProperty(PropertyName = "description")]
- public string Description { get; set; }
- /// <summary>
- /// ordered list of ids of items in folder
- /// </summary>
- [JsonProperty(PropertyName = "order")]
- public ICollection<Guid> Order { get; set; }
- /// <summary>
- /// Name of the collection
- /// </summary>
- [JsonProperty(PropertyName = "collection_name")]
- public string CollectionName { get; set; }
- /// <summary>
- /// id of the collection
- /// </summary>
- [JsonProperty(PropertyName = "collection_id")]
- public Guid CollectionId { get; set; }
- }
最后一个PostmanRequest的模型
- /// <summary>
- /// [Postman](http://getpostman.com) request object
- /// </summary>
- public class PostmanRequestGet
- {
- /// <summary>
- /// id of request
- /// </summary>
- [JsonProperty(PropertyName = "id")]
- public Guid Id { get; set; }
- /// <summary>
- /// headers associated with the request
- /// </summary>
- [JsonProperty(PropertyName = "headers")]
- public string Headers { get; set; }
- /// <summary>
- /// url of the request
- /// </summary>
- [JsonProperty(PropertyName = "url")]
- public string Url { get; set; }
- /// <summary>
- /// path variables of the request
- /// </summary>
- [JsonProperty(PropertyName = "pathVariables")]
- public Dictionary<string,string> PathVariables { get; set; }
- /// <summary>
- /// method of request
- /// </summary>
- [JsonProperty(PropertyName = "method")]
- public string Method { get; set; }
- /// <summary>
- /// data to be sent with the request
- /// </summary>
- [JsonProperty(PropertyName = "data")]
- public string Data { get; set; }
- /// <summary>
- /// data mode of reqeust
- /// </summary>
- [JsonProperty(PropertyName = "dataMode")]
- public string DataMode { get; set; }
- /// <summary>
- /// name of request
- /// </summary>
- [JsonProperty(PropertyName = "name")]
- public string Name { get; set; }
- /// <summary>
- /// request description
- /// </summary>
- [JsonProperty(PropertyName = "description")]
- public string Description { get; set; }
- /// <summary>
- /// format of description
- /// </summary>
- [JsonProperty(PropertyName = "descriptionFormat")]
- public string DescriptionFormat { get; set; }
- /// <summary>
- /// time that this request object was generated
- /// </summary>
- [JsonProperty(PropertyName = "time")]
- public long Time { get; set; }
- /// <summary>
- /// version of the request object
- /// </summary>
- [JsonProperty(PropertyName = "version")]
- public string Version { get; set; }
- /// <summary>
- /// request response
- /// </summary>
- [JsonProperty(PropertyName = "responses")]
- public ICollection<string> Responses { get; set; }
- /// <summary>
- /// the id of the collection that the request object belongs to
- /// </summary>
- [JsonProperty(PropertyName = "collection-id")]
- public Guid CollectionId { get; set; }
- /// <summary>
- /// Synching
- /// </summary>
- [JsonProperty(PropertyName = "synced")]
- public bool Synced { get; set; }
- }
现在您需要做的就是向[应用程序] api / postman发出GET请求,并且您将以Postman可读的形式使用最新的安全API.