The setup
I have solution with quite few micro services in the form of Azure functions and a few shared projects and one MVC6 Mudblazor web app.
The Problem
When I deploy all of these components individually through Visual Studio 2022, everything works fine.
However, when I deploy these through an Azure Devops release pipeline, things start going crazy. Functions deploy fine. But the Webapp starts misbehaving. The webapp loads up fine but when i try to login, I get the following errors:
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.JsonConverter
1[[MyProject.Platform.Shared.Wrapper.Result1[[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)
This is the pipeline YAML I used:
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'
The question
What am I doing wrong here?
I was finally able to get it working. The issue was here:
- 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
When you give publishWebProjects: True
"If true, the task will try to find the web projects in the repository and run the publish command on them. Web projects are identified by presence of either a web.config file or wwwroot folder in the directory." - Azure devops info button
Due to this being true originally, it was selecting Client every time because the CLIENT project has a wwwroot folder. With publishWebProjects set to false, you can specify a particular SERVER project.
So, the SERVER project never got deployed.And that caused all of this havoc.
This is the change that finally fixed it:
- task: DotNetCoreCLI@2
displayName: 'Publish'
inputs:
command: 'publish'
publishWebProjects: False
projects: '$(System.DefaultWorkingDirectory)/WebApp/MyProject.Platform.WebApp/Server/MyProject.Platform.Server.csproj'
arguments: '--configuration Debug --output $(Build.ArtifactStagingDirectory)'
zipAfterPublish: true