Blazor Web Assembly App .Net Core Hosted:发布运行时错误

Posted

技术标签:

【中文标题】Blazor Web Assembly App .Net Core Hosted:发布运行时错误【英文标题】:Blazor Web Assembly App .Net Core Hosted: publish runtime error 【发布时间】:2021-01-19 00:11:03 【问题描述】:

我使用 .NET 5.0 RC1 框架创建了一个托管在 .NET Core 应用程序中的简单 Blazor Web 程序集项目,并在 Visual Studio 2019 Preview 中的向导期间添加了授权。它在调试中完美运行,但如果我发布它并尝试连接到服务器,我会收到 500 错误。检查日志错误是:

Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HM37MQFV38CV", Request id "0HM37MQFV38CV:00000003": An unhandled exception was thrown by the application.
      System.NullReferenceException: Object reference not set to an instance of an object.
         at Microsoft.Extensions.DependencyInjection.IdentityServerBuilderConfigurationExtensions.<>c.<AddSigningCredentials>b__10_2(IServiceProvider sp)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitNoCache(ServiceCallSite callSite, TArgument argument)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
         at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
         at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
         at Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.AuthenticateAsync(HttpContext context, String scheme)
         at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
         at IdentityServer4.Hosting.BaseUrlMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
         at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi)
         at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

我认为问题与身份服务器和证书有关,但我不明白是什么。

有什么想法吗?

谢谢。

【问题讨论】:

【参考方案1】:

使用.pfx 文件时出现以下错误:

Blazor - app.UseIdentityServer(); with .pfx key file - Unexpected character encountered while parsing number

我在使用AddDeveloperSigningCredentialAddSigningCredentialservices.AddIdentityServer() 时也遇到了这个错误。

Blazor WebAssembly App with Individual Accounts and ASP.NET Core Hosted - Object reference not set to an instance of an object - AddSigningCredentials

我终于这样解决了:

以管理员身份在 Powershell 中创建新证书:

New-SelfSignedCertificate -DnsName "blazortest" -CertStoreLocation "cert:\CurrentUser\My"

appsettings.json:

  "IdentityServer": 
    "Clients": 
      "BlazorTest.Client": 
        "Profile": "IdentityServerSPA"
      
    ,
    "Key": 
      "Type": "Store",
      "StoreName": "My",
      "StoreLocation": "CurrentUser",
      "Name": "CN=blazortest"
    
  ,

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-api-authorization?view=aspnetcore-3.0#example-deploy-to-azure-app-service

这在本地有效。然后我使用mmc.exe 将证书导出为.pfx 文件并通过Azure App Service -> TLS/SSL settings 上传。

然后我使用Azure Cloud Shell 启用对证书的访问,如下所示:

az webapp config appsettings set --name <app-name> --resource-group <resource-group-name> --settings WEBSITE_LOAD_CERTIFICATES=<comma-separated-certificate-thumbprints>

https://docs.microsoft.com/en-us/azure/app-service/configure-ssl-certificate-in-code#load-the-certificate-in-code

您也可以通过将WEBSITE_LOAD_CERTIFICATES 添加到Configuration 来手动添加Certificate Thumbprint

然后终于成功了!

如果您从 Azure Cloud Shell 收到错误,例如:

ResourceGroupNotFound:找不到资源组“”。

确保您在正确的订阅中并使用以下命令设置正确的订阅:

az account show

az account list

az account set --subscription <subscriptionId>

如果您在IIS 上托管,则需要将.pfx 证书导入Personal 文件夹以获取Local Computer,然后选择Manage Private Keys... 并授予运行Application Pool 的用户访问权限。

在 GCP、Google Cloud Platform 上托管,如果您没有上传证书,您可能会看到类似于此的错误。

未处理的异常。 System.InvalidOperationException:找不到 在“CurrentUser\My”上具有主题“CN=blazortest”的有效证书

Linux 无法使用 Windows 证书存储来加载 TLS 证书,因此需要从文件中加载证书:

https://docs.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/hosted-with-identity-server?view=aspnetcore-5.0&tabs=visual-studio#host-in-azure-app-service-with-certificate-token-signing

【讨论】:

感谢这个有用的答案。如何使用带有 LetsEncrypt 证书的共享托管服务器使其工作。我正在使用 Web 部署发布应用程序并让 Plesk 控制面板访问托管服务器。发布后出现错误“不推荐使用非 JS 模块文件”。如果可能,请分享 LetsEncrypt Key 设置。 @BrijeshKumarTripathi 谢谢!您至少需要在B1 上使用App Service plan 才能使用Custom domains / SSL。当你拥有它时,使用Let's Encrypt Site Extension 来获取自动更新。 github.com/sjkp/letsencrypt-siteextension/wiki/How-to-install 感谢您的快速回复。我不是在 azure 上托管它。我将它托管在另一个托管服务提供商上,并且我的网站拥有 LetsEncrypt 证书。我想知道我是否明确需要在 appsettings.json 中配置它。我的应用程序是带有 Identity 的 Blazor Webassembly 托管应用程序,.NET 版本是 .NET 5。 @BrijeshKumarTripathi 没问题!不 - Let's Encrypt 仅用于 HTTPS,与 IdentityServer 或您的 appsettings.json 无关。 这意味着我不必在 appsettings.json 中提供设置来让 LetsEncrypt 证书在生产环境中工作。如果我错了,请纠正我。【参考方案2】:

好的,我已经用 thi question/answers解决了

在生产中需要使用证书,因此我创建了一个自签名证书并将其路径添加到 appsettings.json。

【讨论】:

以上是关于Blazor Web Assembly App .Net Core Hosted:发布运行时错误的主要内容,如果未能解决你的问题,请参考以下文章

Blazor Web Assembly 中的 window.focus/blur 事件

如何在 Blazor Web Assembly 中将 c# 变量传递给 javascript

在 Blazor Web Assembly 应用程序中显示本地计算机摄像头源

在刷新页面之前,Blazor Web Assembly (wasm) 不会使客户端 cookie 过期

带有 Azure B2C 的 Blazor Web Assembly 应用程序总是在页面加载后立即尝试进行身份验证

Blazor_WASM之4:路由