所以我一直在为我的公司编写一些 ASP.NET Core 培训指南,并在 Windows 上遇到了一个有趣的错误。
当使用 Swashbuckle 实现 Swagger 时,应用程序将在启动时崩溃,在 Swagger 的自动 DI 注册期间,由于 Swagger 应针对的 XML 文档文件的路径被截断:
Exception has occurred: CLR/System.IO.FileNotFoundException
An unhandled exception of type 'System.IO.FileNotFoundException' occurred in Microsoft.AspNetCore.Hosting.dll: 'Could not find file 'C:\Temporary\Work\Swagger'.'
at System.IO.FileStream.OpenHandle(FileMode mode, FileShare share, FileOptions options)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize)
at System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCachePolicy cachePolicy)
at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
at System.Xml.XmlTextReaderImpl.OpenUrl()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XPath.XPathDocument.LoadFromReader(XmlReader reader, XmlSpace space)
at System.Xml.XPath.XPathDocument..ctor(String uri, XmlSpace space)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions.<>c__DisplayClass31_0.<IncludeXmlComments>b__0()
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions.CreateSwaggerProvider(IServiceProvider serviceProvider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitTransient(TransientCallSite transientCallSite, ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass22_0.<RealizeService>b__0(ServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
at Microsoft.Extensions.Internal.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass4_0.<UseMiddleware>b__0(RequestDelegate next)
at Microsoft.AspNetCore.Builder.Internal.ApplicationBuilder.Build()
at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
at SwaggerPathIssue.Program.BuildWebHost(String[] args) in C:\Temporary\Work\Swagger # Path Issue 2.0\Program.cs:line 18
at SwaggerPathIssue.Program.Main(String[] args) in C:\Temporary\Work\Swagger # Path Issue 2.0\Program.cs:line 14
注意异常中列出的路径是:
'C:\Temporary\Work\Swagger'
但实际上应该是:
'C:\Temporary\Work\Swagger #1 Demo\doc\Swagger #1 Demo.xml'
要定位的 XML 文件在 Startup.cs 中指定为:
public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new Info {
Version = "v1",
Title = "Swagger #1 Demo",
});
String xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";
String xmlPath = Path.Combine("doc", xmlFile);
c.IncludeXmlComments(xmlPath);
});
}
从所有适当的位置(路径、文件名、启动器等)删除 # 可使一切按预期工作。
现在,如果我根本不指定自定义路径,而是在 Swagger 默认查看的位置生成 XML 文件(使用我的 .csproj 文件,或者只是将 XML 文件复制到该位置),问题就会消失.
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>bin\Debug\$(TargetFramework)\$(MSBuildProjectName).xml</DocumentationFile>
<NoWarn>1701;1702;1705;1591</NoWarn>
</PropertyGroup>
然而...
如果我在 Ubuntu 上编译并运行原始 ASP.NET Core 2.0 项目(带有 #),则问题不存在。
如果我在 Windows 上编译并运行项目的 ASP.NET Core 2.1 版本(带有 #),则问题不存在。
所以这似乎是 ASP.NET Core 2.0 的一个特定问题,可能是使用参数进行 DI 注册,或者可能是 System.Xml 如何处理路径?我还没有深入研究,但是我想在深入研究的同时将问题放在那里,以求知识。
如果有人知道这个问题的根本原因,请随时回答。