Mixing async and sync in distributed systems

One of the more difficult transitions when moving from a synchronous UI to an inherently async/CQRS-based UI is the burden of figuring out what to do with all these synchronous operations. Especially when dealing with existing systems, users that expect everything to be synchronous don’t really appreciate what used to tell them success right away now.

The problem really exacerbates itself when too much was happening at once, and the need to break things out to improve throughput requires a different protocol for integration.

Consider going to the grocery store. When you place an item in your basket, it’s inherently a synchronous operation. Either the jar of pickles makes it into your cart, or it doesn’t, there is no middle ground there. If you drop the jar of pickles onto the ground, you don’t wait for some async process to come by and let you know by email, “sorry, it seems there was a problem with your request to add the item to your shopping cart.”

Blending async in

Consider another system that requires to you to register with the site, using a local database for “who is registered” and a web service for downstream email communication:

image

In this system, we block the registration of the user against both the local database and the 3rd party web service. We need to check the local database to make sure the username/email is not already used, but what about that web service? What happens when that web service is slow, or unavailable?

We’ve coupled the availability of our system with a system we don’t own, which is potentially disastrous. In the real-world system that the above diagram is based on, when that 3rd party system goes into scheduled maintenance, the web application is brought down for maintenance too! Not a good user experience by any means. Are we really going to turn users away based on the availability of a downstream service?

But there’s another way – shifting the protocol of how this system is built. Let’s make sure what needs to be synchronous is, what what doesn’t need to be, isn’t. Instead of coupling the web service and local database calls together, let’s separate the two out with messaging:

image

Instead of performing the web service call in the same thread of the UI request, we instead send an asynchronous command as a message to perform the downstream operation. We’ve now decoupled the operation of calling the web service (what doesn’t need to be synchronous) with what does need (registering the user). The downstream operations of registering the user in the 3rd party email provider doesn’t need to happen at the same time.

To put it another way – does it affect the user’s registration if the email service provider rejects the message? No! Instead, that’s likely an administrative operation to figure out what happened, but the user is still successfully registered.

Defining the boundaries

When it comes time to figure out what should be synchronous and what shouldn’t, the key is to figure out what information, operations and behaviors your system owns versus are owned by someone else. If you own the UI and the database, then synchronous is a good possibility. If you don’t own the system (like our web service above), then async is a good possibility.

Next time: sync, async and CQRS.

ASP.NET MVC Authentication – Customizing Authentication and Authorization The Right Way

We're continuing the ASP.NET Authentication series (yes, I'm doing a few overlapping series, and yes, it's making me dizzy). The previous post covered Global Authentication and Allow Anonymous. This one continues with a simple tip that can be summed up as follows: keep it simple by extending rather than rewriting.

I see a lot of questions that involve unnecessary complications, and very often it's due to customizing authentication and authorization. For example, developers see that the AuthorizeAttribute won't work for their case, so they start to write a lot of code - using HttpModules, custom view engines, injecting authentication services and sprinkling authorization service calls throughout their controllers, etc.

Sometimes that's necessary, but it's rare. Most of the time you can handle things with either a custom membership provider, a subclassed AuthorizeAttribute, or both. Craig Stuntz summed this up well in a blog post back in 2009:

If you are developing a web application which requires authentication or security features not included in the regular ASP.NET membership feature, you might decide to implement these features yourself. But it seems as if the first instinct of many ASP.NET MVC developers is to do this by customizing their Controllers, because they’ve decided that AuthorizeAttribute can’t possibly serve their needs. They will decide that the way to do this is to write some sort of parent Controller type which examines the currently logged-in user when an action executes and changes the result of the action based on who they are. Others will try to re-implement AuthorizeAttribute without ever examining the source code for the original.

These are very bad approaches, for two important reasons:

  1. They don’t work. If your action result is cached by ASP.NET, then the action will not even run the next time it is requested. AuthorizeAttribute handles this correctly. Code you write in a Controller cannot handle this. Code you write in a custom action filter could work, if you cut and paste the implementation from AuthorizeAttribute. But AuthorizeAttribute is unsealed, so why cut and paste, when you can subtype?
  2. The modularity is wrong. You should aim to develop MVC sites which can be used with any authentication (or role) provider, whether it is ASP.NET membership, domain authentication, OpenId, or a custom membership provider. Wiring authentication concerns into a Controller makes this extremely difficult.

Craig recommends the same thing I'll be recommending - leverage the existing security systems in ASP.NET and ASP.NET MVC.

ASP.NET MVC's authorization system runs directly on top of the existing ASP.NET security system, and both have well established and tested extensibility points.

  • If you need to customize the way ASP.NET MVC integrates with the underlying ASP.NET security system, subclass the AuthorizeAttribute
  • If you need to customize the way the underlying ASP.NET membership system works, leverage the existing ASP.NET security provider system

I'll throw in one more - make sure you really need to customize anything at all.

Step Zero: Do you need to customize anything?

I've seen some examples that use the techniques below to implement authorization features... which didn't need implementing because they were already built in. AuthorizeAttribute, for example, already includes support for role-based authorization, but I've seen sample code that "adds in" role checking.

I've also seen examples which were built because the author assumed that AuthorizeAttribute only worked with Forms Authentication. That's not true - it just verifies if the user (1) is authenticated (2) is in the listed users and/or roles (if any are set). The same AuthorizeAttribute works with other authentication methods - the same attribute is also used with Windows Forms in the Intranet Application template, as well.

The AuthorizeAttribute has a pretty narrowly defined job, so it doesn't take much work to verify whether it already does what you need - check first.

Quick Note: Authentication and Authorization

Any sufficiently long article on web security must eventually devolve into distinguishing between authentication and authorization, so here goes:

  • Authentication is the act of establishing who the user is.
  • Authorization is the act of determining if that user should have access to a resource.

A user may be authenticated but not authorized to access a resource - e.g. a simple user isn't authorized to access site administration pages. A user may be authorized, but not authenticated - e.g. a site which allows anonymous access, a site which controls access using an API / access key, etc.

Customizing ASP.NET MVC's Interaction with ASP.NET Authorization by subclassing AuthorizeAttribute

Subclassing an AuthorizeAttribute is pretty straightforward. In most cases you just create a class that inherits form AuthorizeAttribute and override AuthorizeCore. Here's a very simple example: a key based login.

A simple key based AuthorizeAttribute

In this example, we'll be setting up a custom authorization scheme based on a key which will be validated using a very simple algorithm. This isn't secure for any number of reasons, but with some minor modifications (e.g. expiring a key once it is used) it would be sufficient for things like simple beta program for a pre-release website.

