The NuGet packages we use to build elmah.io
I recently saw someone writing a post of his go-to NuGet packages. I think that listing your favorite packages and the decisions behind each choice is such a great idea, that I wanted to create one for elmah.io. We use a lot of packages, but this is the essential list.
Running a system like elmah.io requires a lot of moving parts. Some features have been written from the ground up while others are utilizing a range of NuGet packages. Here's an alphabetically ordered list of the most essential packages.
The elmah.io API includes a rate-limiting feature to help users stay within their message limit. I'm not talking DoS and DDoS attacks here but more about handling when a user's website starts to output a high number of messages caused by introducing an error, crawlers, automated penetration tests, etc. The
AspNetCoreRateLimit package from Stefan Prodan works very well and is highly configurable. Read more about how to use it in this post: Rate limiting API requests with ASP.NET Core and AspNetCoreRateLimit.
We switched our email provider to Amazon Web Services (AWS) a few years ago. We are very pleased with both the Simple Email Service (SES) as well as Amazon's client for .NET. When looking at the quality of the package, it is obvious that .NET is a priority for AWS now. We generally use the templated feature in AWS SES, but for sending out raw emails and attachments, the
MimeKit NuGet package is a great extension. We wrote a detailed post about how to send emails from .NET with AWSSDK as well as similar packages: How to send emails from C#/.NET - The definitive tutorial.
As we already documented in our post How we do bundling and minification in ASP.NET Core, we use Mads Kristensen's
BundlerMinifier packages for our ASP.NET Core websites. The
BundlerMinifier.TagHelpers package is key to only have your JS and CSS files listed in a single file.
We couldn't say that we were an error monitoring service for .NET developers if we didn't use elmah.io ourselves. All websites and services in elmah.io are monitored with elmah.io. We use almost all of the
Elmah.Io.* packages to integrate different websites, Windows Services, and Azure Functions with elmah.io.
Like everyone else, we use Google Analytics. I have a love/hate relationship with that product. We produce some nice dashboards on top of a range of sources, where the integration with Analytics is based on the
Google.Apis.AnalyticsReporting.V4 NuGet package. The code against this package is hard to write, but it gets the job done. For more information, check out this blog post: Export data from Google Analytics with .NET.
When needing to implement two-factor authentication on a .NET project, I would recommend you to look into
GoogleAuthenticator by Brandon Potter. The API is extremely simple and it gets the job of validating PINs done in just a few lines of code.
Intercom is one of the systems we use to send out emails as well as for chat support. To help our users better, we decorate user objects in Intercom with a lot of information. We are not talking about personal information that would make any GDPR lawyer furious here, but rather metadata and links to our internal support systems. The
Intercom.DotNet.Client is developed by Intercom itself and provides a nice wrapper for their API that allows us to quickly make updates. There is some bad news with this package, though. Development seemed to have stopped on an old version of Intercom's API, why we might want to eliminate this package going forward.
People are sometimes surprised when I tell them how much more than just persisting log messages we do. All messages are processed and enriched with a range of different data before storing. One of these enrichers is a location, based on its IP address. We use the database by IP2Location and they provide a nice NuGet package to run everything locally.
MailChimp.Net.V3 is a wrapper on top of the Mailchimp API developed by Brandon Seydel.
A lot of communication between elmah.io components happens through Azure Service Bus. Users of that resource probably already know about the chaotic mess in the client libraries for Azure. We started with the
WindowsAzure.ServiceBus package. Then migrated to
Microsoft.Aure.ServiceBus, which we currently use. Now there's yet a re-written client for Service Bus named
Azure.Messaging.ServiceBus. Following along with package updates can be hard 😉
We have a range of different storage types in play on elmah.io. One of them being Azure Blob Storage. We use the, now deprecated,
Microsoft.Azure.Storage.Blob package to interact with blob storage. Like the Service Bus package, we are looking into migrating to the new
While we mostly set up logging with Serilog, we use the
ILogger interface from
Microsoft.Extensions.Logging package as an abstraction on top of Serilog. Not because of the always mentioned possibility to switch logging framework, but more as a uniform way of logging both custom log messages as well as getting details from within the frameworks we are using.
One of the technologies I have been most hyped about in the last year is machine learning. So many new possibilities can be introduced with a well-trained model. On elmah.io we have built 3 different features on top of Microsoft's ML.NET. ML.NET is wrapped nicely within the range of NuGet packages prefixed with
I already touched upon our currently used mocking frameworks in the post Moq vs NSubstitute vs FakeItEasy - Which one to choose?. While we are slowly transitioning to
NSubstitute, we still use
Moq in a lot of projects.
Moq has been a great companion over the years, and I would still recommend you to look at both
NSubstitute and make a choice based on your needs.
We use Elasticsearch for our primary data store.
NEST is a client package for Elasticsearch originally developed by the all-round nice guy Martijn Laarman. Since Martijn got a job at Elastic,
NEST matured into the official .NET client for Elasticsearch.
I get it.
System.Text.Json is the best thing since sliced bread. I see that we will run on
System.Text.Json eventually, but for now, we still use
Newtonsoft.Json in a lot of places. Also, a lot of our other package dependencies still depend on
Newtonsoft.Json and probably will keep doing that for years.
When it comes to generating PDF documents, you probably have more options than every other task out there. There's a range of different packages for generating PDF files, most based on the wkhtmltopdf tool. We tried a few of the free ones out there and also blogged about one of them here: Generate a PDF from ASP.NET Core for free. For generating invoices on elmah.io we settled on the commercial
Like already mentioned, we are migrating to
NSubstitute. The simple API offers a lot of features and the advantages of having mock objects as the real type rather than a wrapping
Mock object just makes this test helper an invaluable companion when writing unit tests. For more information about
NSubstitute read through this post: Moq vs NSubstitute vs FakeItEasy - Which one to choose?
Let's talk about the elephant in the room. Yes, we use
NUnit by Charlie Poole. Everyone is talking about
xUnit these days and while I have used that in other projects from time to time, we still run
NUnit on elmah.io. It has worked very well over the years and while it may not be as hyped as
xUnit, the API is simple and it's easy to find documentation whenever we need it.
Polly and Microsoft.Extensions.Http.Polly
Building a service like elmah.io requires a lot of moving parts and integrations with external services. We use
Polly almost everywhere when making HTTP requests between both internal as well as external APIs. With
Polly, we have the option of setting up advanced retry policies and even temporarily stop HTTP requests if an external REST API is unavailable. Combined with the
Microsoft.Extensions.Http.Polly package, I would recommend everyone not already familiar to look into
When creating a new user on elmah.io, we check if the inputted password is part of one or more data breaches. We use the awesome service Have I Been Pwned by Troy Hunt. It's a simple API request to check a password, but Andrew Lock wrote this nice little client that validates a password in a single line of C#.
Yet another package developed by Martijn Laarman is
ShellProgressBar. As suggested by the name, the package makes it easy to produce beautiful progress bars on the command line. Showing progress in the console means more than you would first expect. We use the package to signal progress for long-running tasks in our CLI. We also blogged about how to use
ShellProgressBar here: Building a command-line tool with progress bar in .NET Core.
Command-line tools just look and feel better when introducing a bit of color.
Spectre.Console makes it extremely easy to change the font and background colors, produce bordered controls, including emojis, and more. All in the console.
We use Stripe for accepting payments on elmah.io and we couldn't be happier. After experimenting with other services, Stripe just seems superior to everything else out there. Their NuGet package for .NET is also top-notch. It's a wrapper of their API but it has some nice extensions to make paging easier and much more. If you are interested in seeing
Stripe.Net in action, check out our posts Accepting payments with Stripe and ASP.NET Core and Paid subscriptions with ASP.NET Core and Stripe Billing.
Swashbuckle has been our product of choice for adding Swagger/OpenAPI documentation to our API for years.
Swashbuckle.AspNetCore works perfectly with ASP.NET Core websites and comes with Swagger UI bundled.
I have been using most of the packages for creating command-line interfaces out there. Like Command Line Parser, GoCommando, and Microsoft.Extensions.CommandLineUtils. After publishing .NET Core, Microsoft open-sourced its CLI library that powers the
dotnet command named
System.CommandLine. The library is based on implementing commands and provides you with all of the boilerplate code needed to parse input parameters, formatting help documentation, etc.
When it comes to logging frameworks for .NET I have tried them all. After having introduced Serilog at my previous job, picking that when launching elmah.io back in 2013 seemed like the natural thing to do. Since then, features and sinks grew into what's one of the best logging frameworks I have ever tried. We use a range of different extensions and sinks for Serilog. Like
While we have moved most of our scheduled tasks and services to Azure Functions, we are still dependent on a couple of Windows Services. I have found that
Topshelf by Chris Patterson is still the simplest way to host C# code as a Windows Service.
Another example of processing and enriching log messages is looking up detailed information about which software a client is running on based on the HTTP user agent. I've looked through a range of online services and experimented with a few of them.
UAParser by Søren Enemærke takes a different approach where all processing is running locally, based on a set of regex patterns part of the ua-parser project.
That's a quick list of some of the essential NuGet packages we use. If there's a general interest in going into details with each package, let me know and I'll think about a format to implement this with.
elmah.io: Error logging and Uptime Monitoring for your web apps