【问题标题】:List Of Controllers And Classes In Asp.NET Web APIAsp.NET Web API 中的控制器和类列表
【发布时间】:2014-08-08 15:20:54
【问题描述】:

我想访问我的 web api 中的所有控制器。假设我有 2 个控制器和 2 个类;

Foo

string fooId

string fooName

条形

string barId

string barName

Sample1Controller

Get(int fooId)

Post([FromBody] Foo foo)

Sample2Controller

Get(int barId)

Post([FromBody] Bar bar)

我想列出我的控制器、Foo 和 Bar 类的属性。我该怎么做?

更新

我想为移动应用创建请求和响应类。例如,如果我远程访问这些详细信息,我可以为 java 或 Objective-c 创建请求和响应类。

【问题讨论】:

  • 我最近构建了一个 web-api 解决方案,需要自己生成对类和请求/响应的访问。使用 WebAPI Odata 允许通过元数据链接访问这些对象。这是我遵循的教程之一的链接。 asp.net/web-api/overview/odata-support-in-aspnet-web-api/… odata 提供程序有一个元数据资源,其他应用程序可以使用该资源来获取您的访问点的强类型 xml 架构,然后可以将这些应用程序转换为对象,以与您的 WebAPI Odata 端点集成。
  • @Pynt 感谢您的评论。这很有帮助,但这只是提供模型。我需要控制器和模型。例如有 5 个控制器和 5 个模型。我需要哪个控制器使用 Model1,哪个控制器使用 Model2。我还需要控制器 url 和 HTTP 方法类型(GET、POST 等)。
  • 当您说它只提供模型时,您是指在设置 WebAPI-OData 控制器后被外部应用程序使用时服务引用的结果吗?如果是这样,这些模型应该与 WebAPI 上的控制器进行 1 对 1 映射,那么辅助应用程序是否能够正确使用这些“模型”来构建 OData 查询以检索数据。 AngularJS 有一个 OData 框架。当然还有 C#,它们都可以从 WebAPI 服务参考构建查询。
  • @Pynt 有没有关于它的样本?
  • 我最初评论中提供的链接在页面顶部提供了源代码,但我也会在此处包含它:code.msdn.microsoft.com/ASPNET-Web-API-OData-cecdb524。要检查的关键点是模型、Visual Studio 从模型创建的控制器、包含路由数据的 webapiconfig.cs。或者您想要一个使用另一个项目的 WebAPI Odata 服务的示例?

标签: c# asp.net asp.net-web-api wsdl service-discovery


【解决方案1】:

您可以使用ApiExplorer 类,该类专门用于为 Web API 生成文档。

通常它用于生成 HTML 帮助页面,但没有什么可以阻止您创建更机器可读的输出,例如 JSON 或 XML。如果您通过 API 操作方法公开输出,您将获得取决于请求的类型,就像任何其他 API 方法一样。

有一篇关于创建帮助页面here 的好文章,但是关于输出HTML 以外的任何内容的材料并不多。不幸的是,ApiExplorer 类不可序列化,因此您不能只返回对 GetApiExplorer() 的调用结果,但创建我们自己的可序列化类、填充它们然后从 API 操作返回这些类已经足够简单了。

您可以使用GlobalConfiguration.Configuration.Services.GetApiExplorer().ApiDescriptions 访问ApiExplorer 类。这将返回一个Collection<ApiDescription>,其中包含有关控制器、操作和参数的信息。如果您愿意,它甚至可以用于从任何///summary cmets 访问文档。这取决于您所追求的信息以及您想要的格式,但以下是使用此方法可以实现的目标的示例:

首先我创建了一个类来存储 Action 方法的详细信息:

[DataContract]
public class ActionMethod
{
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public List<Parameter> Parameters { get; set; }
    [DataMember]
    public string SupportedHttpMethods { get; set; }
}