We'll accept a parameter called X-Key and validate that it's a number that passes a simple check.

To start with, we'll create a new class called KeyAuthorizeAttribute that inherits from AuthorizeAttribute:

public class KeyAuthorizeAttribute : AuthorizeAttribute  
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        string key = httpContext.Request["X-Key"];
        return ApiValidatorService.IsValid(key);
    }
}

public static class ApiValidatorService
{
    public static bool IsValid(string key)
    {
        int keyvalue;

        if (int.TryParse(key, out keyvalue))
        {
            return keyvalue % 2137 == 7;
        }
        return false;
    }
}

This AuthorizeCore method checks a value (via header, querystring, form post, etc.) and calls into a service to validate it. In this case, validation is a simple static method that runs our validation algorithm. In your case, you'd probably want to check against a list of pre-issued keys in a database, call out to an external service, etc. AuthorizeCore returns a boolean value - pass or fail.

We can then slap that [KeyAuthorize] attribute on any action or controller in the site, or register it globally (as shown in my previous post).

This request would be allowed: http://localhost:8515/?X-Key=26381272 (because 26381272 mod 2137 equals 7)

This request would be denied: http://localhost:8515/?X-Key=12345

Handling Authorization Failures

AuthorizeAttribute is based on Forms Authentication, so when a request fails a call to the AuthorizeCore method of an applicable AuthorizeAttribute, it will by default redirect to the login page so that, hopefully, the user can get authorized. I walked through the mechanics of this redirection process in a previous post.

The default login page doesn't make any sense in a lot of scenarios, including the example above. If someone comes to my site with a missing or incorrect API key, the login page isn't going to help them. For that specific case, I'd perhaps want to redirect them to a page that tells them how to apply for an access key.

If you need to change what happens when users fail authentication, you've got a few options:

  1. If you want to change the site-wide redirection URL for when a request fails authorization, you can change the authentication/forms/loginUrl setting in web.config. Keep in mind, though, that this affects all authentication redirects for your entire application.
  2. If you want to run custom logic - including but not limited to redirecting to a URL - you can override the AuthorizeAttribute's HandleUnauthorizedRequest method.

Many more examples

This is a very simple example. You can find a lot more by searching on the override code above, e.g. "override authorizecore httpcontextbase". Some examples:

Note: The last one on the list implements the base AuthorizeAttribute interfaces rather than subclassing AuthorizeAttribute, which bears some discussion.

Subclass AuthorizeAttribute or Implement FilterAttribute, IAuthorizationFilter?

If you just look at the AuthorizeCore code in the AuthorizeAttribute, you may think it's so trivial you might as well just build your own IAuthorizationFilter from scratch. The problem with that idea is that it's very easy to do that incorrectly. A large amount of the code in the AuthorizeAttribute is there to make sure it works correctly with caching. If you get this wrong, you can very easily open yourself up to this scenario:

  1. Authorized user accesses an action and is correctly granted access.
  2. The action uses output caching, so the output is cached for future views.
  3. Unauthorized user accesses the action. Since it was cached, the restricted (or user-specific) content is served to the unauthorized user.

The AuthorizeAttribute has ensured that the code in the CacheValidateHandler and OnCacheAuthorization methods interact correctly with ASP.NET's caching system. Unless you really know what you're doing, it's a much better idea to start by subclassing AuthorizeAttribute.

Using AuthorizeAttribute with ASP.NET Web API

ASP.NET Web API uses the same AuthorizeAttribute scheme. It works the same way - drop an attribute on actions, API controllers, or globally, and you're set. All good so far.

But, if you use System.Web.Mvc.AuthorizeAttribute (or a subclassed attribute) on an Action Controller, nothing will happen. ASP.NET Web API uses a very similar, but different AuthorizeAttribute, found in the System.Web.Http namespace. There are some important differences (beyond the scope of this post), but a good place to look is at how the two AuthorizeAttributes handle unauthorized requests:

This reflects the difference between the target focus of both systems - ASP.NET MVC primarily focuses on HTML code that's viewed by people in a browser, and ASP.NET Web API primarily focuses on HTTP traffic that's handled by code. In ASP.NET Web API, you don't tell someone they're not authorized with a login page, you return the appropriate HTTP status code.

Fluent Security

If you have complex authorization requirements - particularly around configuration - you might want to look at Fluent Security. It provides a fluent, code-based configuration system, which lets you do define your application's authentication requirements in one place, like this:

SecurityConfigurator.Configure(configuration =>
{
    // Let Fluent Security know how to get the authentication status of the current user
    configuration.GetAuthenticationStatusFrom(() => HttpContext.Current.User.Identity.IsAuthenticated);

    // Let Fluent Security know how to get the roles for the current user
    configuration.GetRolesFrom(() => MySecurityHelper.GetCurrentUserRoles());

    // This is where you set up the policies you want Fluent Security to enforce
    configuration.For<HomeController>().Ignore();

    configuration.For<AccountController>().DenyAuthenticatedAccess();
    configuration.For<AccountController>(x => x.ChangePassword()).DenyAnonymousAccess();
    configuration.For<AccountController>(x => x.LogOff()).DenyAnonymousAccess();

    configuration.For<BlogController>(x => x.Index()).Ignore();
    configuration.For<BlogController>(x => x.AddPost()).RequireRole(BlogRole.Writer);
    configuration.For<BlogController>(x => x.AddComment()).DenyAnonymousAccess();
    configuration.For<BlogController>(x => x.DeleteComments()).RequireRole(BlogRole.Writer);
    configuration.For<BlogController>(x => x.PublishPosts()).RequireRole(BlogRole.Owner);
});

GlobalFilters.Filters.Add(new HandleSecurityAttribute(), 0);

Customizing ASP.NET MVC Authorization using the existing ASP.NET Security systems

ASP.NET has been around for a long time. It's been beaten on pretty hard, and the existing systems have undergone a huge amount of real-world testing. When you run into a constraint that pushes you towards writing some custom code, the best approach is to make sure you understand how the existing systems work and integrate with them as closely as possible.

Since ASP.NET has been around for a long time, there is a good amount of existing information on the security system. It's a big topic. I'm just going to (try to) summarize, pointing out the best extension points from an ASP.NET MVC point of view.

Extending the Forms Authentication provider

