我们有一套REST服务。服务在POST请求中接受json中的模型,并在POST响应中返回json中的模型。但是,这些模型在我们的ASP.NET Core 2.0项目中不是物理编译类型。相反,它们是映射到我们内部类型的映射对象。即提供的json只是我们核心实体顶层的一层,为了将数据暴露给第三方而被削减。
然而,实体需要与Swagger一起记录。 Swashbuckle做得很好。它通过命名空间Microsoft.AspNetCore.Mvc.ApiExplorer实现。我现在正在尝试使用此命名空间为json中提供的实体定义元数据。但是,我没有太多运气。我想定义一个不基于项目中物理类型的类型。我很乐意定义名称和属性等,但我无法完成我所做的任何事情。例如,抽象类ModelMetadata需要ModelMetadataIdentity类型的参数,但此类型在构造函数中不带任何参数,并且所有重要属性都是Get only。因此,例如,我实际上无法在ModelMetadataIdentity上设置Name属性。我猜这是代码中的一个小问题,我甚至可以构建一个ModelMetadataIdentity。我猜这个课程本来是抽象的。
例如,有一个名为ForType的静态方法可以编译,并且不会抛出任何异常,如下所示:
var customModelMetadataProvider = new CustomModelMetadataProvider(ModelMetadataIdentity.ForType(typeof(TaskInfo)));
context.ApiDescription.SupportedResponseTypes.Add(new Microsoft.AspNetCore.Mvc.ApiExplorer.ApiResponseType { ModelMetadata = customModelMetadataProvider });
但是,这没有任何作用。在Swagger文档中没有为TaskInfo显示任何文档。但是,更重要的是,这对我来说并不好,因为TaskInfo是预编译类型,我试图定义概念类型,而不是物理类型。
要了解我在说什么,您可以在此处查看示例: https://github.com/Microsoft/aspnet-api-versioning/tree/master/samples/webapi/SwaggerODataWebApiSample。例如,Order和Person被定义为项目中的类型,但我想动态地为这些类型构建元数据。
如何使用Microsoft.AspNetCore.Mvc.ApiExplorer命名空间定义概念(动态)类型?如何强制Swashbuckle识别我使用此命名空间定义的元数据?
PS:我知道有些人会想“你为什么不在代码中编写模型并编译它们?”。好吧,显然可以做到这一点,但这为配置不必要的REST服务增加了额外的一步。从内部实体到外部实体的映射是通过配置完成的 - 而不是代码!配置人员不必编译任何内容来公开这些实体。
答案 0 :(得分:0)
这可以通过这样的Swashbuckle完成:
public class SwaggerOperationFilter : IOperationFilter
{
#region Fields
private const string testpropertyname = "TestProperty";
private const string TestSchemaRef = "ADef";
private static Schema TestSchema = new Schema { Required = new List<string> { testpropertyname }, Example = new { TestProperty = "Test" }, Description = "This is a Description", Title = "TestSchema", Properties = new Dictionary<string, Schema>() };
#endregion
#region Static Constructor
static SwaggerOperationFilter()
{
TestSchema.Properties.Add(testpropertyname, new Schema { Type = "string" });
}
#endregion
#region Implementation
public void Apply(Operation operation, OperationFilterContext context)
{
if (!context.SchemaRegistry.Definitions.ContainsKey(TestSchemaRef))
{
context.SchemaRegistry.Definitions.Add(TestSchemaRef, TestSchema);
}
operation.Responses["200"] = new Response
{
Description = "This is a Response Description",
Schema = TestSchema
};
}
#endregion
}