ASP.NET Core

NuGet package with a middleware for ASP.NET Core applications (.NET 8 or later).

Markdown

If your SPA (Blazor WebAssembly, Angular, React, Vue…) is served by an ASP.NET Core application, Jazui.AspNetCore adds a middleware that handles bots before the static files and the index.html fallback. It's also the recommended option on IIS when the application is .NET.

Before you start

  • .NET 8 or later.
  • Your site verified in Jazui and your token.
  • The AstrolUI package source (https://nuget.astrolui.com/v3/index.json) added to NuGet.

Installation

Jazui.AspNetCore isn't on nuget.org: it's published in the AstrolUI NuGet package repository, https://nuget.astrolui.com/v3/index.json. Add that source once (in Visual Studio, from the command line or in a nuget.config) and then install the package like any other. The package carries the Jazui logo and its version follows the .NET version it's published with (for example 10.0.13.1); it works in .NET 8 or later applications.

In Visual Studio

  1. Open Tools › Options › NuGet Package Manager › Package Sources.
  2. Click +, type Name: AstrolUI and Source: https://nuget.astrolui.com/v3/index.json, click Update and then OK.
  3. Right-click your project and choose Manage NuGet Packages….
  4. Top right, under Package source, choose AstrolUI (or All).
  5. In Browse, search for Jazui.AspNetCore, pick the latest version and click Install.

If your solution has a nuget.config with <clear />, Visual Studio only uses that file's sources: add AstrolUI there (example below).

From the command line

Terminal
dotnet nuget add source https://nuget.astrolui.com/v3/index.json --name AstrolUI
dotnet add package Jazui.AspNetCore

With nuget.config

So the whole team and your CI get it without setting anything up, put a nuget.config next to your solution. If you already use package source mapping (packageSourceMapping), add the Jazui.* pattern to the AstrolUI source; otherwise packageSources is enough.

nuget.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
    <add key="AstrolUI" value="https://nuget.astrolui.com/v3/index.json" protocolVersion="3" />
  </packageSources>
  <!-- Solo si usas la asignación de orígenes: los paquetes Jazui.* salen de AstrolUI -->
  <packageSourceMapping>
    <packageSource key="AstrolUI">
      <package pattern="Jazui.*" />
    </packageSource>
    <packageSource key="nuget.org">
      <package pattern="*" />
    </packageSource>
  </packageSourceMapping>
</configuration>

Setup

Register the service and add the middleware before UseStaticFiles and MapFallbackToFile:

Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddJazui(builder.Configuration);

var app = builder.Build();
app.UseForwardedHeaders();   // solo si hay un proxy o CDN delante: la IP y el esquema del bot
app.UseJazui();              // antes de los archivos estáticos y del fallback de la SPA
app.UseStaticFiles();
app.MapFallbackToFile("index.html");
app.Run();
appsettings.json
{
  "Jazui": {
    "Token": "",
    "SiteUrl": ""
  }
}

Don't put the token in appsettings.json: in production use the Jazui__Token environment variable (or user secrets in development). UseForwardedHeaders is only needed if there's a proxy or CDN in front, so Jazui gets the bot's real IP and the https scheme.

Options

All are read from the Jazui configuration section and can also be changed in code:

OptionDefaultWhat for
Token—Account or site token. Without a token, the middleware does nothing.
ApiUrlhttps://api.jazui.comAPI address.
SiteUrl—Public domain when the application sees another one (proxy, tests).
Timeout20 sAfter this time the normal page is served.
ExcludedPaths/api, /_framework, /_content, /_blazorPaths that never go through Jazui (per segment: /api covers /api/x but not /apis).
ExtraBots—User agent fragments added to the bot list.
RemoteBotstrueDownloads Jazui's bot list at startup and every BotsRefreshInterval.
BotsRefreshInterval24 hHow often the list is downloaded again.
ReportUnknownBotstrueTells Jazui about bot-like agents that aren't on the list (without sending the page).
Program.cs
builder.Services.AddJazui(builder.Configuration, options =>
{
    options.Timeout = TimeSpan.FromSeconds(10);
    options.ExcludedPaths = ["/api", "/_framework", "/_content", "/_blazor", "/admin"];
    options.ExtraBots = ["mibotinterno"];
    options.BotsRefreshInterval = TimeSpan.FromHours(12);
});

What it does

For each bot request, it calls the API with the address (or SiteUrl plus the path), the user agent, the bot's IP (from Connection.RemoteIpAddress) and the If-None-Match. If Jazui answers with X-Jazui or a block, it copies the status, headers and body; if it's slow or fails, it logs a warning and continues with the rest of the application. The bot list version in use is in JazuiMiddleware.BotsVersion.

<p>Request your home page as if you were a bot, with the test user agent <code>integration-test</code>:</p><pre><code>curl -I -A "integration-test" https://mysite.com/</code></pre><p>The response must include <code>x-jazui: true</code>, with <code>x-jazui-cache: MISS</code> the first time and <code>HIT</code> afterwards. Without a bot user agent (<code>curl -I https://mysite.com/</code>) you should get your usual website, without <code>x-jazui</code>. In the dashboard, the request shows up in <b>Bot traffic</b> and the page in <b>Cached pages</b>.</p>

Request your home page as if you were a bot, with the test user agent integration-test:

curl -I -A "integration-test" https://mysite.com/

The response must include x-jazui: true, with x-jazui-cache: MISS the first time and HIT afterwards. Without a bot user agent (curl -I https://mysite.com/) you should get your usual website, without x-jazui. In the dashboard, the request shows up in Bot traffic and the page in Cached pages.

If something doesn't work

  • Jazui.AspNetCore isn't found: the AstrolUI source is missing, or your nuget.config has <clear /> or a source mapping without the Jazui.* pattern.
  • No x-jazui: UseJazui() must come before UseStaticFiles() and MapFallbackToFile; also check that the token arrives (Jazui__Token variable).
  • Behind IIS or a proxy, the URL comes out as http: configure UseForwardedHeaders or set SiteUrl.
  • Log warnings tell you why the normal page was served.