Swashbuckle.AspNetCore + Blazor - 在运行时动态 Add/Remove 自定义 .css 文件

Swashbuckle.AspNetCore + Blazor - Dynamically Add/Remove custom .css file at runtime

我有 Blazor Webassembly ASP.NET 核心托管,我安装了 Swashbuckle.AspNetCore 以显示我的 Blazor 应用程序具有的端点(/swagger 端点)。
我的 Startup.Configure 看起来像这样(只有 swagger 部分):

            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");
            });

如您所见,我注入了自定义的 .css 文件,该文件有效。

在我的 Blazor 应用程序中,我注入了 swagger,所以我的页面看起来像这样(.razor 页面):

<iframe src="swagger"/>

同样,它工作正常,显示了 swagger 文档并且它有深色主题。

我注意到(毫不奇怪)这个 iframe 有一个 link 到这个 .css 文件:

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

删除此 link 会带来默认的 swagger 外观(浅色主题)。

我的应用程序的用户可以在整个应用程序中选择他想要的主题 (light/dark)。我的问题是,我如何动态 inject/remove(或者 enable/disable)这个 .css 文件,所以根据用户选择的应用程序主题,swagger 将显示默认(浅色)或深色主题(使用那个 .css 文件)?

我找不到关于这个问题的任何相关信息,所以我决定提出这个问题。我感谢任何帮助。谢谢。

好的,我明白了。答案是:使用JsInterop。

我的 .razor 页面目前看起来像这样:

@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);
}

我做到了 iframe 根据应用主题切换。 ToggleSwaggerTheme 函数是不言自明的——我正在调用我的 JS 函数来切换 swagger 的主题。

index.html 中,我添加了一个脚本来加载我的 helperFunctions.js(在正文中),其中可以找到 toggleSwaggerTheme 函数:

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

我在 wwwroot 中添加了 helperFunctions.js:
wwwroot -> js -> helperFunctions.js

我的 helperFunctions.js 看起来像这样:

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;
        }
    }
}

以上功能允许我切换 swagger 主题。请注意,我不知道这是否是可以创建的最佳解决方案。另外,我不确定它在生产环境中的表现如何。如果生产中有任何问题,我会更新这个答案。我希望它可以帮助某人。

上线后更新:

我在上线后显示深色主题时遇到了一些问题。但以下似乎解决了这个问题: 在 Program.cs (服务器端)中,我在 CreateHostBuilder 方法中添加了(不确定是否需要):

    webBuilder.UseStaticWebAssets();

所以在我的例子中,它看起来像这样:

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

我还更改了我的 swaggerDark.css 文件 属性:Copy to Output DirectoryCopy always。 您可以通过在“解决方案资源管理器”->“属性”(最后)中右键单击该文件来执行此操作。
完成这些新步骤后,它似乎工作正常。我希望它可以帮助某人。