As mentioned earlier, authentication is the process of establishing who the user is. It doesn't say anything about what access you've got, it just verifies that you are who you claim to be. ASP.NET has some built in systems to handle that - the Forms Authentication provider handles browser based login and account management, and there's a Windows Authentication provider which integrates with the Windows authentication. If you need to modify how authentication works, you'll almost certainly be working with the Forms Authentication provider.

You might assume that you extend authentication by plugging in a new Authentication Provider, but that's not the case. There are two in the box Authentication Providers, and you can't add new ones. That's pretty much never an issue, though, because the Forms Authentication provider gives you plenty of hooks for extension.

Warning: The next paragraph is exceptionally nerdy, but it sets some important background for interfacing with Forms Authentication.

Forms Authentication uses a Forms Authentication Ticket to track your identity - essentially your authenticated username. The ticket is stored in an encrypted Forms Authentication Cookie.  There's support for cookieless authentication, which automatically appends cookie information via an encrypted querystring value. There are two main components that make Forms Authentication work - the FormsAuthetication class which sets the authentication cookie for authenticated users, and a FormsAuthenticationModule which checks for the cookie, authenticates you and sets your identity in the HttpContext. Since FormsAuthenticationModule is an HTTP module, it runs for every request, way at the beginning of the pipeline. That's an important part - a secure authentication system needs to check authentication at the beginning of the request.

This is all underlying machinery - the important part is that when someone logs in, something in your application calls FormsAuthentication.SetAuthCookie(). That sets the Authentication Cookie, which is then checked by the FormsAuthenticationModule on each request. You can see an example of how the default ASP.NET MVC AccountController Login method uses it:

[AllowAnonymous]
[HttpPost]
public ActionResult Login(LoginModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        if (Membership.ValidateUser(model.UserName, model.Password))
        {
            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }
        else
        {
            ModelState.AddModelError("", "The user name or password provided is incorrect.");
        }
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

A good example is DotNetOpenAuth, which adds OpenID, OAuth, and InfoCard authentication to ASP.NET by integrating with the ASP.NET Forms Authentication ticket. You can see how this works in the DotNetOpenAuth OpenAuthAuthenticationTicketHelper.cs class, and in the OpenIdRelyingPartyMvc sample's UserController.

The important points here:

  • While it's tempting to look at your custom authentication needs as completely unique, most can be handled by determining who a user is (your code) and then telling ASP.NET Forms Authentication to track them.
  • If you decide that you'd rather just handle authentication outside of ASP.NET, you've got a lot to think about. You'll be writing a lot of new code which hasn't gone through near the security testing, beating, improvements, etc., that Forms Authentication has.

The ASP.NET Roles and Membership System

The above authentication discussion was completely independent of where and how the actual user information was stored, and that's important. Forms Authentication doesn't handle passwords, logins, user roles, etc., it just tracks users once it's been told about them.

ASP.NET Membership

The default system for managing user and is ASP.NET Membership. There's a SqlMembershipProvider that runs against a SQL Server database, but the provider system allows you to plug in your own custom Membership Provider for managing users. Your login process can use your membership provider to validate the user's credentials, and you can use the membership system to store user information if you want. More on that in a bit.

ASP.NET Role Management

For some sites, authorization and authentication are nearly synonymous - the only goal of authorization is to prevent anonymous access. But for many sites, you've got different roles - users, administrators, superadministrators, and omegasupremeadministrators. For those cases, you need something that maps users to roles, and that's what Role Management Providers do. In most cases, roles and membership are managed together - the same system that tracks who your users are controls what rights they have. You'll often see role and membership providers in one big package, but they're two separate things.

Customizing Membership in ASP.NET

As before, the zeroth rule of customizing membership is to reconsider if you need to. There are plenty of hooks into the existing flow, such as overriding OnAuthorization and just adding some information to HttpContext.Items, Session, etc.

If you really do need a custom user management system, the first thing to do is look to see if someone's already written it. There are membership providers for a lot of backing systems. A quick search shows tons of them:

Implementing your own Membership Provider

If you don't find a Membership Provider that works for you, it's not difficult to write your own. Remember that you're taking more responsibility for your system's security. Matt Wrock wrote a great overview: Implementing custom Membership Provider and Role Provider for Authenticating ASP.NET MVC Applications.

There's plenty of information on MSDN as well, for example: Implementing a Membership Provider

Simple Membership

You'll notice that a lot of Matt's overview of creating Membership and Role Providers included a lot of System.NotImplementedException, because the ASP.NET Membership Provider system shows some underlying assumptions around user data going in relational databases. You can just ignore those parts and use what you want, but if you find the whole thing a little too complex and are tempted to throw it all out, I'd recommend looking at SimpleMembership from ASP.NET Web Pages.

Matthew Osborn wrote an overview of what SimpleMembership is and how it works in ASP.NET Web Pages. Although it was originally written for ASP.NET Web Pages, it can be readily adapted to ASP.NET MVC using the SimpleMembership.Mvc NuGet package.

Wrapping Up

ASP.NET MVC gives you a huge amount of flexibility, and it's tempting to want to write a lot of custom code. If you understand the underlying security systems that ASP.NET MVC uses, though, you can usually integrate with what's in place. You'll be saving yourself a lot of unnecessary code, along with the added costs of testing, debugging and maintenance. More important, though, you'll be using a system that's undergone a huge amount of security testing over the past decade.

For further study:

Limits of performance optimization

Datasheet ThumbnailBack in college, where I was an Electrical Engineering undergrad, I had an especially difficult professor for my microcontrollers course. In this course, we would hand-roll assembly language instructions and upload them to the 68HC12 testing board. (Side-note, I never, EVER want to hand-roll assembly language again. Or hand-compile C code to assembly).

In microcontrollers, onboard memory is a huge limiting factor. Modern devices have lots of available memory, but for embedded devices, your ROM pretty much decides how complicated your program can be.

As part of the course, we were graded on how compact our code was, rather than merely how correct it was. And this makes sense, since compactness can allow for more features/decisions etc.

So we all made reasonable efforts to compact our code using common tricks like shift-operators for multiplication and so on. However, what we didn’t know is that our professor had spent 20-30 years optimizing assembly code for compactness, and our efforts were being graded against his. Any deviation from his solution was a deduction in our grade.

After receiving poor marks, and seeing why, we all as a class reviewed the (his) solution. And wouldn’t you know that while compact, code optimized to its maximum is nearly impossible to understand or maintain. No one in the class, viewing the code for the first time, would be able to decipher what it actually did.

Long-term maintainability

Since we change code far more often than we write code, optimizing solely for performance can make it difficult or impossible to change that code in the future. In the case of our college course, we were being held to standards that were nearly impossible to reach, let alone understand. Performance isn’t an accomplishment, it’s a feature.

It’s a feature that needs to be balanced against all other constraints, like the ability to maintain the code in the future. Highly optimized code often becomes more difficult to understand or comprehend, making it difficult to tweak or refactor in the future.

So when looking at performance optimization, which is many times a necessary endeavor, always keep an eye on the true goal of the performance optimization. How much more optimized does it need to be? What is the threshold for success?

Performance optimization without a clear definition of success just leads down the path of obfuscation and unmaintainability. Optimization does have an upper limit, not only in terms of gains, but of losses in maintainability.

Ajax Control Toolkit May 2012 Release

I’m happy to announce the May 2012 release of the Ajax Control Toolkit. This newest release of the Ajax Control Toolkit includes a new file upload control which displays file upload progress. We’ve also added several significant enhancements to the existing HtmlEditorExtender control such as support for uploading images and Source View. You can download [...] Read More......(read more)

Persisting enumeration classes with NHibernate

As part of my “Crafting Wicked Domain Models” talk, I walk through the concept of enumeration classes, yanked from Java and on Jon Skeet’s list of biggest C# mistakes (or missing features). In my talk, I leave out how to bridge the gap from your domain model to an ORM, simply because it’s just out of scope for that talk to address persistence concerns. Besides, the ORM I use these days to persist relational domain models (NHibernate) handles all the crazy cases an more, so I don’t feel like looking at anything else.

But what I leave out of a talk, I can certainly blog about! Suppose we have one of our enumeration classes (available here on NuGet):

public class Color : Enumeration<Color>
{
    private Color(int value, string displayName)
        : base(value, displayName)
    {
    }

    public static readonly Color Red
        = new Color(1, "Red");
    public static readonly Color Blue
        = new Color(2, "Blue");
}
view raw Color.cs This Gist brought to you by GitHub.

When it comes time to persisting this enumeration class, we want to make sure that the database schema uses the integer value as what gets persisted. When it writes, we want the value to persist, and when it reads, we want the correct enumeration value (Red/Blue) to be hydrated.

To do this in NHibernate, we’ll first need a custom type:

public class EnumerationType<T> : PrimitiveType where T : Enumeration<T>
{
    public EnumerationType()
        : base(new SqlType(DbType.Int32))
    {
    }

    public override object Get(IDataReader rs, int index)
    {
        var o = rs[index];
        var value = Convert.ToInt32(o);
        return Enumeration<T>.FromInt32(value);
    }

    public override object Get(IDataReader rs, string name)
    {
        var ordinal = rs.GetOrdinal(name);
        return Get(rs, ordinal);
    }

    public override Type ReturnedClass
    {
        get { return typeof(T); }
    }

    public override object FromStringValue(string xml)
    {
        return int.Parse(xml);
    }

    public override string Name
    {
        get { return "enumeration"; }
    }

    public override void Set(IDbCommand cmd, object value, int index)
    {
        var parameter = (IDataParameter)cmd.Parameters[index];

        var val = (Enumeration<T>)value;

        parameter.Value = val.Value;
    }

    public override string ObjectToSQLString(object value, Dialect dialect)
    {
        return value.ToString();
    }

    public override Type PrimitiveClass
    {
        get { return typeof(int); }
    }

    public override object DefaultValue
    {
        get { return 0; }
    }
}

This class is the bridge between our ORM (NHibernate) and our enumeration class. NHibernate is fantastic in its ability to provide easy ways to bridge to value objects. Value objects help avoid primitive obsession, but is only useful if you can actually use them when you’re mapping to your persistence layer.

To instruct NHibernate to use our custom types when reading/writing, the easiest way to do so is with a Fluent NHibernate convention:

public class EnumerationTypeConvention : IPropertyConvention, IPropertyConventionAcceptance
{
    private static readonly Type OpenType = typeof(EnumerationType<>);

    public void Apply(IPropertyInstance instance)
    {
        var closedType = OpenType.MakeGenericType(instance.Property.PropertyType);

        instance.CustomType(closedType);
    }

    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => IsEnumerationType(x.Property.PropertyType));
    }

    private bool IsEnumerationType(Type type)
    {
        return GetTypeHierarchy(type)
            .Where(t => t.IsGenericType)
            .Select(t => t.GetGenericTypeDefinition())
            .Any(t => t == typeof(Enumeration<>));
    }

    private IEnumerable<Type> GetTypeHierarchy(Type type)
    {
        while (type != null)
        {
            yield return type;
            type = type.BaseType;
        }
    }
}

