Come generare JSON Postino Raccolte da una WebApi2 progetto utilizzando WebApi HelpPages che sono adatti per l’importazione

Postino è uno strumento che può essere utilizzato per testare i servizi web restful.

Se un Asp.Net il progetto utilizza WebApi in collaborazione con WebApi Helppages documentazione possono essere generate automaticamente esposti i servizi web restful.

Questo generare automaticamente la documentazione è buona, ma poteva essere fatto meglio via aggiunti accessibilità.

Come possono questi techtechnologies essere combinati per generare un file JSON che possono essere importati nel Postino?

InformationsquelleAutor rheone | 2014-04-18

 

3 Replies
  1. 13

    Espansione sul post del blog “Utilizzando ApiExplorer per esportare le informazioni di API per il Postino, un estensione di google Chrome per il test di Web Api” è possibile generare un file JSON che possono essere importati in un Postino per il test e la documentazione.

    Primo è necessario per l’installazione di un controller in grado di esportare 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,
                                      Synced = false,
                                      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()));
        }
    }

    e generare i modelli appropriati:

    Uno per il 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; }
    }

    Uno per il PostmanFolder

    ///<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; }
    }

    Infine un modello per la 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; }
    }

    Ora tutto quello che dovete fare è effettuare una richiesta GET per [applicazione]api/postino e avrete le più recenti API restful in una forma leggibile dal postino.

    • Da dove viene GetHelpPageSampleGenerator() provengono da? C’è un pacchetto NuGet? Ho trovato un potenziale candidato qui.
    • Corretto, sto utilizzando Microsoft ASP.NET Web API 2.2 Pagina di Aiuto nuget.org/packages/Microsoft.AspNet.WebApi.Help
    • Ho dovuto fare una piccola modifica, mi è stato sempre un NullReferenceException in PostmanCollectionForController(). Ho rimosso questo tipo: .ThenBy(description => description.Documentation.ToString(CultureInfo.InvariantCulture))
    • MS ASP.net pacchetto nuget pagina .Aiuto non esiste, ma i suoi genitori non; nuget.org/packages/Microsoft.AspNet.WebApi .
    • Importazione non riuscita a causa della mancanza di collectionId. Ho cambiato questo modello per ottenere l’importazione: [JsonProperty(PropertyName = “collezione-id”)] per [JsonProperty(PropertyName = “collectionId”)]. Tuttavia le cartelle vengono create, ma vuoto, e le richieste sono di seguito le cartelle invece che all’interno di cartelle appropriate. Json è corretto, tuttavia, per quanto posso dire.
    • Vedo che c’è un pacchetto NuGet per questo il codice che è stato aggiornato. Postino.WebApi.HelpDocumentation.
    • Ho paura che il Postino JSON schema è cambiato in modo significativo dal momento che ho originariamente postato la soluzione. Ho inviato una mail allo sviluppatore un po ‘ e che, al tempo in cui egli non era intenzione di pubblicare lo schema. GarDavis Qualcun altro ha preso la soluzione che ho fornito e ha creato un pacchetto NuGet, non so in che stato si trova attualmente in, soddisfare le esigenze di soluzione originale.

  2. 1

    Avrete anche bisogno di aggiornare il PostmanRequestGet.cs modello per ottenere questo lavoro.

    aggiornamento come segue:-

     ///<summary>
            ///    the id of the collection that the request object belongs to
            ///</summary>
            [JsonProperty(PropertyName = "collectionId")]
            public Guid CollectionId { get; set; }
    • credo che questo dovrebbe essere un commento di risposta a cui ti stai riferendo
  3. 1

    Perché non utilizzare standard di Spavalderia e la uso con il Postino?

    1. Quale è Swagger? (Il resto del Web e documentazione delle API client enabler)
    2. L’importazione di Spavalderia file Postino
    3. Utilizzare Swashbuckle pacchetto NuGet in visual studio per generare Swagger per il vostro API (Pacchetto di Installazione Swashbuckle -Pre)

    Bonus: Questo soluzione è supportato con ASP.NET Core Resto WebAPI

    • Al momento di rispondere alla domanda, però posso sbagliarmi, Postino non ha letto la spavalderia di file. Se io uso questo come il mio approccio attuale per uno dei miei più Web-API progetti sviluppati in ASP.NET 4.x. Anche così una spavalderia approccio richiede l’utilizzo di librerie aggiuntive, con la possibilità di incompatibile licenza. Allo stesso modo il Swashbuckle attuazione, anche se può essere più ricco di funzionalità out of the box, non fornire a grana fine / controllo di basso livello come il sopra citato soluzione con Postino caratteristiche specifiche che non sono contemplate nella spavalderia specifica.
    • Per alcuni è abbastanza buono per cui è presente come una risposta per futuri riferimenti, me compreso.

Lascia un commento