0
votes

I have Blazor Webassembly ASP.NET Core hosted and I installed Swashbuckle.AspNetCore to display endpoints that my Blazor app has (/swagger endpoint).
My Startup.Configure looks like this (only swagger part):

            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                foreach (var description in provider.ApiVersionDescriptions)
                {
                    c.SwaggerEndpoint($"{description.GroupName}/swagger.json", $"v{description.GroupName.ToUpperInvariant()}");
                }

                c.InjectStylesheet("/css/swaggerDark.css");
            });

As you can see, I inject custom .css file which works.

In my Blazor app, I inject swagger so my page looks like this (.razor page):

<iframe src="swagger"/>

Again, it works correctly, swagger documentation is displayed and it has dark theme.

I have noticed (to no suprise) that this iframe has a link to this .css file:

<link href="/css/swaggerDark.css" rel="stylesheet" media="screen" type="text/css">

Removing this link brings the default swagger look (light theme).

The user of my app can choose which theme he wants (light/dark) of the whole application. My question is, how do I dynamically inject/remove (or maybe enable/disable) this .css file so depending on which app theme the user chooses, the swagger will either display default (light) or dark theme (using that .css file)?

I couldn't find any relevant info on this issue so I decided to create this question. I appreciate any help. Thank you.

1

1 Answers

0
votes

Ok, I figured it out. The answer is: use JsInterop.

My .razor page looks like this at the moment:

@page "/something"
@inject IJSRuntime JS //needed to call InvokeVoidAsync

    //I made my own ThemeManager to control the Blazor app theme
    @if (ThemeManager.IsDefaultTheme)
    {
        <iframe id="myiframe" src="swagger" @onload="() => ToggleSwaggerTheme(true)" />
    }
    else
    {
        <iframe id="myiframe" src="swagger" @onload="() => ToggleSwaggerTheme(false)" />
    }

@code {
    private async Task ToggleSwaggerTheme(bool isLight) => await JS.InvokeVoidAsync("toggleSwaggerTheme", isLight);
}

I made it so the iframe toggles depending on the app theme. The ToggleSwaggerTheme function is self-explanatory - I'm calling my JS function to toggle the theme of swagger.

In index.html I added a script to load my helperFunctions.js (in body) in which toggleSwaggerTheme function can be found:

<script src="/js/helperFunctions.js"></script>

I added helperFunctions.js in my wwwroot:
wwwroot -> js -> helperFunctions.js

My helperFunctions.js looks like this:

function toggleSwaggerTheme(isLight) {
    let myiframe = document.getElementById('myiframe');
    let styleSheets = myiframe.contentWindow.document.styleSheets;
    for (let i = 0; i < styleSheets.length; i++) {
        if (styleSheets[i].href == null) {
            continue;
        }

        if (styleSheets[i].href.includes("/css/swaggerDark.css")) {
            styleSheets[i].disabled = isLight;
            break;
        }
    }
}

The above function allowed me to toggle the swagger theme. Please note, I don't know if this is the best solution that can be created. Also, I'm not sure how it's going to behave in the production environment. I will update this answer if there are any problems in the production. I hope it can help somebody.

UPDATE AFTER GOING LIVE:

I've had some issues with displaying dark theme after going live. But the following seems to fix the issue: In Program.cs (Server side), in CreateHostBuilder method I added (not sure if it's needed):

    webBuilder.UseStaticWebAssets();

So in my case, it looks like this:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStaticWebAssets();
                webBuilder.UseStartup<Startup>();
            });

I also changed my swaggerDark.css file property: the Copy to Output Directory to Copy always. You do this by right-clicking the file in Solution Explorer -> Properties (at the end).
After doing these new steps, It seems to be working fine. I hope it can help somebody.