This convention walks the type hierarchy for each property type given, and checks to see if the property type’s type hierarchy is a generic type that closes the open generic type of our enumeration class. Finally, we just need to hook our convention up to Fluent NHibernate, but that really depends on how we have Fluent NHibernate hooked up. We don’t have to use Fluent NHibernate to hook up our custom user type, but it’s much easier this way.

With NHibernate, we get the benefits of using Java-style enumeration classes, and have it seamlessly plug in to our persistence layer, which is the whole point of ORMs, right?

Task Parallel Library and Servers, Part 4: TaskHelpers

This is part 4 in a series on using Task Parallel Library when writing server applications, especially ASP.NET MVC and ASP.NET Web API applications.

  1. Introduction
  2. SynchronizationContext
  3. ContinueWith
  4. TaskHelpers

Simple Task Helpers

I know we left off in part 3 with a problem, but we're not going to solve it yet, because we still need to build some foundation helper classes that will make it easier to do that. In particular, there are some good practices we can codify around the creation and conversion of tasks that led us to write the TaskHelpers class that we use today in ASP.NET Web Stack.

Caching Tasks (and Disposability)

One of the important things to remember about TaskCompletionSource is that it can be somewhat expensive to create. If you look at the implementation of the async/await compiler feature, you'll see that they go to great lengths to cache a bunch of reusable tasks; we don't go quite as far, but we have at least centralized our creation of completed, canceled, and faulted tasks so that we can improve this caching logic as time goes on, as we see fit.

You might've noticed that the Task class implements IDisposable; doesn't that mean you should dispose it when you're done with it? Wouldn't that invalidate all this caching work? It turns out the answer is not so simple; the truth is that it's often impossible to know who the true owner of a task is. Stephen Toub, the architect behind the Task Parallel Library, argues that you should not dispose your Task objects, and his work with the compiler team to enable their caching behavior in .NET 4.5 is the ultimate validation of this argument. Resist the temptation: do not dispose your Task!

Canceled Tasks

