ASP.NET
This provider is compatible with the following frameworks:
- ASP.NET (Core) WebAPI
- ASP.NET (Core) MVC
See ASP.NET Framework for the .NET Framework version of these instructions.
Installation
Step 1 - Install the NuGet package
ASP.NET is supported through our Raygun4Net.AspNetCore provider.
The best way to install Raygun4Net.AspNetCore is to use the dotnet
CLI tool. Run the following command in your project folder to install it.
dotnet add package Mindscape.Raygun4Net.AspNetCore
NuGet documentation for the Mindscape.Raygun4Net.AspNetCore package can be found here.
Step 2 - Configure Raygun
This can be done through the appsettings.json
configuration file or in-code.
appsettings.json configuration:
Add a new section called RaygunSettings
"RaygunSettings": {
"ApiKey": "paste_your_api_key_here"
}
Pass the Configuration
object into the call to .AddRaygun
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRaygun(builder.Configuration);
In-code configuration:
Use a delegate to configure Raygun
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRaygun(settings =>
{
settings.ApiKey = "paste_your_api_key_here";
});
Step 3 - Add the Raygun middleware
This middleware will capture unhandled exceptions that occur durring a request.
var app = builder.Build();
app.UseRaygun();
/* The rest of your app setup */
You should call .UseRaygun
after any other exception handling middleware. eg., app.UseDeveloperExceptionPage()
or app.UseExceptionHandler("/Home/Error")
.
The above setup will capture all unhandled exceptions and send them to Raygun.
Step 4 - Release
For Raygun to capture unhandled exceptions, you will need to run your application in Production
mode (dotnet run --environment Production
). This way, unhandled exceptions will not be passed to the Development
exception handler. You can also raise a test exception like so:
app.MapGet("/throw", (Func<string>)(() => throw new Exception("Exception in request pipeline")));
Optional - Enhance your logging with Raygun
To fully leverage the capabilities of Raygun, we recommend integrating it into your logging pipeline. By doing so, any time a method like _logger.LogError()
is invoked, a report is also dispatched to Raygun. This can be easily achieved by using our Serilog Sinks Raygun provider.
Manually sending exceptions
A RaygunClient
singleton is added to the DI container when .AddRaygun()
is called. You can manually send exceptions by retrieving this RaygunClient
instance from the container and calling SendInBackground
.
Note that SendInBackground
should only be used for handled exceptions, otherwise the program may shut down before there is a chance to send the exception to Raygun. Unhandled exceptions should be sent using the SendAsync
method.
Example:
Pass in a RaygunClient
to the constructor of your class.
private readonly RaygunClient _raygunClient;
public MyClass(RaygunClient raygunClient)
{
_raygunClient = raygunClient;
}
Call SendInBackground
when handling exceptions within your class.
try
{
throw new Exception("Something has gone wrong");
}
catch (Exception e)
{
await _raygunClient.SendInBackground(e);
}
Throw exceptions to avoid missing stack traces
You may have code that detects that something has gone wrong but doesn't actually throw an exception. A .NET exception needs to be thrown in order for its stack trace to be populated. Ensure you throw exceptions before catching and sending it for the stack trace to be generated.
// Wont produce a stack trace
_raygunClient.SendInBackground(new Exception("Something has gone wrong"));
try
{
// Will produce a stack trace
throw new Exception("Something has gone wrong");
}
catch (Exception e)
{
await _raygunClient.SendInBackground(e);
}
Modify or cancel messages
On the RaygunClient
, attach an event handler to the SendingMessage
event. This event handler will be called just before any exception reports are sent to Raygun. The event arguments provide the RaygunMessage
object that is about to be sent.
There are two expected uses for this event handler:
- Modify the message: Change the
RaygunMessage
object before the exception report is sent to Raygun. - Cancel the message: Set
Cancel = true
on theRaygunMessage
to prevent the exception report from being sent to Raygun. Useful if the exception is from parts of the application you have no control over (such as third party packages).
Modifying a message example:
_raygunClient.SendingMessage += (sender, args) =>
{
args.Message.Details.Tags.Add("Fruits!");
};
Cancelling a message example:
_raygunClient.SendingMessage += (sender, args) =>
{
if ("BadServer".Equals(args.Message.Details.MachineName))
{
args.Cancel = true;
}
};
Additionally, the RaygunClient
can be configured by registering it with the Dependency Injection container. This provides a centralized location for the client to be configured.
builder.Services.AddSingleton(s =>
{
var client = new RaygunClient(s.GetService<RaygunSettings>()!, s.GetService<IRaygunUserProvider>()!);
client.SendingMessage += (sender, eventArgs) =>
{
eventArgs.Message.Details.Tags.Add("Fruits!");
};
return client;
});
// register the RaygunClient before calling AddRaygun
builder.Services.AddRaygun(builder.Configuration);
Note that if an exception occurs within your SendingMessage
event handler, Raygun4Net will detect this and send the new exception as well as the original exception that was being processed. When processing the new exception, the event handler will not be called again in order to avoid an infinite loop.
Custom grouping
When exception reports are sent to Raygun, they get grouped using our classification logic. We improve this logic every now and then, but sometimes you may come across scenarios where exception reports are grouped together or put into separate groups that you were not expecting. This can be from cases we are not yet handling, scenarios that are specific to your application, or unique grouping preferences you have. Raygun4Net lets you provide your own custom grouping logic before exceptions are sent to Raygun.
To use the custom grouping key feature, start by getting the RaygunClient
instance used to send your exception reports and attach an event handler to the CustomGroupingKey
event. This event gets fired before the SendingMessage
event described in the section above. The event arguments provide both the original Exception
object and the RaygunMessage
object that is about to be sent. In the event handler, you can use whatever logic you want to build a grouping key (string) for the given exception. When the key is ready, set it to the CustomGroupingKey
property of the event arguments. Exceptions that end up with the same key will be grouped together.
note: Grouping keys have a limit of 100 characters.
Unless you have extreme grouping logic that needs to be applied to all exceptions, we recommend that you only apply custom grouping logic to scenarios that we are not handling for you. You can include checks in your event handler for certain types of exceptions, for example, and only create a custom grouping key for them. Exceptions that you don't provide a custom grouping key for will be grouped in Raygun using the grouping classifiers we provide.
Here is an example of providing a custom grouping key
_raygunClient.CustomGroupingKey += (sender, args) =>
{
// This example simply performs pure message based grouping on basic Exception instances:
if (args.Message.Details.Error.ClassName.Equals("Exception"))
{
string key = args.Exception.Message;
args.CustomGroupingKey = key;
}
};
Note that if an exception occurs within your CustomGroupingKey
event handler, Raygun4Net will detect this and send the new exception as well as the original exception that was being processed. When processing the new exception, the event handler will not be called again in order to avoid an infinite loop.
Exclude errors by HTTP status code
You can exclude errors by their HTTP status code by providing an array of status codes to ignore in the configuration. For example, if you wanted to exclude errors that return the I'm a teapot response code, you could use this configuration:
"RaygunSettings": {
"ApiKey": "paste_your_api_key_here",
"ExcludedStatusCodes": [418]
}
Exclude errors that originate from a local origin
To prevent Raygun4Net from sending exceptions that originate from a local origin (your debug/development machine), set the ExcludeErrorsFromLocal
setting to true
as seen in the code below. This is useful if you find that you are generating pointless noise in the development process. This option is a convenient alternative to using transforms to do the same thing.
"RaygunSettings": {
"ApiKey": "paste_your_api_key_here",
"ExcludeErrorsFromLocal": true
}
Remove sensitive request data
By default, Raygun4Net will send all form-fields and headers in the current HTTP request. If you have sensitive data in an HTTP request that you wish to prevent being transmitted to Raygun, you can provide a list of possible named values to remove:
"RaygunSettings": {
"ApiKey": "paste_your_api_key_here",
"IgnoreFormFieldNames": ["password","creditcard","cv2"]
}
Three attributes are available, to remove values from these properties:
IgnoreFormFieldNames
(ignores values fromHttpRequest.Form
)IgnoreHeaderNames
(ignores values fromHttpRequest.Headers
)IgnoreCookieNames
(ignores values fromHttpRequest.Cookies
)
Or specify them in code:
builder.Services.AddRaygun(settings =>
{
settings.IgnoreFormFieldNames = ["password", "creditcard", "cv2"];
});
Setting any of these options to true
will cause Raygun4Net to ignore all values in that category. Also, by placing before, after, or at both ends of a name, Raygun4Net will use that as an ends-with, starts-with or contains condition respectively when determining what to ignore.
Customers
User information enables the Raygun dashboard to track unique users impacted by each error or crash. While you can input any useful data, remember to respect your company's privacy policies. At a minimum, input a unique GUID for user impact visibility per error. A database ID, if available, could help in resolving issues. Providing names and contact details allows for direct communication about issue resolution.
Default implementation
By default Raygun4Net ships with a DefaultRaygunUserProvider
which will attempt to get the user information from
the HttpContext.User
object. This is Opt-In which can be added by calling:
services.AddRaygunUserProvider();
Custom implementation
If you want to provide your own implementation of the IRaygunUserProvider
you
can do so by creating a class that implements the interface and then adding it to the services during configuration
using services.AddRaygunUserProvider<MyCustomUserProvider>()
.
Below is an example user provider that uses the HttpContext.User
similar to our DefaultRaygunUserProvider
.
public class ExampleUserProvider : IRaygunUserProvider
{
private readonly IHttpContextAccessor _contextAccessor;
public ExampleUserProvider(IHttpContextAccessor httpContextAccessor)
{
_contextAccessor = contextAccessor;
}
public RaygunIdentifierMessage? GetUser()
{
var ctx = _contextAccessor.HttpContext;
if (ctx == null)
{
return null;
}
var identity = ctx.User.Identity as ClaimsIdentity;
if (identity?.IsAuthenticated == true)
{
return new RaygunIdentifierMessage(identity.Name)
{
IsAnonymous = false
};
return null;
}
}
This can be registered in the services during configuration like so:
services.AddRaygunUserProvider<ExampleUserProvider>();
note: This behaviour is new since Raygun4Net v10.0.0. The previous User and UserInfo properties are marked as obsolete but are still functioning for now.
Here are the available RaygunIdentifierMessage
properties:
Identifier
(passed into the constructor) is the unique identifier from your system for this user.IsAnonymous
is a flag indicating whether the user is logged in (or identifiable) or if they are anonymous. An anonymous user can still have a unique identifier.Email
The user's email address. If you use email addresses to identify your users, feel free to set the identifier to their email and leave this blank. We will use the identifier as the email address if it looks like one, and if no email address is specified in this field.FullName
The user's full name.FirstName
The user's first (or preferred) name.UUID
A device identifier. Could be used to identify users across devices or machines that are breaking for many users.
note:
The string properties on a User
have a maximum length of 255 characters. Users that have fields that exceed this amount will not be processed.
Tags
An overload of SendAsync
and SendInBackground
allows you to include a list of tags with each manually sent exception:
_raygunClient.SendAsync(exception, new List<string>() { "tag1", "tag2" });
Exceptions can be searched in your Raygun dashboard by tags that you've included.
Custom data
You can include key-value custom data using an overload of the SendAsync
or SendInBackground
method. Values can be primitive types or rich object structures. All properties of objects and their children will be sent to Raygun. Cyclic object references will be detected and handled as appropriate, and any property getter that produces an exception will cause that property value to be displayed as the exception message.
_raygunClient.SendAsync(exception, null, new Dictionary<string, object>() { { "key", "value" } });
The second parameter is the list of tags (mentioned above), which can be null
if none apply to the current exception.
Version numbering
By default, Raygun4Net will attempt to set ApplicationVersion
from the entry assembly. It is possible to override this by providing a version through RaygunSettings
:
Via appsettings:
"RaygunSettings": {
"ApiKey": "paste_your_api_key_here",
"ApplicationVersion": "1.0.0.0"
}
In code:
services.AddRaygun(settings =>
{
settings.ApiKey = "paste_your_api_key_here";
settings.ApplicationVersion = "1.0.0.0";
});
Stripping wrapper exceptions
If you have common outer exceptions that wrap a valuable inner exception which you'd prefer to group by, you can specify these by using the following multi-parameter method:
_raygunClient.AddWrapperExceptions(typeof(MyWrapperException));
The above example will cause MyWrapperException
instances to be stripped away and never sent to Raygun. Instead, only the inner exception of any stripped exceptions will be sent. By default TargetInvocationException
will always be stripped - see below to override this behavior.
AggregateException support
AggregateException
is a special case as it can hold multiple inner exceptions. By stripping AggregateException
instances using the method described above, all inner exceptions will be sent to Raygun as separate exception reports. That way, each inner exception can be put into the appropriate individual groups and managed separately.
Prevent wrapper exception stripping
If you want to prevent Raygun4Net from stripping the default wrapper exception (TargetInvocationException
), then you can call the multi-parameter RemoveWrapperExceptions
method as shown below. This can also be useful if you've used the above instructions to cause Raygun4Net to strip a wrapper exception type that you later don't want to strip within a single execution of the app.
_raygunClient.RemoveWrapperExceptions(typeof(TargetInvocationException));
Proxy settings
The Raygun4Net provider uses the default Windows proxy settings when sending messages to Raygun. Unfortunately, we don't support setting a proxy server or proxy credentials by configuration yet.
Adding Raygun to the Front End in ASP.NET
On the first line of the /[Pages|Views]/Shared/_layout.cshtml
file, add @inject Microsoft.Extensions.Configuration.IConfiguration Configuration
Then, at the end of the <head>
element, add the Raygun4JS CDN fetch script with the API key automatically imported from your app's Configuration
.
@inject Microsoft.Extensions.Configuration.IConfiguration Configuration
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - razorDemo</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/razorDemo.styles.css" asp-append-version="true" />
<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>
<script type="text/javascript">
rg4js('apiKey', '@Configuration["RaygunSettings:ApiKey"]');
rg4js('enableCrashReporting', true);
rg4js('enableRealUserMonitoring', true); <!-- Optional, enable Real User Monitoring -->
</script>
</head>
<body>
<!-- The rest of the body -->
</body>
If you want to include the logged-in user's details, they can populated from the HttpContext.User
object.
To do this, add @using System.Security.Claims
to the top of the _layout.cshtml
file, then update the Raygun4JS fetch script at the end of the <head>
element to include the rg4js('setUser', {...});
section below:
<script type="text/javascript">
rg4js('apiKey', '@Configuration["RaygunSettings:ApiKey"]');
rg4js('enableCrashReporting', true);
rg4js('enableRealUserMonitoring', true); <!-- Optional, enable Real User Monitoring -->
rg4js('setUser', {
identifier: @ViewContext.HttpContext?.User?.FindFirstValue(ClaimTypeNameIdentifier),
isAnonymous: @(!(ViewContext.HttpContext?.User?.Identity?.IsAuthenticated ?? false)),
email: @ViewContext.HttpContext?.User?.FindFirstValue(ClaimTypes.Email),
fullName: @ViewContext.HttpContext?.User?.FindFirstValue(ClaimTypes.GivenName),
});
</script>
Depending on your authentication model, you may need to adjust what ClaimTypes
you use.
For more front-end configuration options, visit our JavaScript provider's Advanced Features documentation.
The provider is open source and available at the Raygun4Net repository.