Azure DevOps部署ASP.NET Core 6 MVC+MudBlazor应用登录异常排查
我拥有一个包含多个Azure Functions微服务、若干共享项目,以及一个集成MudBlazor的ASP.NET Core 6 MVC Web应用的解决方案。
通过Visual Studio 2022单独部署所有组件时,一切运行正常。但使用Azure DevOps发布流水线部署后,Azure Functions部署正常,Web应用可正常启动,然而尝试登录时出现以下异常:
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: ExpectedStartOfValueNotFound, < Path: $ | LineNumber: 0 | BytePositionInLine: 0.System.Text.Json.JsonException: ExpectedStartOfValueNotFound, < Path: $ | LineNumber: 0 | BytePositionInLine: 0.
---> System.Text.Json.JsonReaderException: ExpectedStartOfValueNotFound, < LineNumber: 0 | BytePositionInLine: 0.
at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& , ExceptionResource , Byte , ReadOnlySpan1 ) at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte ) at System.Text.Json.Utf8JsonReader.ReadFirstToken(Byte ) at System.Text.Json.Utf8JsonReader.ReadSingleSegment() at System.Text.Json.Utf8JsonReader.Read() at System.Text.Json.Serialization.JsonConverter1[[MyProject.Platform.Shared.Wrapper.Result`1[[MyProject.Platform.Application.Features.Accounts.Queries.GetById.GetProjectByIdResponse, PublicKeyToken=null]].ReadCore(Utf8JsonReader& , JsonSerializerOptions , ReadStack& ) Exception_EndOfInnerExceptionStack at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& , JsonReaderException ) at System.Text.Json.Serialization.JsonConverter`1[[MyProject.Platform.Shared.Wrapper.Result`1[[MyProject.Platform.Application.Features.Accounts.Queries.GetById.GetProjectByIdResponse,
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task , ComponentState )
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: Unexpected character encountered while parsing value: T. Path '', line 0, position 0. Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: T. Path '', line 0, position 0. at Newtonsoft.Json.JsonTextReader.ParseValue() at Newtonsoft.Json.JsonTextReader.Read() at Newtonsoft.Json.JsonReader.ReadAndMoveToContent() at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[Object](String value, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[Object](String value) at at Toolbelt.Blazor.HttpClientInterceptor.InvokeAsync(HttpClientInterceptorEventHandler asyncEventHandler, HttpClientInterceptorEventArgs args) at Toolbelt.Blazor.HttpClientInterceptor.InvokeAfterSendAsync(HttpClientInterceptorEventArgs args) at Toolbelt.Blazor.HttpClientInterceptorHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage , HttpCompletionOption , CancellationTokenSource , Boolean , CancellationTokenSource , CancellationToken ) at at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task) at Microsoft.AspNetCore.Components.Forms.EditForm.HandleSubmitAsync() at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task) at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task , ComponentState ) Failed to load resource: the server responded with a status of 405 (Method Not Allowed)
同时还返回了405(Method Not Allowed)状态码错误。
以下是我使用的Azure DevOps流水线YAML配置:
trigger: - development - master pool: vmImage: 'windows-latest' variables: solution: '**/*.sln' buildPlatform: 'Any CPU' buildConfiguration: 'Debug' publishPath: '$(Build.ArtifactStagingDirectory)/publish' stages: - stage: BuildApp displayName: Build Apps jobs: - job: BuildApp displayName: Build App steps: - task: DotNetCoreInstaller@2 displayName: 'Install .NET 6 SDK' inputs: version: '6.x' - task: DotNetCoreInstaller@2 displayName: 'Install .NET 7 SDK' inputs: version: '7.x' - task: DotNetCoreCLI@2 displayName: 'Install WebAssembly tools for .NET 6' inputs: command: 'custom' custom: 'workload' arguments: 'install wasm-tools-net6' workingDirectory: '$(Agent.ToolsDirectory)/dotnet' - task: DotNetCoreInstaller@2 displayName: 'Install .NET 3 SDK' inputs: version: '3.x' - task: NuGetToolInstaller@1 inputs: versionSpec: '6.5' - task: NuGetCommand@2 inputs: command: 'restore' restoreSolution: '$(System.DefaultWorkingDirectory)/WebApp/MyProject.Platform.sln' feedsToUse: 'config' nugetConfigPath: '$(System.DefaultWorkingDirectory)/nuget.config' arguments: '-Parallel' - task: MSBuild@1 displayName: 'BUILD!!' inputs: solution: '$(System.DefaultWorkingDirectory)/WebApp/MyProject.Platform.sln' msbuildArchitecture: 'x64' platform: 'any cpu' configuration: $(buildConfiguration) - task: DotNetCoreCLI@2 inputs: command: 'build' projects: '$(System.DefaultWorkingDirectory)/WebApp/MyProject.Platform.WebApp/Server/MyProject.Platform.Server.csproj' arguments: '--configuration Debug --output $(Build.ArtifactStagingDirectory)' - task: DotNetCoreCLI@2 displayName: 'Publish' inputs: command: 'publish' publishWebProjects: True projects: '$(System.DefaultWorkingDirectory)/WebApp/MyProject.Platform.WebApp/Server/MyProject.Platform.Server.csproj' arguments: '--configuration Debug --output $(Build.ArtifactStagingDirectory)' zipAfterPublish: true - task: CopyFiles@2 inputs: targetFolder: '$(Build.ArtifactStagingDirectory)' - task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: drop'
请问我在部署流程中存在哪些错误操作,导致了上述问题?
1. 重复构建/发布引发文件冲突
流水线中连续执行了MSBuild、dotnet build和dotnet publish三个构建/发布步骤,会导致$(Build.ArtifactStagingDirectory)目录下的文件被多次覆盖,可能丢失WebAssembly客户端静态资源或后端API路由配置文件,进而引发API请求的405错误和JSON解析失败。
正确做法是只保留dotnet publish步骤,因为publish命令会自动完成restore、build和打包的完整流程,无需额外执行build或MSBuild。
2. Debug配置部署的潜在问题
流水线使用Debug配置发布,而Visual Studio部署通常默认用Release配置。Debug配置下可能包含调试钩子、未优化代码,甚至部分API路由行为与Release模式不同,也可能引发CORS或路由匹配问题。建议将buildConfiguration变量改为Release。
3. 冗余SDK安装导致版本混淆
项目基于ASP.NET Core 6,无需安装.NET 3和.NET 7 SDK,多余的SDK可能导致构建时使用错误的.NET版本,引发兼容性问题。应移除.NET 3和.NET 7的安装步骤,只保留.NET 6 SDK和对应的wasm-tools-net6 workload。
4. 无效的CopyFiles步骤
当前CopyFiles步骤未指定源文件路径,相当于没有执行任何操作,应直接删除该步骤,避免流程混淆。
修正后的流水线核心步骤示例
variables: buildConfiguration: 'Release' # 改为Release配置 stages: - stage: BuildApp displayName: Build Apps jobs: - job: BuildApp displayName: Build App steps: - task: DotNetCoreInstaller@2 displayName: 'Install .NET 6 SDK' inputs: version: '6.x' - task: DotNetCoreCLI@2 displayName: 'Install WebAssembly tools for .NET 6' inputs: command: 'custom' custom: 'workload' arguments: 'install wasm-tools-net6' workingDirectory: '$(Agent.ToolsDirectory)/dotnet' - task: NuGetToolInstaller@1 inputs: versionSpec: '6.5' - task: DotNetCoreCLI@2 displayName: 'Publish Web App' inputs: command: 'publish' projects: '$(System.DefaultWorkingDirectory)/WebApp/MyProject.Platform.WebApp/Server/MyProject.Platform.Server.csproj' arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)' zipAfterPublish: true - task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: drop'
额外排查点
- 检查Web应用的API路由配置,确认登录接口的HTTP方法(POST/GET)是否与前端请求一致,405错误通常是请求方法不匹配导致的。
- 确认Azure App Service的启动命令是否正确,避免因启动参数错误导致后端API未正常加载。
内容的提问来源于stack exchange,提问作者mkr231