The first and easiest helpers to show are for the creation of canceled tasks. These are also the easiest thing to cache, since they have no state, so we also get to show how caching might work for the more complex versions.

public static class TaskHelpers
{
    public static Task Canceled()
    {
        return CancelCache<AsyncVoid>.Canceled;
    }

    public static Task<TResult> Canceled<TResult>()
    {
        return CancelCache<TResult>.Canceled;
    }
}

static class CancelCache<TResult>
{
    public static readonly Task<TResult> Canceled
        = GetCancelledTask();

    static Task<TResult> GetCancelledTask()
    {
        var tcs = new TaskCompletionSource<TResult>();
        tcs.SetCanceled();
        return tcs.Task;
    }
}

struct AsyncVoid { }

We are taking advantage of the static initialization facilities of the C# language, combined with generics, to get a create-on-demand, cached-for-app-lifetime canceled task.

You'll notice that I'm using a private struct (AsyncVoid) as a stand-in to represent the T for our cancel cache. We could have just as easily used any other type, but my feeling here is that it should be trivial to look at some Task object which is-a Task<T> and know whether it was purposefully or accidentally casted down to Task. Perhaps just as importantly, there is no non-generic version of TaskCompletionSource, so not having the result be a Task<T> was kind of out of the question.

Completed Tasks

Our next task creation helper is around completed tasks. Here, we do a small amount of caching for completed Task, as well as a completed Task<object> which returns null. The compiler in .NET 4.5 is much more aggresive about pre-computing and caching completed tasks with common return values; we could do the same thing at some point in the future if we so desired, since we funnel all our helpers through here.

public static class TaskHelpers
{
    static readonly Task<object> _completedTaskReturningNull
        = FromResult<object>(null);

    static readonly Task _defaultCompleted
        = FromResult<AsyncVoid>(default(AsyncVoid));

    public static Task Completed()
    {
        return _defaultCompleted;
    }

    public static Task<TResult> FromResult<TResult>(
        TResult result)
    {
        var tcs = new TaskCompletionSource<TResult>();
        tcs.SetResult(result);
        return tcs.Task;
    }

    public static Task<object> NullResult()
    {
        return _completedTaskReturningNull;
    }
}

Faulted Tasks

The final kind of task creation we need to support is faulted tasks. There is really no opportunity for caching here, since the exception objects will be different every time. Note that there are two versions here, one which takes a single exception and one which takes many exceptions; the latter is useful when you're aggregating the results of several faulted tasks together.

public static class TaskHelpers
{
    public static Task FromError(
        Exception exception)
    {
        return FromError<AsyncVoid>(exception);
    }

    public static Task<TResult> FromError<TResult>(
        Exception exception)
    {
        var tcs = new TaskCompletionSource<TResult>();
        tcs.SetException(exception);
        return tcs.Task;
    }

    public static Task FromErrors(
        IEnumerable<Exception> exceptions)
    {
        return FromErrors<AsyncVoid>(exceptions);
    }

    public static Task<TResult> FromErrors<TResult>(
        IEnumerable<Exception> exceptions)
    {
        var tcs = new TaskCompletionSource<TResult>();
        tcs.SetException(exceptions);
        return tcs.Task;
    }
}

Run Synchronously

Calling Task.Factory.StartNew when you don't actually need to do anything asynchronously can be expensively wasteful, because it's likely to spin up a worker thread and cause a thread switch to run your inherently synchronously code. We have several overloads of RunSynchronously which can be used to get Task objects which are already completed and contain the result of the synchronous code. These functions also accept cancellation tokens, and return canceled tasks when the token is signaled; they also take advantage of our previous helper methods to get caching benefits.

public static class TaskHelpers
{
    public static Task RunSynchronously(
        Action action,
        CancellationToken token = default(CancellationToken))
    {
        if (token.IsCancellationRequested)
            return Canceled();

        try
        {
            action();
            return Completed();
        }
        catch (Exception e)
        {
            return FromError(e);
        }
    }

    public static Task<TResult> RunSynchronously<TResult>(
        Func<TResult> func,
        CancellationToken token = default(CancellationToken))
    {
        if (token.IsCancellationRequested)
            return Canceled<TResult>();

        try
        {
            return FromResult(func());
        }
        catch (Exception e)
        {
            return FromError<TResult>(e);
        }
    }

    public static Task<TResult> RunSynchronously<TResult>(
        Func<Task<TResult>> func,
        CancellationToken token = default(CancellationToken))
    {
        if (token.IsCancellationRequested)
            return Canceled<TResult>();

        try
        {
            return func();
        }
        catch (Exception e)
        {
            return FromError<TResult>(e);
        }
    }
}

Copying Task Results to TaskCompletionSource

The final bit of helpers for this post are a few extension methods for TaskCompletionSource which can be used to partially or fully copy the results of a task onto the completion source. These helpers only set the results if the task is currently complete; they don't wait for the task to complete if it has not already done so.

public static class TaskHelpers
{
    public static bool TrySetFromTask<TResult>(
        this TaskCompletionSource<TResult> tcs,
        Task source)
    {
        if (source.Status == TaskStatus.Canceled)
            return tcs.TrySetCanceled();

        if (source.Status == TaskStatus.Faulted)
            return tcs.TrySetException(
                source.Exception.InnerExceptions);

        if (source.Status == TaskStatus.RanToCompletion)
        {
            var tr = source as Task<TResult>;
            return tcs.TrySetResult(
                tr == null
                    ? default(TResult)
                    : tr.Result);
        }

        return false;
    }

    public static bool TrySetFromTask<TResult>(
        this TaskCompletionSource<Task<TResult>> tcs,
        Task source)
    {
        if (source.Status == TaskStatus.Canceled)
            return tcs.TrySetCanceled();

        if (source.Status == TaskStatus.Faulted)
            return tcs.TrySetException(
                source.Exception.InnerExceptions);

        if (source.Status == TaskStatus.RanToCompletion)
        {
            // Sometimes the source is Task<Task<TResult>>,
            // and sometimes it's Task<TResult>. Handle both.

            var ttr = source as Task<Task<TResult>>;
            if (ttr != null)
                return tcs.TrySetResult(ttr.Result);

            var tr = source as Task<TResult>;
            if (tr != null)
                return tcs.TrySetResult(tr);

            return
                tcs.TrySetResult(
                    FromResult(default(TResult)));
        }

        return false;
    }

    public static bool TrySetIfFailed<TResult>(
        this TaskCompletionSource<TResult> tcs,
        Task source)
    {
        switch (source.Status)
        {
            case TaskStatus.Canceled:
            case TaskStatus.Faulted:
                return tcs.TrySetFromTask(source);
        }

        return false;
    }
}

