10

Web API があり、ドキュメントを自動生成するWeb API ヘルプ ページを追加しました。パラメータがリストされているメソッドではうまく機能しますが、次のようなメソッドがあります。

public SessionResult PostLogin(CreateSessionCommand request)

また、私のヘルプ ページでは、プロパティ セクションにコマンド パラメータのみがリストされています。ただし、サンプル リクエスト セクションでは、CreateSessionCommandクラスのすべてのプロパティがリストされています。

パラメーター

名前 | 説明 | 追加情報

リクエスト | ドキュメントはありません。| | リクエスト本文でこのパラメータを定義します。

代わりに、クラスのすべてのプロパティをリストしたいと思いCreateSessionCommandます。これを行う簡単な方法はありますか?

4

3 に答える 3

7

そのため、誰かが興味を持っている場合に備えて、この問題の回避策を考案することができました.

HelpPageConfigurationExtensions.cs に、次の拡張メソッドを追加しました。

public static void AlterApiDescription(this ApiDescription apiDescription, HttpConfiguration config)
{
    var docProvider = config.Services.GetDocumentationProvider();
    var addParams = new List<ApiParameterDescription>();
    var removeParams = new List<ApiParameterDescription>();

    foreach (var param in apiDescription.ParameterDescriptions)
    {
        var type = param.ParameterDescriptor.ParameterType;

        //string is some special case that is not a primitive type
        //also, compare by full name because the type returned does not seem to match the types generated by typeof
        bool isPrimitive = type.IsPrimitive || String.Compare(type.FullName, typeof(string).FullName) == 0;

        if (!isPrimitive)
        {
            var properties = from p in param.ParameterDescriptor.ParameterType.GetProperties() 
                               let s = p.SetMethod 
                               where s.IsPublic 
                               select p;

            foreach (var property in properties)
            {
                var documentation = docProvider.GetDocumentation(new System.Web.Http.Controllers.ReflectedHttpParameterDescriptor()
                {
                    ActionDescriptor = param.ParameterDescriptor.ActionDescriptor,
                    ParameterInfo = new CustomParameterInfo(property)
                });

                addParams.Add(new ApiParameterDescription()
                {
                    Documentation = documentation,
                    Name = property.Name,
                    Source = ApiParameterSource.FromBody,
                    ParameterDescriptor = param.ParameterDescriptor
                });
            }

            //since this is a complex type, select it to be removed from the api description
            removeParams.Add(param);
        }
    }

    //add in our new items
    foreach (var item in addParams)
    {
        apiDescription.ParameterDescriptions.Add(item);
    }

    //remove the complex types
    foreach (var item in removeParams)
    {
        apiDescription.ParameterDescriptions.Remove(item);
    }
}

そして、これが私が使用するパラメーター情報インスタンス化されたクラスです

internal class CustomParameterInfo : ParameterInfo
{
    public CustomParameterInfo(PropertyInfo prop)
    {
        base.NameImpl = prop.Name;
    }
}

次に、拡張機能クラス内の別のメソッドで拡張機能を呼び出します

public static HelpPageApiModel GetHelpPageApiModel(this HttpConfiguration config, string apiDescriptionId)
{
    object model;
    string modelId = ApiModelPrefix + apiDescriptionId;
    if (!config.Properties.TryGetValue(modelId, out model))
    {
        Collection<ApiDescription> apiDescriptions = config.Services.GetApiExplorer().ApiDescriptions;
        ApiDescription apiDescription = apiDescriptions.FirstOrDefault(api => String.Equals(api.GetFriendlyId(), apiDescriptionId, StringComparison.OrdinalIgnoreCase));
        if (apiDescription != null)
        {
            apiDescription.AlterApiDescription(config);

            HelpPageSampleGenerator sampleGenerator = config.GetHelpPageSampleGenerator();
            model = GenerateApiModel(apiDescription, sampleGenerator);
            config.Properties.TryAdd(modelId, model);
        }
    }

    return (HelpPageApiModel)model;
}

これに使用されるコメントは、クラス オブジェクトのプロパティではなく、コントローラー メソッドに追加する必要があります。これは、オブジェクトが外部ライブラリの一部である可能性があります

于 2013-08-21T19:49:02.787 に答える
6

これは@Joshの回答に追加する必要があります。モデル クラスのプロパティを一覧表示するだけでなく、各プロパティのドキュメントも含める場合は、次のようにAreas/HelpPage/XmlDocumentationProvider.csファイルを変更する必要があります。

public virtual string GetDocumentation(HttpParameterDescriptor parameterDescriptor)
{
    ReflectedHttpParameterDescriptor reflectedParameterDescriptor = parameterDescriptor as ReflectedHttpParameterDescriptor;
    if (reflectedParameterDescriptor != null)
    {
        if (reflectedParameterDescriptor.ParameterInfo is CustomParameterInfo)
        {
            const string PropertyExpression = "/doc/members/member[@name='P:{0}']";
            var pi = (CustomParameterInfo) reflectedParameterDescriptor.ParameterInfo;

            string selectExpression = String.Format(CultureInfo.InvariantCulture, PropertyExpression, pi.Prop.DeclaringType.FullName + "." + pi.Prop.Name); 
            XPathNavigator methodNode = _documentNavigator.SelectSingleNode(selectExpression);
            if (methodNode != null)
            {
                return methodNode.Value.Trim();
            }
        }
        else
        {
            XPathNavigator methodNode = GetMethodNode(reflectedParameterDescriptor.ActionDescriptor);
            if (methodNode != null)
            {
                string parameterName = reflectedParameterDescriptor.ParameterInfo.Name;
                XPathNavigator parameterNode = methodNode.SelectSingleNode(String.Format(CultureInfo.InvariantCulture, ParameterExpression, parameterName));
                if (parameterNode != null)
                {
                    return parameterNode.Value.Trim();
                }
            }                    
        }
    }

    return null;
}

また、CustomParameterInfoクラスはプロパティ情報も保持する必要があります。

internal class CustomParameterInfo : ParameterInfo
{
    public PropertyInfo Prop { get; private set; }

    public CustomParameterInfo(PropertyInfo prop)
    {
        Prop = prop;
        base.NameImpl = prop.Name;
    }
}
于 2013-11-08T13:35:45.770 に答える