请注意,SupportedHttpMethods 只是 string 而不是 List&lt;T&gt;。您可能希望将其改进为 List&lt;T&gt;,但对于此示例,我只是用逗号分隔它们以使生活稍微更轻松。

ActionMethod 类有一个 List&lt;Parameter&gt;,如下所示:

[DataContract]
public class Parameter
{
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string Source { get; set; } //where we pass the parameter when calling the action
    [DataMember]
    public string Type { get; set; }
    [DataMember]
    public List<Parameter> SubParameters { get; set; }

}

请注意,SubParameters 用于存储复杂类型的成员变量类型。我只捕获了一层深度,但如果需要,扩展它很容易。

然后,我创建了一个新的Controller,其中包含一个操作方法,它将以List&lt;ActionMethod&gt; 的形式返回我们的API 信息。请注意,我添加了属性[ApiExplorerSettings(IgnoreApi = true)],它告诉ApiExplorer 忽略此Controller 中的任何内容,因此我们不会在我们的文档控制器上生成文档(这可行,但它对我来说太元了!)。

[ApiExplorerSettings(IgnoreApi = true)]
public class HelpController : ApiController
{
    public List<ActionMethod> Get()
    {
        var apiActions = new List<ActionMethod>();

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

        foreach (var api in apiDescriptions)
        {
            List<Parameter> parameters = new List<Parameter>();
            //get the parameters for this ActionMethod
            foreach (var parameterDescription in api.ParameterDescriptions)
            {
                Parameter parameter = new Parameter()
                {
                    Name = parameterDescription.Name, 
                    Source = parameterDescription.Source.ToString(),
                    Type = parameterDescription.ParameterDescriptor.ParameterType.ToString(),
                    SubParameters = new List<Parameter>()
                };
                //get any Sub-Parameters (for complex types; this should probably be recursive)
                foreach (var subProperty in parameterDescription.ParameterDescriptor.ParameterType.GetProperties())
                {
                    parameter.SubParameters.Add(new Parameter()
                    {
                        Name = subProperty.Name,
                        Type = subProperty.PropertyType.ToString()
                    });
                }

                parameters.Add(parameter);
            }
            //add a new action to our list
            apiActions.Add(new ActionMethod()
            {
                Name = api.ActionDescriptor.ControllerDescriptor.ControllerName,
                Parameters = parameters, 
                SupportedHttpMethods = string.Join(",", api.ActionDescriptor.SupportedHttpMethods)
            });
        }

        return apiActions;
    }
}

然后我们可以访问/api/help 的 api 文档。使用您在问题中作为示例提供的控制器和操作方法,请求 JSON 会给出如下响应:

[
   {
      "Name":"Bar",
      "Parameters":[
         {
            "Name":"barId",
            "Source":"FromUri",
            "Type":"System.Int32",
            "SubParameters":[

            ]
         }
      ],
      "SupportedHttpMethods":"GET"
   },
   {
      "Name":"Bar",
      "Parameters":[
         {
            "Name":"bar",
            "Source":"FromBody",
            "Type":"ApiTest.Controllers.Bar",
            "SubParameters":[
               {
                  "Name":"barId",
                  "Source":null,
                  "Type":"System.String",
                  "SubParameters":null
               },
               {
                  "Name":"barName",
                  "Source":null,
                  "Type":"System.String",
                  "SubParameters":null
               }
            ]
         }
      ],
      "SupportedHttpMethods":"POST"
   },
   {
      "Name":"Foo",
      "Parameters":[
         {
            "Name":"fooId",
            "Source":"FromUri",
            "Type":"System.Int32",
            "SubParameters":[

            ]
         }
      ],
      "SupportedHttpMethods":"GET"
   },
   {
      "Name":"Foo",
      "Parameters":[
         {
            "Name":"foo",
            "Source":"FromBody",
            "Type":"ApiTest.Controllers.Foo",
            "SubParameters":[
               {
                  "Name":"fooId",
                  "Source":null,
                  "Type":"System.String",
                  "SubParameters":null
               },
               {
                  "Name":"fooName",
                  "Source":null,
                  "Type":"System.String",
                  "SubParameters":null
               }
            ]
         }
      ],
      "SupportedHttpMethods":"POST"
   }
]