What's Next?

We've got a firm understanding of the fundamentals, and built up all the necessary infrastructure, so now we're ready to start writing our replacement helpers for the existing Task methods; in particular, we will be looking to completely replace the usage of ContinueWith with safer, targeted, a better performing helper methods.

Windows 8 and ASP.NET Web API – Part 1 – Getting Started

Many of the key Windows 8 Metro Style application features either require or can greatly benefit from a connection to online services. ASP.NET Web API is a great fit for these services, as it's tightly focused around providing HTTP services to applications. I'm starting a series that will look at how to leverage ASP.NET Web API services from Windows 8 applications.

In this first post in the series, we'll begin with a simple C# Windows 8 Metro Style application that displays data from the ASP.NET Web API Contact Manager sample. Once we've got the basics locked down, we'll move on to some more complex topics. I'm thinking Live Tiles and Notifications, but I'm interested in your ideas of where to go next, so please let me know in the comments.

The ASP.NET Web API Contact Manager sample

I thought it would be simplest to start with an official, tried and true Web API sample that's been around since the early days of WCF Web API - the Contact Manager Sample. You can download the code here: http://code.msdn.microsoft.com/Contact-Manager-Web-API-0e8e373d

This code is originally written for Visual Studio 2010, but I'm going to be working on Visual Studio 11 Beta running on Windows 8 Consumer Preview, so I ran through the upgrade. There's an alert which says "One or more Web Application projects in this solution require SQL Server Express. You will need to download and install the appropriate version of SQL Server Express for these projects to work." A quick look at the code, however shows that all the data is in-memory, so we can ignore it. If we keep with this code for long, we can just remove the offending NuGet package, but let's not let that slow us down just yet.

Running the application shows that the application is indeed working.

2012-04-27_01h26_16

The HTML client page is making an .getJSON() call back to the Web API service, which returns a list of contacts in JSON format, then uses jQuery templating to display the contacts in HTML format. That jQuery templating should probably be updated to use the newer JSRender system, but it doesn't really matter for this example, since we're just concerned about the services, not the HTML client.

Looking at the ASP.NET Web API's services using F12 developer tools

We're going to be using Fiddler2 in a bit, but since the simplest way to view the output of the Web API's JSON services is in a browser. In IE, you do that by pressing the F12 hotkey to display developer tools - it looks like this:

2012-04-27_02h01_20

Now switch to the Network view (or your browser's equivalent), start monitoring, and browse to /contacts (in my case the full URL is http://localhost:33936/contacts, your port number will vary). IE prompts you to download the JSON file and the browser's address bar goes back to the previous. That's a little wacky - other browsers display the JSON as text - but the service call response is included in the results. Clicking on it to bring up the detailed view and showing the response body shows the JSON data:

2012-04-27_02h09_00

The JSON data returned is as follows (I removed some of the contacts from the list for brevity):

[ { "Address" : "1 Microsoft Way",
    "City" : "Redmond",
    "ContactId" : 1,
    "Email" : "gblock@microsoft.com",
    "Name" : "Glenn Block",
    "Self" : "contact/1",
    "State" : "Washington",
    "Twitter" : "gblock",
    "Zip" : "98112"
  },
  { "Address" : "1 Microsoft Way",
    "City" : "Redmond",
    "ContactId" : 2,
    "Email" : "howard@microsoft.com",
    "Name" : "Howard Dierking",
    "Self" : "contact/2",
    "State" : "Washington",
    "Twitter" : "howard_dierking",
    "Zip" : "98112"
  },
  { "Address" : "1 Microsoft Way",
    "City" : "Redmond",
    "ContactId" : 3,
    "Email" : "yavorg@microsoft.com",
    "Name" : "Yavor Georgiev",
    "Self" : "contact/3",
    "State" : "Washington",
    "Twitter" : "digthepony",
    "Zip" : "98112"
  }]

That content's being returned from the ContactsController's Get action, which just returns a Queryable list:

public IQueryable Get()
{
    return this.repository.GetAll().AsQueryable();
}

Out of the box, ASP.NET Web API can format data in JSON and XML format, so the output is automatic depending on content negotiation. If you're familiar with ASP.NET Web API, this is all pretty standard stuff. If you're not, I recommend the ASP.NET Web API content section at http://asp.net/web-api and my previous blog / screencast series on getting started with ASP.NET Web API.

The point is that this sample is producing JSON data that we can display in our Windows 8 Metro application.

Creating a Windows 8 Metro style application using the Blank template

To create the Windows 8 Metro application, add a new project using the File / Add / New Project... dialog. Select the Visual C# / Windows Metro Style section, then pick the Blank Application template. I called mine ContactManagerMetro because I have no imagination.

2012-04-27_00h49_24

Why the Blank Application template? Good question. I started with the Split Application template, but it has existing data structures which are hierarchical (since the Split Application helps with navigating structured content), so it wasn't a good fit. I think the Blank Application template is a good start since it's nice and simple.

This application is, as promised, rather blank. The main form is even called BlankPage.xaml, which while being rather descriptive of the initial state, seems unlikely to remain accurate for very long in most cases. Since we're just proving concepts at this point, though, I'm going to grit my teeth and leave the name as BlankPage.xaml. Focus.

Writing the Metro Application XAML

We've got a lot of options for how to display the contact information, but I think a good start is using the same kind of display that the original HTML view used. In the Metro XAML land, that's usually done using a ListView. Inside BlankPage.xaml's empty grid, I'm going to add the following ListView markup:

<GridView x:Name="ContactList">
    <GridView.ItemTemplate>
        <DataTemplate>
            <StackPanel Width="200" Height="150" Margin="10" Background="#FF161C8F">
                <TextBlock Text="{Binding Name}" FontSize="24" />
                <TextBlock Text="{Binding Address}" />
                <TextBlock Text="{Binding City}" />
                <TextBlock Text="{Binding State}" />
                <TextBlock Text="{Binding Zip}" />
                <TextBlock Text="{Binding Twitter}" />
            </StackPanel>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

This is pretty rudimentary, we'll clean it up later. The main reason I'm writing it now is to make sure I know what I'll be binding to, and for the above TextBlock binding values I just based the values off the contact properties returned by the service.

Calling the Web API service from our Metro Application

Calling the service is actually pretty straightforward. First, I'll use the System.Net.Http.HttpClient to call the service. As all external calls in WinRT are async, I need to handle that. Fortunately the async/await keywords make that really easy.

Since our service returns JSON, I'm going to leverage the utility classes in the Windows.Data.Json namespace to parse it. The code is a little repetitive and could definitely use some refactoring, but it handles the job of mapping JSON values to an anonymous object. Tim Heuer recently blogged about using that with anonymous type binding, and I liked his approach.

With all the plumbing in place, I'll call this GetContacts() method from my OnNavigatedTo event.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    GetContacts();
}

