user1206480
user1206480

Reputation: 1858

Custom Middleware is causing Blazor Server-side page to stop working

My custom middleware appears to be causing some sort of conflict with my blazor server-side page. The sample middleware in short checks for a bool status and if true redirects to the counter page provided by the out of the box blazor template. Without the middleware inserted into the pipeline the counter page works just fine when you click the button, but once the middleware is placed in the pipeline the button no longer works, as it does not increment the count. I've placed the custom middleware right before the app.UseEndpoints middleware, though it appears it doesn't matter where it's placed, as it doesn't work no matter the order that it's in. Why is my custom middleware breaking the blazor server-side page from functioning properly?

middleware:

class CheckMaintenanceStatusMiddleware
{
    private readonly RequestDelegate _next;
    public CheckMaintenanceStatusMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {


        var statusCheck = true;

        if(statusCheck && context.Request.Path.Value != "/counter")
        {
            context.Response.Redirect("/counter");
        }
        else
        {
            await _next.Invoke(context);
        }
    }

}

public static class CheckMaintenanceStatusMiddlewareExtension
{
    public static IApplicationBuilder UseCheckMaintenanceStatus(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<CheckMaintenanceStatusMiddleware>();
    }
}

configure method in Startup file:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{


    var connectionString = Configuration.GetConnectionString("DefaultConnection");
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }

    app.UseHttpsRedirection();

    app.UseStaticFiles();


    app.UseCookiePolicy();

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseCheckMaintenanceStatus();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToPage("/_Host");
    });

}

Upvotes: 7

Views: 7046

Answers (3)

Gaurang Thakkar
Gaurang Thakkar

Reputation: 31

This is old post. But I am using app_offline.htm page to stop the blazor app

I put it in the root (content root folder) and have just plain html which says "Site is under maintenance"

This page will terminate all request and all blazor hub connection.

Then, when I am done updating my app, I rename this file to app_offline2.htm

Meaning "app_offline.htm" is a special file name used my framework and Core to determine if any request can be served by application.

Upvotes: 0

Corey Weathers
Corey Weathers

Reputation: 419

I suspect what's happening here is

  • The browser goes to the app URL and attempts to negotiate a SignalR connection.
  • SignalR returns the protocol and token to use to successfully connect to the Hub (using "/_blazor?id=token_value").

Unfortunately the custom middleware is redirecting every request, so it ends up stopping the application from doing the initial connection to the hub (triggering a bunch of console errors) - though I was able to successfully redirect to "/counter". But because the middleware is stopping the SignalR connection, it breaks the connection from the client to the server which is necessary for Blazor Server apps.

I would suggest moving this check from middleware. You could try creating a service that can return if the app is in maintenance mode, add a service call to the Index.razor component, and then render a "Maintenance Mode" component if necessary.

Upvotes: 1

Nan Yu
Nan Yu

Reputation: 27588

With your code , the blazor negotiate url is also been redirect so negotiate won't work .

Try below codes which avoid that :

if (statusCheck && context.Request.Path.Value != "/counter"&& !context.Request.Path.Value.StartsWith("/_blazor"))
{
    context.Response.Redirect("/counter");
}
else
{
    await _next.Invoke(context);
}

Upvotes: 5

Related Questions