WebSpark.Bootswatch Complete Installation Guide
WebSpark.Bootstrap.Install.md Last updated: May 31, 2025 at 3:10 PM
WebSpark.Bootswatch Complete Installation Guide
A comprehensive guide for implementing dynamic Bootstrap theme switching in ASP.NET Core applications using WebSpark.Bootswatch.
๐ Table of Contents
- Overview
- Prerequisites
- Quick Start
- Detailed Installation
- Testing & Verification
- Customization Options
- Troubleshooting
- Best Practices
- Resources
๐ฏ Overview
WebSpark.Bootswatch enables dynamic Bootstrap theme switching in ASP.NET Core applications without page reloads. This guide provides complete implementation instructions with real-world examples.
Features
- โ Dynamic theme switching
- โ Theme persistence across sessions
- โ 20+ Bootswatch themes included
- โ Responsive dropdown component
- โ Performance optimized with caching
- โ No page reload required
๐ง Prerequisites
Before starting, ensure you have:
Requirement | Version | Notes |
---|---|---|
ASP.NET Core | 6.0+ | Tested with .NET 6, 7, 8, 9 |
Visual Studio | 2022+ | Or VS Code with C# extension |
Bootstrap | 5.0+ | Included via Bootswatch themes |
Basic Knowledge | - | ASP.NET Core MVC, Dependency Injection |
๐ Quick Start
For experienced developers, here's the minimal setup:
# Install packages
dotnet add package WebSpark.Bootswatch --version 1.10.3
dotnet add package WebSpark.HttpClientUtility --version 1.0.10
# Add to Program.cs
builder.Services.AddBootswatchThemeSwitcher();
app.UseBootswatchAll();
# Add to _ViewImports.cshtml
@addTagHelper *, WebSpark.Bootswatch
# Add to _Layout.cshtml
<bootswatch-theme-switcher />
๐ฆ Detailed Installation
1. Package Installation
1.1 Using Visual Studio Package Manager
- Right-click on your project in Solution Explorer
- Select Manage NuGet Packages
- Go to Browse tab
- Search for and install:
WebSpark.Bootswatch
(v1.10.3)WebSpark.HttpClientUtility
(v1.0.10)
1.2 Using Package Manager Console
Install-Package WebSpark.Bootswatch -Version 1.10.3
Install-Package WebSpark.HttpClientUtility -Version 1.0.10
1.3 Using .NET CLI
dotnet add package WebSpark.Bootswatch --version 1.10.3
dotnet add package WebSpark.HttpClientUtility --version 1.0.10
1.4 Manual Package Reference
Add to your .csproj
file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="WebSpark.Bootswatch" Version="1.10.3" />
<PackageReference Include="WebSpark.HttpClientUtility" Version="1.0.10" />
</ItemGroup>
</Project>
2. Configuration Setup
2.1 Create Required Directory
First, create the output directory for WebSpark operations:
# Windows PowerShell
New-Item -ItemType Directory -Force -Path "c:\temp\WebSpark\CsvOutput"
# Command Prompt
mkdir "c:\temp\WebSpark\CsvOutput"
# Bash/WSL
mkdir -p "/c/temp/WebSpark/CsvOutput"
2.2 Update appsettings.json
Add the WebSpark configuration section:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"WebSpark": {
"CsvOutputFolder": "c:\\temp\\WebSpark\\CsvOutput",
"HttpRequestResultPollyOptions": {
"RetryCount": 3,
"RetryDelayInSeconds": 1,
"TimeoutInSeconds": 30,
"CircuitBreakerHandledEventsAllowedBeforeBreaking": 5,
"CircuitBreakerDurationOfBreakInSeconds": 60
}
}
}
2.3 Update appsettings.Development.json
Ensure development environment has the same configuration:
{
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"WebSpark": "Debug"
}
},
"WebSpark": {
"CsvOutputFolder": "c:\\temp\\WebSpark\\CsvOutput",
"HttpRequestResultPollyOptions": {
"RetryCount": 2,
"RetryDelayInSeconds": 1,
"TimeoutInSeconds": 15,
"CircuitBreakerHandledEventsAllowedBeforeBreaking": 3,
"CircuitBreakerDurationOfBreakInSeconds": 30
}
}
}
3. Service Registration
3.1 Update Program.cs - Using Statements
Add the required using statements at the top of Program.cs
:
using WebSpark.ArtSpark.Client.Clients;
using WebSpark.ArtSpark.Client.Interfaces;
using WebSpark.Bootswatch;
using WebSpark.HttpClientUtility.ClientService;
using WebSpark.HttpClientUtility.RequestResult;
using WebSpark.HttpClientUtility.StringConverter;
3.2 Service Registration - Complete Example
Here's the complete service registration in the correct order:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
// Add HttpContextAccessor for Tag Helper support
builder.Services.AddHttpContextAccessor();
// Add HttpClient factory (required for WebSpark.HttpClientUtility)
builder.Services.AddHttpClient();
// Register WebSpark.HttpClientUtility services
builder.Services.AddSingleton<IStringConverter, SystemJsonStringConverter>();
builder.Services.AddScoped<IHttpClientService, HttpClientService>();
builder.Services.AddScoped<HttpRequestResultService>();
// Register IHttpRequestResultService with telemetry decorator
builder.Services.AddScoped<IHttpRequestResultService>(provider =>
{
IHttpRequestResultService service = provider.GetRequiredService<HttpRequestResultService>();
// Add Telemetry (basic decorator for logging and monitoring)
service = new HttpRequestResultServiceTelemetry(
provider.GetRequiredService<ILogger<HttpRequestResultServiceTelemetry>>(),
service
);
return service;
});
// Add WebSpark.Bootswatch theme switcher
builder.Services.AddBootswatchThemeSwitcher();
// Configure HttpClient for your application (example)
builder.Services.AddHttpClient<IArtInstituteClient, ArtInstituteClient>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseRouting();
// Configure WebSpark.Bootswatch (includes static files and style cache)
// IMPORTANT: This must be called after UseRouting() and before UseAuthorization()
app.UseBootswatchAll();
app.UseAuthorization();
app.MapStaticAssets();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.WithStaticAssets();
app.Run();
3.3 Service Registration Order (Critical!)
The order of service registration is important:
- โ
AddHttpClient()
- Must be first - โ
AddSingleton<IStringConverter, SystemJsonStringConverter>()
- โ
AddScoped<IHttpClientService, HttpClientService>()
- โ
AddScoped<HttpRequestResultService>()
- โ
AddScoped<IHttpRequestResultService>()
with decorator - โ
AddBootswatchThemeSwitcher()
- Must be last
4. View Integration
4.1 Update Views/_ViewImports.cshtml
Add the WebSpark.Bootswatch tag helpers:
@using WebSpark.ArtSpark.Demo
@using WebSpark.ArtSpark.Demo.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, WebSpark.Bootswatch
4.2 Tag Helper Verification
Verify tag helpers are working by checking IntelliSense shows:
<bootswatch-theme-switcher>
- Proper attribute completion
5. Layout Implementation
5.1 Update Views/Shared/_Layout.cshtml
Here's the complete layout file with WebSpark.Bootswatch integration:
@using WebSpark.Bootswatch.StyleCache
@inject IStyleCache StyleCache
@inject BootswatchThemeHelper BootswatchThemeHelper
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebSpark.ArtSpark Demo</title>
<!-- Dynamic Bootswatch Theme CSS -->
<link rel="stylesheet" href="@await BootswatchThemeHelper.GetThemeBootstrapUrlAsync()" />
<!-- Site-specific CSS -->
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">WebSpark.ArtSpark Demo</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Artwork" asp-action="Index">Artwork</a>
</li>
</ul>
<!-- WebSpark.Bootswatch Theme Switcher -->
<div class="navbar-nav">
<bootswatch-theme-switcher
dropdown-toggle-text="Theme"
dropdown-toggle-class="nav-link dropdown-toggle"
dropdown-menu-class="dropdown-menu dropdown-menu-end"
dropdown-item-class="dropdown-item" />
</div>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© @DateTime.Now.Year - WebSpark.ArtSpark Demo - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
<!-- Core JavaScript Libraries -->
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<!-- WebSpark.Bootswatch JavaScript (Required for theme switching) -->
<script src="~/lib/webspark-bootswatch/webspark-bootswatch.js"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
5.2 Key Layout Components Explained
Component | Purpose | Required |
---|---|---|
@inject IStyleCache StyleCache |
Caches theme CSS for performance | โ Yes |
@inject BootswatchThemeHelper BootswatchThemeHelper |
Provides theme URL generation | โ Yes |
@await BootswatchThemeHelper.GetThemeBootstrapUrlAsync() |
Dynamic theme CSS URL | โ Yes |
<bootswatch-theme-switcher> |
Theme dropdown component | โ Yes |
webspark-bootswatch.js |
Client-side theme switching logic | โ Yes |
5.3 Theme Switcher Customization Options
<!-- Basic theme switcher -->
<bootswatch-theme-switcher />
<!-- Customized theme switcher -->
<bootswatch-theme-switcher
dropdown-toggle-text="Choose Theme"
dropdown-toggle-class="btn btn-outline-secondary dropdown-toggle"
dropdown-menu-class="dropdown-menu dropdown-menu-dark"
dropdown-item-class="dropdown-item"
show-theme-name="true"
include-default-theme="true" />
<!-- Minimal theme switcher for mobile -->
<bootswatch-theme-switcher
dropdown-toggle-text="๐จ"
dropdown-toggle-class="btn btn-sm btn-link dropdown-toggle"
dropdown-menu-class="dropdown-menu dropdown-menu-end"
dropdown-item-class="dropdown-item small" />
๐งช Testing & Verification
Test Steps
1. Build and Run
# Build the project
dotnet build
# Run the application
dotnet run
2. Visual Verification Checklist
- Application starts without errors
- "Theme" dropdown appears in navigation
- Dropdown contains multiple theme options
- Selecting a theme changes the page appearance immediately
- Theme selection persists across page refreshes
- No JavaScript errors in browser console
- All page elements respond to theme changes
3. Browser Developer Tools Testing
- Network Tab: Verify Bootstrap CSS files load from CDN
- Console Tab: Check for JavaScript errors
- Application Tab: Verify theme preference is stored in localStorage
- Elements Tab: Confirm CSS URLs change when themes switch
4. Theme Testing Matrix
Test these popular themes to ensure proper functionality:
Theme | Background | Navigation | Buttons | Cards |
---|---|---|---|---|
Default | White | Light | Blue | White |
Cerulean | White | Blue | Blue | White |
Cosmo | White | Dark Blue | Orange | White |
Cyborg | Dark | Black | Red | Dark |
Darkly | Dark | Dark | Primary | Dark |
Flatly | White | Green | Green | White |
Journal | White | Light | Red | White |
Litera | White | Light | Blue | White |
Lumen | White | Light | Orange | White |
Lux | White | Dark | Gold | White |
Materia | White | Colorful | Pink | White |
Minty | White | Green | Green | White |
Morph | Light | Gradient | Blue | Light |
Pulse | White | Purple | Purple | White |
Quartz | Light | Orange | Orange | Light |
Sandstone | White | Green | Green | White |
Simplex | White | Red | Red | White |
Sketchy | White | Hand-drawn | Blue | White |
Slate | Dark | Dark | Primary | Dark |
Solar | Dark | Dark Blue | Blue | Dark |
Spacelab | White | Blue | Blue | White |
Superhero | Dark | Dark | Orange | Dark |
United | White | Orange | Orange | White |
Vapor | Dark | Pink/Purple | Pink | Dark |
Yeti | White | Light | Blue | White |
Zephyr | White | Light | Blue | White |
๐จ Customization Options
Advanced Service Configuration
// Custom theme selection
builder.Services.AddBootswatchThemeSwitcher(options =>
{
// Only include specific themes
options.IncludeThemes = new[]
{
"default", "cerulean", "cosmo", "flatly",
"journal", "lumen", "pulse", "simplex"
};
// Set default theme
options.DefaultTheme = "lumen";
// Custom CDN base URL
options.CdnBaseUrl = "https://custom-cdn.example.com/bootswatch/";
// Cache configuration
options.CacheExpirationMinutes = 60;
});
// Custom HTTP client configuration
builder.Services.AddHttpClient("BootswatchClient", client =>
{
client.Timeout = TimeSpan.FromSeconds(10);
client.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
});
Custom CSS Integration
Create a custom-themes.css
file that adapts to theme changes:
/* Custom CSS that works with all Bootswatch themes */
:root {
--custom-shadow: 0 2px 4px rgba(0,0,0,0.1);
--custom-border-radius: 0.375rem;
}
.custom-card {
background-color: var(--bs-body-bg);
border: 1px solid var(--bs-border-color);
border-radius: var(--custom-border-radius);
box-shadow: var(--custom-shadow);
color: var(--bs-body-color);
}
.custom-button {
background-color: var(--bs-primary);
border-color: var(--bs-primary);
color: var(--bs-primary-text, white);
}
.custom-button:hover {
background-color: var(--bs-primary-bg-subtle);
border-color: var(--bs-primary-border-subtle);
}
/* Dark theme adaptations */
[data-bs-theme="dark"] .custom-card {
--custom-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
JavaScript Customization
// Custom theme change event handler
document.addEventListener('themeChanged', function(event) {
console.log('Theme changed to:', event.detail.theme);
// Custom logic when theme changes
updateCustomComponents(event.detail.theme);
// Analytics tracking
gtag('event', 'theme_change', {
'theme_name': event.detail.theme
});
});
function updateCustomComponents(theme) {
// Update charts, graphs, or other components
if (typeof Chart !== 'undefined') {
Chart.defaults.color = getComputedStyle(document.documentElement)
.getPropertyValue('--bs-body-color');
}
}
// Programmatically change theme
function setTheme(themeName) {
if (window.WebSparkBootswatch) {
window.WebSparkBootswatch.setTheme(themeName);
}
}
// Get current theme
function getCurrentTheme() {
return localStorage.getItem('bootswatch-theme') || 'default';
}
๐ Troubleshooting
Common Issues and Solutions
Issue 1: Theme Switcher Not Appearing
Symptoms:
- No dropdown in navigation
- Empty dropdown menu
Possible Causes & Solutions:
Cause | Solution |
---|---|
Tag helpers not registered | Add @addTagHelper *, WebSpark.Bootswatch to _ViewImports.cshtml |
Missing service registration | Verify AddBootswatchThemeSwitcher() in Program.cs |
Incorrect tag helper syntax | Check <bootswatch-theme-switcher> spelling and attributes |
Debug Steps:
<!-- Add to your view to debug -->
@{
var themeHelper = ViewContext.HttpContext.RequestServices
.GetService<BootswatchThemeHelper>();
}
<p>Theme Helper Available: @(themeHelper != null)</p>
Issue 2: Dependency Injection Errors
Error Messages:
Unable to resolve service for type 'IHttpRequestResultService'
Unable to resolve service for type 'IStringConverter'
Solution Checklist:
- Verify all using statements are added
- Check service registration order
- Ensure
AddHttpClient()
is called first - Confirm WebSpark.HttpClientUtility package is installed
Debug Registration:
// Add logging to verify service registration
builder.Services.AddBootswatchThemeSwitcher();
// Verify services are registered
var serviceProvider = builder.Services.BuildServiceProvider();
var themeHelper = serviceProvider.GetService<BootswatchThemeHelper>();
Console.WriteLine($"Theme Helper Registered: {themeHelper != null}");
Issue 3: Themes Not Loading
Symptoms:
- Theme dropdown works but appearance doesn't change
- CSS files return 404 errors
Solutions:
Problem | Fix |
---|---|
Missing UseBootswatchAll() |
Add after UseRouting() in Program.cs |
Incorrect CSS URL | Verify @await BootswatchThemeHelper.GetThemeBootstrapUrlAsync() |
CDN connectivity issues | Check network connectivity and firewall settings |
Cache issues | Clear browser cache and application cache |
Debug CSS Loading:
<!-- Debug theme URL generation -->
@{
var currentThemeUrl = await BootswatchThemeHelper.GetThemeBootstrapUrlAsync();
}
<p>Current Theme URL: @currentThemeUrl</p>
<!-- Test direct CDN access -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/flatly/bootstrap.min.css" />
Issue 4: JavaScript Errors
Common Errors:
webspark-bootswatch.js not found
Uncaught TypeError: Cannot read property 'setTheme'
Solutions:
- Verify JavaScript file reference:
<script src="~/lib/webspark-bootswatch/webspark-bootswatch.js"></script>
- Check file exists in
wwwroot/lib/webspark-bootswatch/
- Ensure script loads after jQuery and Bootstrap
Manual JavaScript Fix:
<!-- Fallback if automated script doesn't work -->
<script>
window.WebSparkBootswatch = {
setTheme: function(theme) {
localStorage.setItem('bootswatch-theme', theme);
location.reload();
}
};
</script>
Issue 5: Configuration Errors
Error: System.ArgumentNullException: Value cannot be null. (Parameter 'CsvOutputFolder')
Solution: Verify configuration in appsettings.json
:
{
"WebSpark": {
"CsvOutputFolder": "c:\\temp\\WebSpark\\CsvOutput"
}
}
Create Missing Directory:
New-Item -ItemType Directory -Force -Path "c:\temp\WebSpark\CsvOutput"
Issue 6: Performance Issues
Symptoms:
- Slow theme switching
- High memory usage
Optimizations:
// Enable response compression
builder.Services.AddResponseCompression();
// Configure caching
builder.Services.AddBootswatchThemeSwitcher(options =>
{
options.CacheExpirationMinutes = 120; // Increase cache time
});
// Add memory cache
builder.Services.AddMemoryCache();
Debug Logging Configuration
Add detailed logging to troubleshoot issues:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"WebSpark": "Debug",
"WebSpark.Bootswatch": "Trace",
"WebSpark.HttpClientUtility": "Debug"
}
}
}
Health Check Implementation
// Add health checks for WebSpark services
builder.Services.AddHealthChecks()
.AddCheck<BootswatchHealthCheck>("bootswatch");
// Custom health check
public class BootswatchHealthCheck : IHealthCheck
{
private readonly BootswatchThemeHelper _themeHelper;
public BootswatchHealthCheck(BootswatchThemeHelper themeHelper)
{
_themeHelper = themeHelper;
}
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
try
{
var url = await _themeHelper.GetThemeBootstrapUrlAsync();
return string.IsNullOrEmpty(url)
? HealthCheckResult.Unhealthy("Theme URL generation failed")
: HealthCheckResult.Healthy($"Theme URL: {url}");
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy("Bootswatch service error", ex);
}
}
}
๐ Best Practices
Performance Optimization
1. CDN and Caching Strategy
// Optimize caching configuration
builder.Services.AddBootswatchThemeSwitcher(options =>
{
// Cache themes for 2 hours in production
options.CacheExpirationMinutes = app.Environment.IsDevelopment() ? 5 : 120;
// Use faster CDN
options.CdnBaseUrl = "https://fastly.jsdelivr.net/npm/[email protected]/dist/";
});
// Add response caching
builder.Services.AddResponseCaching();
app.UseResponseCaching();
2. Bundle and Minification
<!-- Production optimization -->
<environment include="Development">
<link rel="stylesheet" href="@await BootswatchThemeHelper.GetThemeBootstrapUrlAsync()" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="@await BootswatchThemeHelper.GetThemeBootstrapUrlAsync()" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
Security Considerations
1. Content Security Policy (CSP)
// Add CSP header for external CDN access
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Content-Security-Policy",
"style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fastly.jsdelivr.net;");
await next();
});
2. HTTPS Enforcement
// Ensure all theme URLs use HTTPS
builder.Services.AddBootswatchThemeSwitcher(options =>
{
options.ForceHttps = true;
});
Accessibility Improvements
1. ARIA Labels and Screen Reader Support
<bootswatch-theme-switcher
dropdown-toggle-text="Theme"
dropdown-toggle-class="nav-link dropdown-toggle"
dropdown-menu-class="dropdown-menu dropdown-menu-end"
dropdown-item-class="dropdown-item"
aria-label="Change color theme"
role="button" />
2. Keyboard Navigation
/* Ensure theme switcher is keyboard accessible */
.dropdown-toggle:focus {
outline: 2px solid var(--bs-primary);
outline-offset: 2px;
}
.dropdown-item:focus {
background-color: var(--bs-primary);
color: var(--bs-primary-text, white);
}
Mobile Optimization
/* Responsive theme switcher */
@media (max-width: 768px) {
.bootswatch-theme-switcher .dropdown-menu {
position: fixed !important;
top: auto !important;
left: 10px !important;
right: 10px !important;
width: auto !important;
max-height: 50vh;
overflow-y: auto;
}
}
Testing Strategy
Unit Tests
[Test]
public async Task BootswatchThemeHelper_GetThemeUrl_ReturnsValidUrl()
{
// Arrange
var services = new ServiceCollection();
services.AddBootswatchThemeSwitcher();
var provider = services.BuildServiceProvider();
var helper = provider.GetService<BootswatchThemeHelper>();
// Act
var url = await helper.GetThemeBootstrapUrlAsync("flatly");
// Assert
Assert.That(url, Is.Not.Null);
Assert.That(url, Does.Contain("flatly"));
Assert.That(url, Does.StartWith("https://"));
}
Integration Tests
[Test]
public async Task ThemeSwitcher_RendersCorrectly()
{
// Arrange
var factory = new WebApplicationFactory<Program>();
var client = factory.CreateClient();
// Act
var response = await client.GetAsync("/");
var content = await response.Content.ReadAsStringAsync();
// Assert
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
Assert.That(content, Does.Contain("bootswatch-theme-switcher"));
Assert.That(content, Does.Contain("webspark-bootswatch.js"));
}
๐ Resources
Official Documentation
- WebSpark.Bootswatch NuGet Package
- WebSpark.HttpClientUtility Documentation
- Bootswatch Official Website
- Bootstrap 5 Documentation
CDN Resources
Theme Previews
ASP.NET Core Resources
Community Resources
๐ Version History
Version | Date | Changes |
---|---|---|
1.0.0 | 2025-05-30 | Initial comprehensive installation guide |
Complete implementation with WebSpark.ArtSpark.Demo | ||
Detailed troubleshooting and best practices | ||
Performance optimization guidelines |
๐ง Support
If you encounter issues not covered in this guide:
- Check the troubleshooting section above
- Review the GitHub repository for known issues
- Search Stack Overflow with the
webspark-bootswatch
tag - Create a minimal reproduction of your issue
- File an issue with detailed information
โก Quick Reference Commands
# Install packages
dotnet add package WebSpark.Bootswatch --version 1.10.3
dotnet add package WebSpark.HttpClientUtility --version 1.0.10
# Create output directory
mkdir "c:\temp\WebSpark\CsvOutput"
# Build and run
dotnet build && dotnet run
๐ฏ Essential Files to Modify
- โ
Program.cs
- Service registration - โ
appsettings.json
- Configuration - โ
Views/_ViewImports.cshtml
- Tag helpers - โ
Views/Shared/_Layout.cshtml
- Theme integration
This guide was created based on a successful implementation with WebSpark.Bootswatch v1.10.3 and ASP.NET Core. For the most up-to-date information, always refer to the official NuGet package documentation.