public async void GetContacts()
{
    var serviceuri = "http://localhost:33936/contacts";
    var client = new System.Net.Http.HttpClient();

    var response = await client.GetAsync(serviceuri);
    if (response.IsSuccessStatusCode)
    {
        var data = await response.Content.ReadAsStringAsync();
        var contacts = JsonArray.Parse(data);

        var qry = from m in contacts
            select new
            {
                Name = m.GetObject()["Name"].GetString(),
                Address = m.GetObject()["Address"].GetString(),
                City = m.GetObject()["City"].GetString(),
                State = m.GetObject()["State"].GetString(),
                Zip = m.GetObject()["Zip"].GetString(),
                Twitter = m.GetObject()["Twitter"].GetString(),
            };

        ContactList.ItemsSource = qry;
    }
}

This calls into our service and displays the following data:

Screenshot

Hurrah! We got data from our service and viewed it in the app. It's pretty ugly, though. Let's clean up the formatting a bit so it matches the original app a little better. I'm using the underappreciated <Run> XAML element for that:

<GridView x:Name="ContactList">
    <GridView.ItemTemplate>
        <DataTemplate>
            <StackPanel Width="250" Height="150" Margin="10" Background="#FF161C8F">
                <TextBlock Text="{Binding Name}" FontSize="28" Margin="10,20,10,0" />
                <TextBlock Margin="10,0">
                    <Run Text="{Binding Address}" />, <Run Text="{Binding City}" />
                </TextBlock>
                <TextBlock Margin="10,0">
                    <Run Text="{Binding State}" /> <Run Text="{Binding Zip}" />
                </TextBlock>
                <TextBlock Margin="10,0">
                    @<Run Text="{Binding Twitter}" />
                </TextBlock>
            </StackPanel>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

That at least organizes the text a bit:

Screenshot (2)

And that's at least a decent start. Questions? Where should we go next?

Great Free Course on Building ASP.NET MVC Apps With EF Code First, HTML5 and jQuery

Pluralsight has developed a great training course on Building ASP.NET MVC Apps with EF Code First, HTML5 and jQuery .  It is presented by the most excellent Dan Wahlin , and is really comprehensive.  Details of the course outline can be found here . Free 1-Month Subscription to the Course Pluralsight is offering a special promotion that allows you to get a free 1-month subscription to watch the above course as many time as you want at no cost.  There is no obligation to buy anything at the end of the offer and you don’t need to supply a credit card in order to take part in it. To get access to the course you simply follow @pluralsight on Twitter and then visit this page and enter your Twitter name using the form on it.  Pluralsight...(read more)

ASP.NET MVC Authentication – Global Authentication and Allow Anonymous

As I was recently updating the Wrox Professional ASP.NET book for ASP.NET MVC 4, I thought about some of the common questions, tip, and tricks I've seen over the past few years, and thought it was time for a... quick blog series! Let's start with Global Authentication.

ASP.NET MVC has had an Account Controller since the ASP.NET MVC 1.0 preview releases; it handles login and registration. That, by itself, just allows users to get logged in - it doesn't do anything to restrict access. That's where the AuthorizeAttribute comes into play. AuthorizeAttribute is a Filter attribute which can be placed on ASP.NET MVC actions or entire controllers to prevent unauthorized access. Attempting to access a restricted controller action when you're not authorized redirects you to login, as I previously described in quite gory detail in a previous post titled Looking at how the ASP.NET MVC Authorize interacts with ASP.NET Forms Authorization.

Reminder: Don't use web.config to restrict access, use [Authorize]

Note: This is old news to MVC veterans, but bears repeating because it continues to be a common question and is really important to get right.

In ASP.NET Web Forms, requests mapped to physical files. There's an <authorization> element  in web.config which can be used to restrict file-based access. So this worked well for ASP.NET Web Forms and file-based authorization in general.

But it's a very bad idea to use web.config based authorization in ASP.NET MVC, because URL's map to actions via routing, which can change. You may have multiple routes that map to the same controller action, or you may change routes over time. AuthorizeAttribute was built specifically for this purpose, because you can place your security directly on the resource (the action or controller). Change the routes all you want, the authorization rules go along with the actions.

Another interesting note here is that, since ASP.NET Web Forms has supported routing since ASP.NET 4, you need to pay closer attention to securing routes there as well. K. Scott Allen discussed that in an MSDN Magazine article a few years ago, Routing with ASP.NET Web Forms.

The progression of global authentication in ASP.NET MVC

The AuthorizeAttribute works pretty well, but you have to put it on every controller (or action, if you need to be that granular) that needs to be secured. That's tedious and error prone, and if you forget it, you've opened your site up to anonymous access. In many cases, it's preferable to restrict access to the entire site except for the the Login and Register actions. That's become a little easier with each release, to the point where in ASP.NET MVC 4 I think it's finally about right.

Rick Anderson wrote two comprehensive posts on this - and authorization in ASP.NET MVC in general - in a pair of posts covering security in ASP.NET MVC:

ASP.NET MVC 1 and 2 - Custom Controller Base

In the first post, Rick explains that prior to ASP.NET MVC 3, the recommended approach was to create a custom Controller base class with an [Authorize] attribute applied. This probably sounds more complicated than it is, because it's really easy:

  1. Right-click the Controllers folder and add a new Controller. Call it something like AuthorizedController.
  2. Delete the Index action.
  3. Add the [Authorize] attribute to the class.
  4. Clean up the Using block at the top if you care about that kind of thing.

End result:

using System.Web.Mvc;

namespace InstantMonkeysOnline.Controllers
{
    [Authorize]
    public class AuthorizedController : Controller
    {
    }
}

Now you can use this AuthorizedController base class for any other controllers in your application. Changing the HomeController base class to inherit from AuthorizedController will require authorization to view the site home:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace InstantMonkeysOnline.Controllers
{
    public class HomeController : AuthorizedController
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

            return View();
        }

        //More actions here
    }
}

The downside is that you have to remember to do this, so unless you change the T4 templates, you're setting yourself up for an easy mistake down the road.

