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.