请求 XML 给了我们:

<?xml version="1.0" encoding="UTF-8"?>
<ArrayOfActionMethod xmlns="http://schemas.datacontract.org/2004/07/ApiTest.Controllers" 
                     xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <ActionMethod>
        <Name>Bar</Name>
        <Parameters>
            <Parameter>
                <Name>barId</Name>
                <Source>FromUri</Source>
                <SubParameters />
                <Type>System.Int32</Type>
            </Parameter>
        </Parameters>
        <SupportedHttpMethods>GET</SupportedHttpMethods>
    </ActionMethod>
    <ActionMethod>
        <Name>Bar</Name>
        <Parameters>
            <Parameter>
                <Name>bar</Name>
                <Source>FromBody</Source>
                <SubParameters>
                    <Parameter>
                        <Name>barId</Name>
                        <Source i:nil="true" />
                        <SubParameters i:nil="true" />
                        <Type>System.String</Type>
                    </Parameter>
                    <Parameter>
                        <Name>barName</Name>
                        <Source i:nil="true" />
                        <SubParameters i:nil="true" />
                        <Type>System.String</Type>
                    </Parameter>
                </SubParameters>
                <Type>ApiTest.Controllers.Bar</Type>
            </Parameter>
        </Parameters>
        <SupportedHttpMethods>POST</SupportedHttpMethods>
    </ActionMethod>
    <ActionMethod>
        <Name>Foo</Name>
        <Parameters>
            <Parameter>
                <Name>fooId</Name>
                <Source>FromUri</Source>
                <SubParameters />
                <Type>System.Int32</Type>
            </Parameter>
        </Parameters>
        <SupportedHttpMethods>GET</SupportedHttpMethods>
    </ActionMethod>
    <ActionMethod>
        <Name>Foo</Name>
        <Parameters>
            <Parameter>
                <Name>foo</Name>
                <Source>FromBody</Source>
                <SubParameters>
                    <Parameter>
                        <Name>fooId</Name>
                        <Source i:nil="true" />
                        <SubParameters i:nil="true" />
                        <Type>System.String</Type>
                    </Parameter>
                    <Parameter>
                        <Name>fooName</Name>
                        <Source i:nil="true" />
                        <SubParameters i:nil="true" />
                        <Type>System.String</Type>
                    </Parameter>
                </SubParameters>
                <Type>ApiTest.Controllers.Foo</Type>
            </Parameter>
        </Parameters>
        <SupportedHttpMethods>POST</SupportedHttpMethods>
    </ActionMethod>
</ArrayOfActionMethod>

有关ApiExplorer 类的更多信息,请访问MSDN

【讨论】:

  • 就是这样!!谢谢@petelids!
【解决方案2】:

要获取包含您的控制器的程序集,请将操作添加到这些控制器之一,以便在执行时您可以获取程序集:

var types = GetType().Assembly.GetTypes();

现在您可以遍历这些类型并测试它是什么类型。如果你所有的控制器都实现了一个通用接口或扩展一个通用类等...你也可以测试命名空间..

例如:

for (var t in types)
{
   if (t.IsSubClassOf(typeof( ApiController))){  .... }
}

这是一个教程/示例:

How to get all types in the references that implement IMyInterface

【讨论】:

  • 好的,可以参考一下教程或示例吗?
  • 抱歉,这些信息对我来说还不够。我不知道我把这些代码放在哪里了。我是 Web API 的新手。
  • 那么你正在做你不应该做的事情,这就是你的做法。你需要了解类型和反射
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-23
  • 2023-02-04
  • 2016-05-04
  • 2023-03-11
  • 2016-07-08
  • 2012-11-03
  • 2017-03-18
相关资源
最近更新 更多