Blazor

Installation

To monitor Blazor applications, we will add both Raygun4NET which provides C#/Razor error monitoring and Raygun4JS which is a JavaScript library that will handle client side javascript error monitoring.


You can install the Raygun NuGet packages either using the Nuget Package manager in your IDE or using the .NET CLI as shown bellow.

  1. In your Blazor Server project folder run:
dotnet add package Mindscape.Raygun4Net.AspNetCore
  1. In your Blazor Client project folder run:
dotnet add package Mindscape.Raygun4Net.NetCore

In wwwroot/index.html add this snippet to your markup immediately before the closing </head> tag:

<script type="text/javascript">
  !function(a,b,c,d,e,f,g,h){a.RaygunObject=e,a[e]=a[e]||function(){
  (a[e].o=a[e].o||[]).push(arguments)},f=b.createElement(c),g=b.getElementsByTagName(c)[0],
  f.async=1,f.src=d,g.parentNode.insertBefore(f,g),h=a.onerror,a.onerror=function(b,c,d,f,g){
  h&&h(b,c,d,f,g),g||(g=new Error(b)),a[e].q=a[e].q||[],a[e].q.push({
  e:g})}}(window,document,"script","//cdn.raygun.io/raygun4js/raygun.min.js","rg4js");
</script>

This will fetch the Raygun4JS script from our CDN asynchronously so it doesn't block the page load.


Add the following code to your appsettings.json.
(Note: if you're using another type of config, add it there)

"RaygunSettings": {
  "ApiKey": "paste_your_api_key_here"
}

Your app API key is displayed when you create a new application in your Raygun account, or can be viewed in the application settings.

Paste this at the bottom of the <body> section in Pages/_Host, just below the line: <script src="_framework/blazor.webassembly.js"></script>

<script type="text/javascript">
  rg4js('apiKey', 'paste_your_api_key_here');
  rg4js('trackEvent', {  type: 'pageView', path: window.location.pathname});
  rg4js('enableCrashReporting', true);
  rg4js('enablePulse', true); <!-- optional, enable RealUserMonitoring -->
  window.rg4js = rg4js;     <!-- This is needed to connect Raygun4JS with Blazor callbacks -->
</script>

For client side error reporting, you can skip step 3.


Configure the RaygunAspNetCore Middleware to handle exceptions that have been triggered on the server and send them to Raygun automatically. For errors thrown inside Razor components, see the next section.

In Program.cs:

  1. Add using Mindscape.Raygun4Net.AspNetCore; to your using statements.
  2. Add builder.Services.AddRaygun(builder.Configuration); .
  3. Add app.UseRaygun(); after any other ExceptionHandling methods e.g. app.UseDeveloperExceptionPage() or app.UseExceptionHandler("/Home/Error").

Your code should look similar to the following:

using Mindscape.Raygun4Net.AspNetCore;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRaygun(builder.Configuration);
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseWebAssemblyDebugging();
}
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.UseRaygun();
app.UseHttpsRedirection();

app.UseBlazorFrameworkFiles();
app.UseStaticFiles();

app.UseRouting();


app.MapRazorPages();
app.MapControllers();
app.MapFallbackToFile("index.html");

app.Run();

As there is no middleware pipeline that processes requests for Razor components, exceptions cannot be caught and dealt with globally. However, you can use an error processing component as a cascading value to process errors in a centralized way. Even so, you'll need to manually catch exceptions that occur inside your Razor components and then pass it to the Error component.

Create a new <Error> component.

Shared/Error.razor:

@using Mindscape.Raygun4Net
@inject IConfiguration Configuration

<CascadingValue Value="this">
    @ChildContent
</CascadingValue>

@code {

    [Parameter]
    public RenderFragment ChildContent { get; set; } = null!;

    RaygunClient Raygun => new RaygunClient(Configuration["RaygunSettings:ApiKey"]);

    public void ProcessError(Exception ex)
    {
        Raygun.SendInBackground(ex);
    }
}

Wrap the <Router> component in the new <Error> component

/App.razor:

<Error>
    <Router ...>
        ...
    </Router>
</Error>

Once this is setup you can catch exceptions in your components, and send them to Raygun.

Pages/SomePage.razor:

@page "/SomePage"

<PageTitle>SomePage</PageTitle>

<h1>SomePage</h1>

<button class="btn btn-primary" @onclick="OnClick">Click me</button>

@code {

    [CascadingParameter]
    public Error Error { get; set; } = null!;

    private void OnClick()
    {
        try
        {
           // ... Your code
        }
        catch (Exception e)
        {
            Error.ProcessError(e);
            throw;
        }
    }
}

For more details on the Raygun4Net.AspNetCore provider and additional documentation about this provider and configuration options that can be specified, please see the documentation for the ASP.NET Core provider.

For more details about the Raygun4JS provider and additional documentation about this provider and configuration options that can be specified, please see the documentation for the JavaScript provider.


Deploy Raygun into your production environment for best results, or raise a test exception. Once we detect your first error event, the Raygun app will automatically update.


User Tracking (optional)

Setup server side user tracking by setting the following information against the active RaygunClient instance.

raygunClient.UserInfo = new RaygunIdentifierMessage("users_email_address@domain.com")
{
  IsAnonymous = false,
  FullName = "Firstname Lastname",
  FirstName = "Firstname"
};

Setup client side user tracking by adding the following information to the script block at the bottom of the page in Pages/_Host.

rg4js('setUser', {
  identifier: 'users_email_address_or_unique_id',
  isAnonymous: false,
  email: 'users_email_address@domain.com',
  firstName: 'Firstname',
  fullName: 'Firstname Lastname'
});

Alternatively, this can be provided from a server rendered code section by using a JavaScript invoke call:

var userData = new
{
  Identifier = "users_email_address_or_unique_id",
  IsAnonymous = false,
  Email = "users_email_address@domain.com",
  FirstName = "Firstname",
  FullName = "Firstname Lastname"
};

await JSRuntime.InvokeVoidAsync("rg4js", "setUser", userData);

These providers are open source and are available from the Raygun4Net repository and the Raygun4JS repository