Everyday we use a lot of NuGet packages. Most of them are well-known and required to install, while some of them are optional. Nowadays, most of the “optional” packages have become industrial standard, like NUnit or Newtonsoft.Json. However, developers keep developing new software, and we see many new packages appearing on the NuGet Gallery.
In this article, we will review several general-purpose packages that are worth your attention.
By “general purpose” I mean that you are very likely to use some of these packages, no matter what are you developing: a web application, server side or a desktop application.
An easy way to perform fire-and-forget, delayed, and recurring tasks inside ASP.NET applications. No Windows Service required.
Fire-and-forget tasks:
// Static methods are for demo purposes
BackgroundJob.Enqueue(
() => Console.WriteLine("Simple!"));
Delayed tasks:
BackgroundJob.Schedule(
() => Console.WriteLine("Reliable!"),
TimeSpan.FromDays(7));
Recurring tasks:
RecurringJob.AddOrUpdate(
() => Console.WriteLine("Transparent!"),
Cron.Daily);
A better date and time API for .NET.
Jon was born on June 19th, 1976 (Gregorian). How old is he now, in the UK time zone?
LocalDate birthDate = new LocalDate(1976, 6, 19);
DateTimeZone zone = DateTimeZoneProviders.Tzdb["Europe/London"];
ZonedClock clock = SystemClock.Instance.InZone(zone);
LocalDate today = clock.GetCurrentLocalDateTime().Date;
Period age = Period.Between(birthDate, today);
Console.WriteLine("Jon is: {0} years, {1} months, {2} days old.", age.Years, age.Months, age.Days);
UniRest is a set of lightweight HTTP libraries available in multiple languages.
The library is available for all mainstream languages preserving the same API. .NET version has portable library and can run virtually on all .NET Framework versions.
A basic POST request example:
HttpResponse<MyClass> jsonResponse = Unirest.post("http://httpbin.org/post")
.header("accept", "application/json")
.field("parameter", "value")
.field("foo", "bar")
.asJson<MyClass>();
Shouldly is an assertion framework which focuses on giving great error messages when the assertion fails while being simple and terse.
Assert.That(map.IndexOfValue("boo"), Is.EqualTo(2)); // -> Expected 2 but was 1
map.IndexOfValue("boo").ShouldBe(2); // -> map.IndexOfValue("boo") should be 2 but was 1
Lightweight .NET component for programmatically generating Markdown. Useful for producing rich diagnostic logs with minimal dependencies.
var data = new[]
{
new{Year = 1991, Album = "Out of Time", Songs=11, Rating = "* * * *"},
new{Year = 1992, Album = "Automatic for the People", Songs=12, Rating = "* * * * *"},
new{Year = 1994, Album = "Monster", Songs=12, Rating = "* * *"}
};
Console.Write(data.ToMarkdownTable());
// Produces:
//
// Year | Album | Songs | Rating
// ----:| ------------------------ | -----:| ---------
// 1991 | Out of Time | 11 | * * * *
// 1992 | Automatic for the People | 12 | * * * * *
// 1994 | Monster | 12 | * * *
ziplib is a Zip, GZip, Tar and BZip2 library written entirely in C# for the .NET platform.
How to create a Zip file:
FastZip fastZip = new FastZip();
bool recurse = true; // Include all files by recursing through the directory structure
string filter = @"\.txt$"; // Only files ending in ".txt"
fastZip.CreateZip("fileName.zip", @"C:\SourceDirectory", recurse, filter);
Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities.
Few examples that do not require explanation:
DateTime.UtcNow.AddHours(-30).Humanize() => "yesterday"
DateTime.UtcNow.AddHours(-2).Humanize() => "2 hours ago"
TimeSpan.FromMilliseconds(1299630020).Humanize(4) => "2 weeks, 1 day, 1 hour, 30 seconds"
"string".Pluralize() => "strings"
"Men".Singularize() => "Man"
"man".ToQuantity(1) => "1 man"
Generic Graph Data Structures and Algorithms for .NET.
The most demanded feature is topological sorting:
DataSet ds = new MyDataSet(); // your dataset
var graph = ds.ToGraph(); // wraps the dataset into a DataSetGraph
foreach(DataTable table in graph.TopologicalSort()) // applies a topological sort to the dataset graph
Console.WriteLine(table.TableName); // in which order should we delete the tables?
EPPlus is a .NET library that reads and writes Excel 2007/2010 files using the Open Office Xml format (XLSX).
This is a sample how you can return a spreadsheet from your web server without access to the file system.
private void DumpExcel(DataTable tbl)
{
using (ExcelPackage pck = new ExcelPackage())
{
//Create the worksheet
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Demo");
//Load the datatable into the sheet, starting from cell A1. Print the column names on row 1
ws.Cells["A1"].LoadFromDataTable(tbl, true);
//Format the header for column 1-3
using (ExcelRange rng = ws.Cells["A1:C1"])
{
rng.Style.Font.Bold = true;
}
//Example how to Format Column 1 as numeric
using (ExcelRange col = ws.Cells[2, 1, 2 + tbl.Rows.Count, 1])
{
col.Style.Numberformat.Format = "#,##0.00";
col.Style.HorizontalAlignment = ExcelHorizontalAlignment.Right;
}
//Write it back to the client
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=ExcelDemo.xlsx");
Response.BinaryWrite(pck.GetAsByteArray());
}
}
It is a .NET code library that allows you to parse “out of the web” HTML files. The parser is very tolerant with “real world” malformed HTML.
For example, here is how you would fix all href
tags in an HTML file:
HtmlDocument doc = new HtmlDocument();
doc.Load("file.htm");
foreach(HtmlNode link in doc.DocumentElement.SelectNodes("//a[@href"])
{
HtmlAttribute att = link["href"];
att.Value = FixLink(att);
}
doc.Save("file.htm");
A small validation library for .NET that uses a fluent interface and lambda expressions for building validation rules.
Example:
using FluentValidation;
public class CustomerValidator: AbstractValidator<Customer> {
public CustomerValidator() {
RuleFor(customer => customer.Surname).NotEmpty();
RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
RuleFor(customer => customer.Address).Length(20, 250);
RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
}
private bool BeAValidPostcode(string postcode) {
// custom postcode validating logic goes here
}
}
Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
bool validationSucceeded = results.IsValid;
IList<ValidationFailure> failures = results.Errors;