wake-up-neo.net

ASP.NET-Web-API Generieren Sie alle Parameter von Modellhilfeseiten

Ich bin damit beschäftigt, eine Web-API zu erstellen (Inside einer asp mvc4-Anwendung). Ich verwende die auf der asp.net-Site vorgeschlagene Bibliothek zur Erstellung von Dokumentation ( http://www.asp.net/web-api/overview/creating-web-apis/creating-api-help-pages ) .

Mein Problem ist, dass, wenn mein Parameter ein Modell ist, ich nicht angeben kann, welche Eigenschaften das Modell auf den generierten Hilfeseiten enthält.

Hier ist ein Beispiel:

MODELL:

public class TestModel
{
    property String FirstName {get;set;}
    property String Surname {get; set;}
    property Boolean Active {get;set;} 
}

AKTION:

/// <summary>
/// This is a test action
/// </summary>
/// <param name="model">this is the model</param> <-- this works
/// <param name="FirstName">This is the first name </param>  <-- doesn't work
/// <param name ="model.Surname">This is the surname</param> <-- doesn't work
public HttpResponseMessage Post(my.namespace.models.TestModel model)
{
  ...
}

Nur der Parameter für das Modell wird generiert.

Ich habe mir das XML-Dokument angesehen, das für die Dokumentation generiert wird, und es werden die anderen Parameter hinzugefügt.

<member name="my.namespace.api.Post(my.namespace.models.TestModel)">
     <summary>
         this is a test action
     </summary>
     <param name="model>this is the model</param>
     <param name="FirstName">This is the first name </param>
     <param name="model.Surname">This is the surname</param>
</member>

Auf den Hilfeseiten wird jedoch nur das Parametermodell generiert.

Ich habe es bis zu der Methode zurückverfolgt, bei der die Parameter aus der XML-Datei abgerufen werden.

Collection<ApiDescription> apiDescriptions = config.Services.GetApiExplorer().ApiDescriptions;

Diese befindet sich in der automatisch generierten HelpPageConfigurationExtentions.cs.

Nähere ich mich dem falschen Weg? Kennt jemand eine Arbeit?

Anregungen oder Lösungen werden gebeten.

23
Jeandre Pentz

Die MVC-Web-API-Dokumentationsfunktion führt Ihre API-Klassen und -Methoden mit Reflektion durch. Dies wird die Struktur der Dokumentation aufbauen, führt jedoch zu mehr oder weniger leeren (und nutzlosen) Dokumentationen, sofern Sie keine Dokumentationskommentare hinzugefügt haben. 

Der Hauptteil der Dokumentation wird mit der XML-Datei gefüllt, die mit /// Dokumentationskommentaren generiert wird, die eine bestimmte Struktur haben, die befolgt werden muss. Das bedeutet, dass Sie Ihre XML-Datei nicht mit dem ausfüllen können, was Sie möchten, sondern es muss mit etwas verbunden sein, das sich in Ihrer API befindet, und der Struktur Ihrer Klassen und Eigenschaften folgen.

In Ihrem Fall können Sie also keine Dokumentation von Modelleigenschaften in eine API-Methode einfügen. Sie müssen es in das Modell einfügen, in dem die Eigenschaft vorhanden ist.

MODELL:

  public class TestModel
  {
  /// <summary>This is the first name </summary>
      property String FirstName {get;set;}
  /// <summary>This is the surname</summary>
      property String Surname {get; set;}
      property Boolean Active {get;set;} 
  }

AKTION:

  /// <summary>
  /// This is a test action
  /// </summary>
  /// <param name="model">this is the model</param> 
  public HttpResponseMessage Post(my.namespace.models.TestModel model)
  {
    ...
  }

Hilfeseiten ändern

Die standardmäßig generierten Hilfeseiten enthalten keine Modelldokumentation, sondern nur die API-Methoden. Um weitere Informationen zu den Parametern in Ihrer API anzuzeigen, ist eine Anpassung erforderlich. Die folgende Anweisung ist eine Möglichkeit, Parameterdokumentation hinzuzufügen.

Erstellen Sie zwei neue Typen in Bereiche/HelpPage/Models

public class TypeDocumentation
{
    public TypeDocumentation()
    {
        PropertyDocumentation = new Collection<PropertyDocumentation>();
    }

    public string Summary { get; set; }
    public ICollection<PropertyDocumentation> PropertyDocumentation { get; set; } 
}

public class PropertyDocumentation
{
    public PropertyDocumentation(string name, string type, string docs)
    {
        Name = name;
        Type = type;
        Documentation = docs;
    }
    public string Name { get; set; }
    public string Type { get; set; }
    public string Documentation { get; set; }
}

Fügen Sie HelpPageApiModel.cs eine neue Eigenschaft hinzu

public IDictionary<string, TypeDocumentation> ParameterModels{ get; set; } 

Erstellen Sie eine neue Schnittstelle

internal interface IModelDocumentationProvider
{
    IDictionary<string, TypeDocumentation> GetModelDocumentation(HttpActionDescriptor actionDescriptor);
}

Ändern Sie XmlDocumentationProvider, um die neue Schnittstelle zu implementieren

public class XmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider
{
    private const string TypeExpression = "/doc/members/member[@name='T:{0}']";
    private const string PropertyExpression = "/doc/members/member[@name='P:{0}']";
///...
///... existing code
///...

    private static string GetPropertyName(PropertyInfo property)
    {
        string name = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", property.DeclaringType.FullName, property.Name);
        return name;
    }

    public IDictionary<string, TypeDocumentation> GetModelDocumentation(HttpActionDescriptor actionDescriptor)
    {
        var retDictionary = new Dictionary<string, TypeDocumentation>();
        ReflectedHttpActionDescriptor reflectedActionDescriptor = actionDescriptor as ReflectedHttpActionDescriptor;
        if (reflectedActionDescriptor != null)
        {
            foreach (var parameterDescriptor in reflectedActionDescriptor.GetParameters())
            {
                if (!parameterDescriptor.ParameterType.IsValueType)
                {
                    TypeDocumentation typeDocs = new TypeDocumentation();


                    string selectExpression = String.Format(CultureInfo.InvariantCulture, TypeExpression, GetTypeName(parameterDescriptor.ParameterType));
                    var typeNode = _documentNavigator.SelectSingleNode(selectExpression);

                    if (typeNode != null)
                    {
                        XPathNavigator summaryNode;
                        summaryNode = typeNode.SelectSingleNode("summary");
                        if (summaryNode != null)
                            typeDocs.Summary = summaryNode.Value;
                    }

                    foreach (var prop in parameterDescriptor.ParameterType.GetProperties())
                    {
                        string propName = prop.Name;
                        string propDocs = string.Empty;
                        string propExpression = String.Format(CultureInfo.InvariantCulture, PropertyExpression, GetPropertyName(prop));
                        var propNode = _documentNavigator.SelectSingleNode(propExpression);
                        if (propNode != null)
                        {
                            XPathNavigator summaryNode;
                            summaryNode = propNode.SelectSingleNode("summary");
                            if (summaryNode != null) propDocs = summaryNode.Value;
                        }
                        typeDocs.PropertyDocumentation.Add(new PropertyDocumentation(propName, prop.PropertyType.Name, propDocs));

                    }
                    retDictionary.Add(parameterDescriptor.ParameterName, typeDocs);
                }

            }

        }

        return retDictionary;
    }
}

Fügen Sie HelpPageConfigurationExtension in der GenerateApiModel-Methode Code hinzu

IModelDocumentationProvider modelProvider =
            config.Services.GetDocumentationProvider() as IModelDocumentationProvider;
if (modelProvider != null)
{
    apiModel.ParameterModels = modelProvider.GetModelDocumentation(apiDescription.ActionDescriptor);
}

Ändern Sie HelpPageApiModel.cshtml und fügen Sie Folgendes hinzu, wo die Modelldokumentation angezeigt werden soll.

bool hasModels = Model.ParameterModels.Count > 0;
if (hasModels)
{
     <h2>Parameter Information</h2>
  @Html.DisplayFor(apiModel => apiModel.ParameterModels, "Models")

}

Fügen Sie Models.cshtml zu DisplayTemplates hinzu

@using System.Web.Http
@using System.Web.Http.Description
@using MvcApplication2.Areas.HelpPage.Models
@model IDictionary<string, TypeDocumentation>

@foreach (var modelType in Model)
{
    <h3>@modelType.Key</h3>
    if (modelType.Value.Summary != null)
    {
    <p>@modelType.Value.Summary</p>
    }
    <table class="help-page-table">
        <thead>
            <tr>
                <th>Property</th>

                <th>Description</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var propInfo in modelType.Value.PropertyDocumentation)
            {
                <tr>
                    <td class="parameter-name"><b>@propInfo.Name</b> (@propInfo.Type)</td>

                    <td class="parameter-documentation">
                        <pre>@propInfo.Documentation</pre>
                    </td>
                </tr>
            }
        </tbody>
    </table>
}
27
agilejoshua

josants Antwort funktioniert großartig. Ich fand es jedoch ein bisschen übertrieben eifrig. Ich fand, dass es einfache Dinge wie Strings als Modelle meldete und sie als Char-Array mit einem Längenfeld bezeichneten!

Wir brauchten dies nur für Modelle, deshalb fügte ich diesen Code am Ende der GetModelDocumentation-Methode hinzu:

if (parameterDescriptor.ParameterName == "value" || parameterDescriptor.ParameterName == "model")
{
    retDictionary.Add(parameterDescriptor.ParameterName, typeDocs);
}

Jetzt werden nur Parameterdetails für nicht einfache Typen zurückgegeben.

0
Maxcelcat