Other Useful NuGet Packages

As mentioned earlier, the lessons learned and the tools we used to build NuGet Gallery could fill a book. The previous sections covered features needed by nearly every web application, such as an admin section, profiling, error logging, and so on.

In this section I'll quickly cover a smattering of useful packages used in NuGet Gallery that aren't necessarily needed by most applications, but which are very useful when you do need them. Each section begins with the command to install the package.

T4MVC

Install-Package T4MVC

T4MVC (http://nuget.org/packages/T4MVC), authored by David Ebbo, installs a T4 template that generates strongly typed helpers for ASP.NET MVC. For example, when you want an action link, instead of writing:

@Html.ActionLink("Delete Book", "Delete", "Books", new { id = Model.Id}, null)

you can write:

@Html.ActionLink("Delete Book", MVC.Books.Delete(Model.Id))

That's pretty handy if you love IntelliSense, as it can provide a list of the available controllers and actions.

WebBackgrounder

Install-Package WebBackgrounder

WebBackgrounder (http://nuget.org/packages/WebBackgrounder) is a package for safely running recurring background tasks in an ASP.NET application. ASP.NET and IIS are free to tear down (that is, stop) your application's AppDomain at any time. There are mechanisms that ASP.NET provides to notify code when this happens. WebBackgrounder takes advantage of this to try and safely run a background timer for running tasks that need to recur.

WebBackgrounder is a very early work in progress, but the NuGet Gallery uses it to regularly update download statistics and update the Lucene.NET index. As you might expect, it's configured in AppActivator via the following two methods.

private static void BackgroundJobsPostStart()
{
    var jobs = new IJob[] {
        new UpdateStatisticsJob(TimeSpan.FromSeconds(10), 
          () => new EntitiesContext(), timeout: TimeSpan.FromMinutes(5)),
        new WorkItemCleanupJob(TimeSpan.FromDays(1),
          () => new EntitiesContext(), timeout: TimeSpan.FromDays(4)),
        new LuceneIndexingJob(TimeSpan.FromMinutes(10), 
          timeout: TimeSpan.FromMinutes(2)),
    };
    var jobCoordinator = new WebFarmJobCoordinator(new EntityWorkItemRepository
(
      () => new EntitiesContext()));
    _jobManager = new JobManager(jobs, jobCoordinator);
    _jobManager.Fail(e => ErrorLog.GetDefault(null).Log(new Error(e)));
    _jobManager.Start();
}

private static void BackgroundJobsStop()
{
    _jobManager.Dispose();
}

The first method, BackgroundJobsPostStart, creates an array of the various jobs you want to run. Each job includes an interval for how often they should be run. For example, we update download count statistics every 10 seconds.

The next part sets up a job coordinator. If your application only runs on a single server, you can simply use the SingleServerJobCoordinator. Since NuGet Gallery runs on Windows Azure, it's effectively a Web Farm, which requires the WebFarmJobCoordinator to ensure the same job isn't being run on multiple servers at the same time. This allows WebBackgrounder to automatically spread out the work onto multiple machines. This coordinator requires some central “repository” in order to synchronize work.

We decided to use the database, since we only have one database per farm (and it is thus centralized), and installed the WebBackgrounder.EntityFramework package to hook it up.

Lucene.NET

Install-Package Lucene.NET

Lucene.NET (http://nuget.org/packages/Lucene.Net) is an open source port of the Apache Lucene search library. It's the most well-known text search engine for .NET. The NuGet Gallery uses it to power package search.

Because it's a port of a Java library, the API and configuration is a bit clunky for those used to .NET APIs. But once it's configured, it's very powerful and fast.

Configuring it goes way beyond the scope of this book. The NuGet Gallery wraps the Lucene.NET functionality within the LuceneIndexingService class. This provides one example of how to interface with Lucene. Also take a look at the LuceneIndexingJob. This is a WebBackgrounder job scheduled to run every 10 minutes.

AnglicanGeek.MarkdownMailer

Install-Package AnglicanGeek.MarkdownMailer

AnglicanGeek.MarkdownMailer (http://nuget.org/packages/AnglicanGeek.MarkdownMailer) is a simple library for sending e-mails. What's great about this library is you can define the e-mail body once using Markdown syntax and it generates a multi-part e-mail with views for both text and HTML.

The NuGet Gallery uses this to send all its notification e-mails, such as those for new users and password resets. Look at the MessageService class for examples of how the gallery uses this library.

Ninject

Install-Package Ninject

There are many dependency injection (DI) frameworks for .NET. The NuGet Gallery team chose Ninject (http://nuget.org/packages/NuGet) as its DI container because of its clean API and speed.

Ninject is the core library. The Ninject.Mvc3 package configures Ninject for an ASP.NET MVC project. It makes getting started with Ninject quick and simple.

As mentioned earlier, all the NuGet Gallery's Ninject bindings are located in the ContainerBindings class. Here's a sample of two bindings plucked from that class:

Bind<ISearchService>().To<LuceneSearchService>().InRequestScope();

Bind<IFormsAuthenticationService>()
    .To<FormsAuthenticationService>()
    .InSingletonScope();

The first line registers LuceneSearchService as a concrete instance of ISearchService. This allows us to keep our classes loosely coupled. Throughout the codebase, classes reference only the ISearchService interface. This makes supplying a fake during unit tests easy. At run time, Ninject injects a concrete implementation. The InRequestScope ensures that a new instance is created for each request. This is important if the type requires request data in its constructor.

The second binding does the same thing, but the InSingletonScope ensures that there's only one instance of FormsAuthenticationService for the whole application. If a service holds onto any request state, or requires request state in its constructor, make sure to use request scope and not singleton.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset