我有一个.Net Core 2.2 OData API,我想为此实现Swagger文档。
我一直在关注这个示例:https://github.com/Microsoft/aspnet-api-versioning/tree/master/samples/aspnetcore/SwaggerODataSample
我已经做到了一点。 现在,我的模型以循环方式相互引用时遇到一个问题,让我解释一下:
注意:我使用EFCore Code first方法处理数据库。
我有以下模型(作为示例):Project,ProjectLocation,ProjectRegion。 让我们称它们为A,B和C是为了使内容简短。
A对B&C的引用如下:
public virtual ICollection<X> X{ get; set; }
B和C都直接像这样引用A:
public A A{ get; set; }
这都是标准的关系数据库模型,但是SwaggerUI似乎无法处理。
我得到的错误如下:
无法加载API定义。 错误: 提取错误: 内部服务器错误/swagger/v1/swagger.json
处理请求时发生未处理的异常。 TypeLoadException:无法从程序集“ Tc2fc56a7babe40419a678a075439246c.DynamicModels,版本= 0.0.0.0,文化=中性,PublicKeyToken = null”中加载类型“ NCCRD.Services.DataV2.Database.Models.ProjectLocation”。
System.Signature.GetSignature(Void * pCorSig,int cCorSig,RuntimeFieldHandleInternal fieldHandle,IRuntimeMethodInfo methodHandle,RuntimeType declaringType)
如果需要,还可以使用堆栈跟踪。
我已尽我所能阅读了这两篇文章和所有参考链接,但找不到有效的解决方案:
https://github.com/swagger-api/swagger-codegen/issues/741
https://github.com/swagger-api/swagger-codegen/issues/728
看似好的解决方案是:https://systemout.net/2017/04/07/swagger-asp-net-core-fixing-circular-self-references/,但这也没有任何效果。 (我也联系作者寻求帮助)
从B或C中删除对A的引用后,SwaggerUI就会很好地加载。
如果有人能对此有所启发,我将非常感激。 预先感谢您提供的任何帮助。
答案 0 :(得分:2)
经过两天的深入研究和实验,我找不到开箱即用的解决方案。 Swashbuckle曾经是我的首选,但是因为我在.NetCore中使用Odata,所以这不是一个选择。 Swashbuckle为OData和.NetCore分别提供了选项,但不幸的是,不能同时使用。
但是我确实找到了一个解决方案,通过我的努力,我能够将其转换为适合我需要的东西。以下帖子构成了我最终解决方案的起点(仍然是一个进行中的BTW):https://stackoverflow.com/a/51774147/4261155
我的“ CustomDocumentFilter”版本已在GitHub上发布:https://github.com/SAEONData/NCCRD/blob/swagger_odata_netcore/NCCRD_API/NCCRD.Services.DataV2/Database/Contexts/CustomDocumentFilter.cs
如前所述,这项工作仍在进行中,因此将在接下来的几天内进行更改,但是与原始版本一起,我希望这可以对处于相同情况的其他人有所帮助。另外请记住,该类经过修改以满足我的特定需求,而不是为其他任何人提供的“开箱即用”的解决方案。
答案 1 :(得分:0)
这似乎是与Model Substitution功能有关的错误。该修补程序已发布在 Microsoft.AspNetCore.OData.Versioning.ApiExplorer 程序包的版本3.1.1中。如果此问题仍然存在,请在API版本库中报告new issue。
答案 2 :(得分:0)
我使用linq序列化了响应。
这是我的课程:
public sealed class ProductDto
{
public int ProductId { get; set; }
public string Description { get; set; }
public string Type { get; set; }
public List<PlanDto> Plans { get; set; }
}
public class PlanDto
{
public int PlanId { get; set; }
public int ProductId { get; set; }
public string Description { get; set; }
public bool Active { get; set; }
public DateTime Created { get; set; }
public virtual ProductDto Product { get; set; }
}
然后,我从响应中删除了在这种情况下为 Product = null 的循环引用。
我的解决方案:
productEntity.ForEach(i => i.Plans.ForEach(j => j.Product = null));
当昂首阔步地解决了这个问题时,就不需要序列化了。