ASP.NET MVC 3 - Global Action Filters

ASP.NET MVC 3 made it easy to apply an action filter to all actions in your application. If you look in the Global.asax in an new ASP.NET MVC 3 (or later) application, you'll see a RegisterGlobalFilters method.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
}

To require authorization throughout your application, you could just register AuthorizationAttribute, right?

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new AuthorizeAttribute());
}

Unfortunately, this works a little too well - it's global, so users can't login. But, really, really secure, right?

Rick proposed a custom LoginAuthorizeAttribute which inherited from AuthorizeAttribute but added an exception for the AccountController, but Levi Broderick (an ASP.NET team member who's a whiz with web security) recommended using a filter to whitelist actions which should be available for anonymous access.

using System.Web.Mvc;
using MvcGlobalAuthorize.Controllers;

namespace MvcGlobalAuthorize.Filters {
    public sealed class LogonAuthorize : AuthorizeAttribute {
        public override void OnAuthorization(AuthorizationContext filterContext) {
            bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true)
            || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true);
            if (!skipAuthorization) {
                base.OnAuthorization(filterContext);
            }
        }
    }
}

So now you'd register LogonAuthorize as a global filter, and to allow access to an action, you'll need that AllowAnonymousAttribute. Since it's just a marker attribute, there's no actual code - just attribute usage settings.

using System;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, 
                AllowMultiple = false, Inherited = true)]
public sealed class AllowAnonymousAttribute : Attribute { }

ASP.NET MVC 4 and the AllowAnonymous attribute

The good news is that this is even easier in ASP.NET MVC 4, because it's baked in. By baked in, I mean that:

  • There's a built-in AllowAnonymousAttribute in the the System.Web.Mvc namespace which whitelists actions for anonymous access
  • The AuthorizeAttribute filter has built-in logic that allows access to actions decorated with the AllowAnonymousAttribute

That means that you can just register the AuthorizeAttribute as a global filter and put the AllowAnonymousAttribute on any actions that should be public.

If you use the AllowAnonymousAttribute without registering AuthorizeAttribute there's no effect. For that reason, the default AccountController in a new ASP.NET MVC 4 project has [AllowAnonymous] on all the actions that should always be public:

[Authorize]
public class AccountController : Controller
{
    [AllowAnonymous]
    public ActionResult Login()

    [AllowAnonymous]
    [HttpPost]
    public JsonResult JsonLogin(LoginModel model, string returnUrl)

    [AllowAnonymous]
    [HttpPost]
    public ActionResult Login(LoginModel model, string returnUrl)

    public ActionResult LogOff()

    [AllowAnonymous]
    public ActionResult Register()

    [AllowAnonymous]
    [HttpPost]
    public ActionResult JsonRegister(RegisterModel model)

    [AllowAnonymous]
    [HttpPost]
    public ActionResult Register(RegisterModel model)

    public ActionResult ChangePassword()

    [HttpPost]
    public ActionResult ChangePassword(ChangePasswordModel model)

    public ActionResult ChangePasswordSuccess()
}

That works because, as mentioned above, the AuthorizeAttribute has the following logic (as you can see from the code on CodePlex):

bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(
		typeof(AllowAnonymousAttribute), inherit: true)
	|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(
		typeof(AllowAnonymousAttribute), inherit: true);

if (skipAuthorization)
{
    return;
}

Note: I actually started looking into this in detail because I was wondering how the AllowAnonymousAttribute was able to bypass the Authorization check, and was surprised to see that it didn't have any code at all. I wasn't alone here, I noticed David Hayden looked into this as well.

If you're interested in more information on ASP.NET MVC security and the history of the AnonymousAttribute, I highly recommend Rick's posts listed above. He goes into a lot more detail - with some excellent input from Levi - on what not to do (e.g. put security logic into routing) and further considerations like requiring HTTPS globally.

Custom errors and error detail policy in ASP.NET Web API

Today Kurt and I were attempting to debug an Web API service we had deployed to a remote machine. The service was returning 500 errors, and for various reasons, we couldn’t just try to do the requests from that deployed box. We wanted to get the full exception details in the response, but we were just seeing blank 500 errors, with no responses.

We first tried the Web.Config setting for custom errors:

<customErrors mode="Off" />

But this didn’t affect anything. Digging a little further, we found that ASP.NET Web API uses a different configuration for error details being passed along. This is for a couple of reasons; first, the custom errors element in the Web.Config is an ASP.NET thing. It’s something that ASP.NET uses to determine if that yellow screen of death with additional detail should be shown to users. However, ASP.NET Web API is designed to be self-hosted, outside of ASP.NET and IIS. While the customErrors element affects requests for ASPX and MVC, it does nothing for Web API.

Instead of relying on a lot of XML configuration, Web API uses a lot of programmatic configuration. This helps self hosting, but for changing policies like error detail, we have to change the code, re-compile and re-deploy. To set the error policy in our application, we need to modify our global Web API configuration:

GlobalConfiguration.Configuration.IncludeErrorDetailPolicy
    = IncludeErrorDetailPolicy.Always;

With this mode, requests from any source will get us full exception detail. It’s likely not something we want in production, but nice that it is available. We have three familiar options for the IncludeErrorDetailPolicy setting:

  • LocalOnly (default)
  • Always
  • Off

These correspond 1:1 to the customErrror policy in their behavior, but in the reverse. The ASP.NET customErrors setting talks about when to custom errors, where Web API is when to display exception details. Same settings, but approaching from opposite ends.

What if we want to just have Web API use whatever setting that our Web.Config uses? We can just read the ASP.NET setting and apply it to our Web API config:

var config = (CustomErrorsSection)
    ConfigurationManager.GetSection("system.web/customErrors");

IncludeErrorDetailPolicy errorDetailPolicy;

switch (config.Mode)
{
    case CustomErrorsMode.RemoteOnly:
        errorDetailPolicy
            = IncludeErrorDetailPolicy.LocalOnly;
        break;
    case CustomErrorsMode.On:
        errorDetailPolicy
            = IncludeErrorDetailPolicy.Never;
        break;
    case CustomErrorsMode.Off:
        errorDetailPolicy
            = IncludeErrorDetailPolicy.Always;
        break;
    default:
        throw new ArgumentOutOfRangeException();
}

GlobalConfiguration.Configuration.IncludeErrorDetailPolicy
    = errorDetailPolicy;

With this approach, we just set one policy for custom errors in our Web.Config file, and both our MVC/WebForms and WebAPI requests in the same application use the exact same policy, and we have the ability to change this policy after we deploy.