Scoped CSS issue in Blazor Server

985 Views Asked by At

I am working on a Blazor Server app (.NET 7) deployed to an Azure App Service and looking to make some changes to the theme, starting with the Navbar.

In a standard Blazor app scaffold the MainLayout.razor and NavBar.razor components both have a scoped css file, MainLayout.razor.css and NavBar.razor.css respectively.

I can make changes (just colors) to these files and run the app locally and it works perfectly.

However, once the app is deployed, it's like the changes are not there. It uses the old css from the original template. This is NOT a browser cache issue, as I have cleared this repeatedly, used private windows, different browsers, different machines etc.

The only difference I can see is that the build configuration for the deploy is "Release" as opposed to "Development" when run locally. So I tried changing this option in my pipeline to see if that fixes it (even though this would not be a good solution) and the result was the same - the "old" css is used.

The weird thing is that if I run locally with the "Release" build option, I get no scoped CSS at all. The components get nothing, and render as plain text...

I saw some other posts which recommended setting the host to use static web assets, so adding to program.cs:

builder.WebHost.UseStaticWebAssets();

This works locally (even with "Release" build configuration), however when deployed this causes the app service container to crash on startup. I also am specifically told NOT to use this option in deployed apps in Microsoft's documentation here:

https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/static-files?view=aspnetcore-7.0#static-files-in-non-development-environments-for-blazor-server-apps

I also suspected that this is actually something strange with the Azure App Service, however this is a development slot which has no other services in front of it which could be caching the css.

I thought perhaps the app service itself was doing this, but it has now been several days since code with the old css has been deployed to this slot, so I do not think this is the case.

I also referred to the documentation here:

https://learn.microsoft.com/en-us/aspnet/core/blazor/components/css-isolation?view=aspnetcore-7.0

And according to those docs these scoped css files should "just work", however I went ahead and explicitly set the below options just to be sure:

<PropertyGroup>
  <DisableScopedCssBundling>false</DisableScopedCssBundling>
  <ScopedCssEnabled>true</ScopedCssEnabled>
</PropertyGroup>

And still no result.

I have now tried deploying the app to a brand new app service slot, and I found that it is not getting ANY of the scoped CSS (just like when I test the Release build locally) -- the page loads in plain text on this fresh slot.

So probably I have broken something with css isolation in the app - but it is not apparent where or how this could have occurred. Any tips on where to look on this would be appreciated.

I have found now that the build/deploy pipeline was not including ANY css in the published zip package. This turned out to be due to the way the pipeline was set up. What is still mysterious to me is how it ever worked before, but I have the fix now so that's not so important anymore.

The relevant section of the pipeline code was:

    steps:
    - task: UseDotNet@2
      inputs:
       installationPath: $(Agent.ToolsDirectory)/dotnet
       packageType: sdk
       version: 7.x
      
    - task: DotNetCoreCLI@2
      inputs:
        command: 'build'
        configuration: $(buildConfiguration)
        projects: |
          $(workingDirectory)/*.csproj
        arguments: --output $(System.DefaultWorkingDirectory)/publish_output --configuration $(buildConfiguration)

    - task: ArchiveFiles@2
      displayName: 'Archive files'
      inputs:
        rootFolderOrFile: '$(System.DefaultWorkingDirectory)/publish_output'
        includeRootFolder: false
        archiveType: zip
        archiveFile: $(Build.ArtifactStagingDirectory)/web-$(Build.BuildId).zip
        replaceExistingArchive: true

    - publish: $(Build.ArtifactStagingDirectory)/web-$(Build.BuildId).zip
      artifact: drop

What this does is running the build in 'Release' mode, zips up the build output, and dropping it in the Pipeline workspace for the deploy step to pick up after. The problem is it does not include any of the needed css assets.

3

There are 3 best solutions below

1
On BEST ANSWER

It does look like an issue I had in the past. Here is the S.O. that I opened to find the solution Azure include {Assembly}.styles.css in generated packages

I was missing the publish part of the pipeline.

  • task: DotNetCoreCLI@2

displayName: 'dotnet publish'

inputs:

command: publish

projects: |

'**\xxx.csproj'

configuration: 'Release'

arguments: '--output $(Build.ArtifactStagingDirectory)/$(buildConfiguration)'

0
On

It turns out that non-Development builds do not include the .css files in the output. I had to add a publish step to this and the PUBLISH artifact includes all of the resources as you'd expect:

New YAML:

    - task: UseDotNet@2
      displayName: Get .NET 7
      inputs:
       installationPath: $(Agent.ToolsDirectory)/dotnet
       packageType: sdk
       version: 7.x

    - task: DotNetCoreCLI@2
      displayName: Build
      inputs:
        command: build
        projects: $(workingDirectory)/*.csproj
        arguments: '--configuration $(buildConfiguration)'
    - task: DotNetCoreCLI@2
      displayName: Publish
      inputs:
        command: 'publish'
        publishWebProjects: false
        projects: $(workingDirectory)/*.csproj
        arguments: '--output $(build.artifactstagingdirectory) --configuration $(buildConfiguration)'
        zipAfterPublish: true

    - task: PublishPipelineArtifact@1
      inputs:
        fileSharePath: $(build.artifactstagingdirectory)
        ArtifactName: 'drop'
        publishLocation: pipeline

This runs the publish command directly to the same location the previous version did. I also had to make a minor update to the path that the deploy step was using to grab the zip package due to different folder structure of the output:

'$(Pipeline.Workspace)/drop/*.zip'

To this:

'$(Pipeline.Workspace)/drop/a/*.zip'

With the above changes the problem is solved.

3
On

I had a test in my side, as you can see, I changed a style in MainLayout.razor.css and publish it to Azure web, it worked. I first published the origin app to Azure first then changed the style and published again.

enter image description here enter image description here