27 Apr 2015
In my previous post I praised Postal for being such a simple and easy library
to use for templating and sending emails from your .net app. I also briefly mentioned
how it just uses the standard SMTP settings from your Web.config
or App.config
file
for sending out the mails.
This is fine in most scenarios, but on one of our last projects we were using Postmark
and gave preference to using the HTTP API instead of relying on the SMTP protocol. The main
advantage of this is that HTTP tends to be far less chatty than SMTP and you can increase
the throughput of your mails.
Step 1: Install Postmark .net library
From the Package Manager Console inside Visual Studio do:
This installs the official Postmark .net library from NuGet.
Step 2: Implement an IEmailService
An IEmailService
is Postal's way to allow you to alter the behaviour of sending the email.
The default implementation uses the System.Net.Mail
namespace to compose a MailMessage
instance
and send it using the configuration that sits in your .config
file.
This is what we want to change in order to start using the Postmark API, we can send emails using the
following code snippet.
MailMessage message = ...;
var client = new PostmarkClient("<your api token goes here>");
client.SendMessageAsync(message);
This is absolutely perfect, because the default EmailService
implementation contains a method to create
a MailMessage based on an Email
object, so we can simply use that and pass the MailMessage
to the
PostmarkClient
. The result is the following service:
public class PostmarkEmailService : IEmailService
{
// the default implementation used to generated
// the MailMessage objects
private Postal.EmailService _inner;
private PostmarkClient _client;
public PostmarkEmailService(string token)
{
_inner = new EmailService();
_client = new PostmarkClient(token);
}
public void Send(Email email)
{
var msg = CreateMailMessage(email);
_client.SendMessageAsync(msg)
.Wait();
}
public Task SendAsync(Email email)
{
var msg = CreateMailMessage(email);
return _client.SendMessageAsync(msg);
}
public MailMessage CreateMailMessage(Email email)
{
return _inner.CreateMailMessage(email);
}
}
Step 3: Set an instance of our service as the default one
Now that we have a service that can send Emails using the Postmark API, the only thing that
remains to be done is to configure Postal the use it as IEmailService
used for sending
out the mails during the startup of our app.
Email.CreateEmailService = () => new PostmarkEmailService("<your token goes here>");
Conclusion
That's it! From now on all Send
calls on an Email
object will use Postmark to send out
the emails.
Changing Postal's default send implementation is super easy, thanks to the
nice NuGet package that Postmark provides and to the extensibility of Postal.
17 Mar 2015
Even though people sometimes claim that open source .net is not in a healthy state and that
the community too often relies on what Microsoft is providing, there do exist some awesome open
source libraries out there. Over the course of the last couple of years, we've started several -
often small scale - new projects at work and I've come to rely on some libraries that solve some
specific problems, and they solve them well. This post is not about packages that are in
NuGet's top 100 list, but about lesser known libraries that deserve some extra attention.
Are there some things they have in common? Yes!
- Most of them have excellent documentation, time
and time again this turns out to be extremely important for any OSS project, especially go get
starters on board.
- These libraries are not frameworks in the sense that they don't force you into any
application structure or require you to inherit from class X or Y. They are just nice libraries
that you can plug into your projects and they do what they promise.
So let's get into it...
Hangfire
Hangfire is a library that allows you to quickly and beautifully add background processing
to your ASP.net application. It's extremely simple to setup and scheduling background work is as
straightforward as it can be.
BackgroundJob.Enqueue(() => Console.WriteLine("Simple!"));
There are several things I love about Hangfire:
- The built-in dashboard is beautiful, clear and gives a good view of what is happening and -
maybe more important - what is going wrong.
There are no requirements on the method that is to be executed in the background. No class to
inherit from, no attributes have to added to it, it just needs to be a public method. This
allows you to structure your background jobs as you see fit.
While It Just Works when you add it to an ASP.net application, you're not restricted to it.
You can schedule and process the jobs basically anywhere: Windows Services, Console Applications,
Azure Web workers, .... If you include this in your application, you know that you will be able
to take your code and split it into different components if needed. And Hangfire will still
be able to do the processing.
It was once featured on Scott Hanselman's blog. It probably helped a lot to highlight the
existence of Hangfire, but some people also quickly noted its shortcomings. It had a dependancy
on System.Web
even though it was architected as an OWIN component, it depended on Common.Logging
and used SQL Server by default. All of these were true, but it should be noted that Hangfire's author
Sergey Odinokov has been quick to address the issues. By now, Hangfire is already in a much better
shape, so I have the impression that Sergey knows very well what he is doing.
Postal
Shortly after the Razor View Engine came out for ASP.net, Andrew Davey had the excellent idea to
start using it to do Email templating: Postal was born. The idea is simple, your Views
folder gets
an extra subdirectory called Emails
where you put in all your Razor Email templates and everything Razor
has to offer comes for free: Layouts, strongly-typed models, Url-helpers, partials, etc. Sending
an e-mail is as simple as
dynamic email = new Email("Example"); // Uses Views\Emails\Example.cshtml
email.To = "webninja@example.com";
email.FunnyLink = DB.GetRandomLolcatLink();
email.Send();
You basically create a Email
object and treat it as a dynamic
, you chuck some properties onto it, which you can
then inside your Email template.
To: @ViewBag.To
From: lolcats@website.com
Subject: Important Message
Hello,
You wanted important web links right?
Check out this: @ViewBag.FunnyLink
<3
Of course you can use strongly-typed Models if you want to.
It respects Web.config
's smtp settings and hence works perfectly with services like Mandrill or Postmark, has
some nice features like image inlining, and it is built to integrate perfectly with any MVC version. Good stuff!
Formo
Whether you're in a console app, a web application or a windows service, reading from your app.config
's and web.config
's
application settings is never a fun thing to do, especially if you want to read DateTime
or int
values.
Formo solves this problem very elegantly by simply exposing the settings as a dynamic
object. This makes the code to
read the settings much easier on the eye.
dynamic config = new Formo.Configuration();
// This simply reads the string
string apiEndPoint = config.ApiEndPoint;
// This converts the value in to an int, no
// need to do any conversion in your code
int timeout = config.ApiTimeout<int>();
// This uses a default value of 5 if the
// configuration files contains no values
int retries = config.ApiRetries<int>(5);
If you don't like dynamic
, you can even go a step further and bind the application settings to a simple POCO class.
public class Settings
{
public string ApiEndpoint { get; set; }
public int ApiTimeout { get; set; }
}
dynamic configuration = new FormoConfiguration();
Settings settings = configuration.Bind<Settings>();
Even though Formo's scope is very limited and even though it seems that reading configuration files will change drastically
with aspnet5, I find it a very useful library which for me has reduced the friction of reading config files perfectly.
CsvHelper
When dealing with data from legacy systems, then CSV files are still commonly used as the way to export data. In the past
I have used several different ways of dealing with these files: copy/paste from codeproject (yeah, I know), hand written
CSV reader for specific format, etc.
Until I bumped into CsvHelper, that is. The feature that I love the most, is how you can define a CsvClassMap
to populate
a certain POCO class. You can then use a CsvReader
to convert each row into an instance of that POCO class. That way, you don't
have to think about all the nitty gritty details that can occur when you need to read CSV files. These class maps provide a lot
of configuration options and I have yet to encounter a situation that CsvHelper cannot handle.
Topshelf
Writing a Windows Service is a lot harder than it should be. The logic itself is the easy part, but writing and configuring the part
that creates the service on the system is just a mess. If you follow the Visual Studio Way of doing things, this mess involves
- Creating a
ServiceBase
class, this contains the business logic of th Service
- Adding a
ProjectInstaller
to the project. Here we go into drag-and-drop territory, with .Designer.cs
files and toolboxes and
magically generated InitializeComponent
methods.
- This
ProjectInstaller
should contain an instance of a ServiceProcessInstaller
. This tells the installer under which account
the service should run.
- The
ProjectInstaller
also needs to contain one or more ServiceInstaller
instances which tell the ...
- ...
You get the gist, it is overly complex and involves too much automatically generated code and magic strings. Compare this to the beauty
of a Topshelf service.
- First you create a console app and add Topshelf through NuGet
- Then, you create a class that holds your service logic. The only important thing is that the class must have some kind of
Start
and Stop
method
- and finally the main method of the
Program.cs
should look something like this
public static void Main()
{
HostFactory.Run(c =>
{
c.Service<BookSyncService>(s =>
{
s.WhenStarted(tc => tc.Start());
s.WhenStopped(tc => tc.Stop());
});;
c.UseNLog();
c.SetServiceName("BookSync");
c.SetDisplayName("Book Sync Service");
c.SetDescription("Sync books");
});
}
The result is a simple .exe file that you can use to install, uninstall, start and stop your Windows Service. To install it you
simply go to the command-line and execute
.\yourservice.exe install
and the service will be configured in the Windows Service registry. Other operations are very similar and you can find
more information in the full reference.
Conclusion
At first sight none of these libraries do something spectacular. They do however make your work lighter by simply taking care
of some very mundane problems like background processing, reading CSV files or creating a Windows Service. And this is where
there value comes from: they allow you to focus on the real challenges of your application. And as cheesy as it may be, that's
a beautiful goal.