code, asp.net comments edit

If you’re not familiar with WCF Web API, it’s a framework with nice HTTP abstractions used to expose simple HTTP services over the web. Its focus is targeted at applications that provide HTTP services for various clients such as mobile devices, browsers, desktop applications.

In some ways, it’s similar to ASP.NET MVC as it was developed with testability and extensibility in mind. There are some concepts that are similar to ASP.NET MVC, but with a twist. For example, where ASP.NET MVC has filters, WCF has operation handlers.

security

One question that comes up often with Web API is how do you authenticate requests? Well, you run Web API on ASP.NET (Web API also supports a self-host model), one approach you could take is to write an operation handler and attach it to a set of operations (an operation is analogous to an ASP.NET MVC action).

However, some folks like the ASP.NET MVC approach of slapping on an AuthorizeAttribute. In this blog post, I’ll show you how to write an attribute, RequireAuthorizationAttribute, for WCF Web API that does something similar.

One difference is that in the WCF Web API case, the attribute simply provides metadata, but not the the behavior, for authorization. If you wanted to use the existing ASP.NET MVC AuthorizeAttribute in the same way, you could do that as well, but I leave that as an exercise for the reader.

I’ll start with the easiest part, the attribute.

[AttributeUsage(AttributeTargets.Method)]
public class RequireAuthorizationAttribute : Attribute
{
    public string Roles { get; set; }
}

For now, it only applies to methods (operations). Later, we can update it to apply to classes as well if we so choose. I’m still learning the framework so I didn’t want to go bite off too much all at once.

The next step is to write an operation handler. When properly configured, the operation handler runs on every request for the operation that it applies to.

public class AuthOperationHandler 
      : HttpOperationHandler<HttpRequestMessage, HttpRequestMessage>
{
  RequireAuthorizationAttribute _authorizeAttribute;

  public AuthOperationHandler(RequireAuthorizationAttribute authorizeAttribute)
    : base("response")
  {
    _authorizeAttribute = authorizeAttribute;
  }

  protected override HttpRequestMessage OnHandle(HttpRequestMessage input)
  {
    IPrincipal user = Thread.CurrentPrincipal;
    if (!user.Identity.IsAuthenticated)
    {
      throw new HttpResponseException(HttpStatusCode.Unauthorized);
    }

    if (_authorizeAttribute.Roles == null)
    {
      return input;
    }

    var roles = _authorizeAttribute.Roles.Split(new[] { " " }, 
      StringSplitOptions.RemoveEmptyEntries);
    if (roles.Any(role => user.IsInRole(role)))
    {
      return input;
    }

    throw new HttpResponseException(HttpStatusCode.Unauthorized);
  }
}

Notice that the code accesses HttpContext.Current. This restricts this operation handler to only work within ASP.NET applications. Hey, I write what I know! Many folks replied to me that I should use Thread.CurrentPrincipal. My brain must have been off when I wrote this to not think of it. :)

Then all we do is ensure that the user is authenticated and in one of the specified roles if any role is specified. Very simple straightforward code at this point.

The final step is to associate this operation handler with some operations. In general, when you build a Web API application, the application author writes a configuration class that derives from WebApiConfiguration and either sets it as the default configuration, or passes it to a service route.

Within that configuration class, the author can specify an action that gets called on every request and gives the configuration class a chance to map a set of operation handlers to an operation.

For example, in a sample Web API app, I added the following configuration class.

public class CommentsConfiguration : WebApiConfiguration
{
    public CommentsConfiguration()
    {
        EnableTestClient = true;

        RequestHandlers = (c, e, od) =>
        {
            // TODO: Configure request operation handlers
        };

        this.AppendAuthorizationRequestHandlers();
    }
}

The RequestHandlers is a property of type Action<Collection<HttpOperationHandler>, ServiceEndpoint, HttpOperationDescription>

In general, it would be up to the application author to wire up the authentication operation handler I wrote to the appropriate actions. But I wanted to provide a method that helps with that. That’s the AppendAuthorizationRequestHandlers method in there, which is an extension method I wrote.

public static void AppendAuthorizationRequestHandlers(
  this WebApiConfiguration config)
{
  var requestHandlers = config.RequestHandlers;
  config.RequestHandlers = (c, e, od) =>
  {
    if (requestHandlers != null)
    {
      requestHandlers(c, e, od); // Original request handler
    }
    var authorizeAttribute = od.Attributes.OfType<RequireAuthorizationAttribute>()
      .FirstOrDefault();
    if (authorizeAttribute != null)
    {
      c.Add(new AuthOperationHandler(authorizeAttribute));
    }
  };
}

Since I didn’t want to stomp on the existing request handlers, I set the RequestHandlers property to a new action that calls the existing action (if any) and then does my custom registration logic.

I’ll admit, I couldn’t help thinking that if RequestHandlers was an event, rather than an action, that sort of logic could be handled for me. Winking
smile Have events fallen out of favor? They do work well to decouple code in this sort of scenario, but I digress.

The interesting part here is that the action’s third parameter, od, is an HttpOperationDescription. This is a description of the operation that includes access to such things as the attributes applied to the method! I simply look to see if the operation has the RequireAuthorizationAttribute applied and if so, I add the AuthOperationHandler I wrote earlier to the operation’s collection of operation handlers.

With this in place, I can now write a service that looks like this:

[ServiceContract]
public class CommentsApi
{
    [WebGet]
    public IQueryable<Comment> Get()
    {
        return new[] { new Comment 
        { 
            Title = "This is neato", 
            Body = "Ok, not as neat as I originally thought." } 
        }.AsQueryable();
    }

    [WebGet(UriTemplate = "auth"), RequireAuthorization]
    public IQueryable<Comment> GetAuth()
    {
        return new[] { new Comment 
        { 
            Title = "This is secured neato", 
            Body = "Ok, a bit neater than I originally thought." } 
        }.AsQueryable();
    }
}

And route to the Web API service like so:

public class Global : HttpApplication
{
  protected void Application_Start(object sender, EventArgs e)
  {
    RouteTable.Routes.MapServiceRoute<CommentsApi>("comments",
      new CommentsConfiguration());
  }
}

With this in place, a request for /comments allows anonymous, but a request for /comments/auth requires authentication.

If you’re interested in checking this code out, I pushed it to my CodeHaacks Github repository as a sample. I won’t make this into a NuGet package until it’s been thoroughly vetted by the WCF Web API team because it’s very likely I have no idea what I’m doing. I’d rather one of those folks make a NuGet package for this. Smile

And if you’re wondering why I’m writing about Web API, we’re all part of the same larger team now, so I figured it’s good to take a peek at what my friends are up to.

asp.net, code comments edit

I like to live life on the wild side. No, I don’t base jump off of buildings or invest in speculative tranches made up of junk stock derivatives. What I do is attempt to run recurring background tasks within an ASP.NET application.

110121-M-2339L-074 Writing code is totally just like this - Photo by DVIDSHUBCC BY 2.0 

But before I do anything wild with ASP.NET, I always talk to my colleague, Levi (sadly, no blog). As a developer on the internals of ASP.NET, he knows a huge amount about it, especially the potential pitfalls. He’s also quite the security guru. As you read this sentence, he just guessed your passwords. All of them.

When he got wind of my plan, he let me know it was evil, unsupported by ASP.NET and just might kill a cat. Good thing I’m a dog person. I persisted in my foolhardiness and suggested maybe it’s not evil, just risky. If so, how can I do it as safely as possible? What are the risks?

There are three main risks, one of which I’ll focus on in this blog post.

  1. An unhandled exception in a thread not associated with a request will take down the process. This occurs even if you have a handler setup via the Application_Error method. I’ll try and explain why in a follow-up blog post, but this is easy to deal with.
  2. If you run your site in a Web Farm, you could end up with multiple instances of your app that all attempt to run the same task at the same time. A little more challenging to deal with than the first item, but still not too hard. One typical approach is to use a resource common to all the servers, such as the database, as a synchronization mechanism to coordinate tasks.
  3. The AppDomain your site runs in can go down for a number of reasons and take down your background task with it. This could corrupt data if it happens in the middle of your code execution.

It’s this last risk that is the focus of this blog post.

Bye Bye App Domain

There are several things that can cause ASP.NET to tear down your AppDomain.

  • When you modify web.config, ASP.NET will recycle the AppDomain, though the w3wp.exe process (the IIS web server process) stays alive.
  • IIS will itself recycle the entire w3wp.exe process every 29 hours. It’ll just outright put a cap in the w3wp.exe process and bring down all of the app domains with it.
  • In a shared hosting environment, many web servers are configured to tear down the application pools after some period of inactivity. For example, if there are no requests to the application within a 20 minute period, it may take down the app domain.

If any of these happen in the middle of your code execution, your application/data could be left in a pretty bad state as it’s shut down without warning.

So why isn’t this a problem for your typical per request ASP.NET code? When ASP.NET tears down the AppDomain, it will attempt to flush the existing requests and give them time to complete before it takes down the App Domain. ASP.NET and IIS are considerate to code that they know is running,such as code that runs as part of a request.

Problem is, ASP.NET doesn’t know about work done on a background thread spawned using a timer or similar mechanism. It only knows about work associated with a request.

So tell ASP.NET, “Hey, I’m working here!”

The good news is there’s an easy way to tell ASP.NET about the work you’re doing! In the System.Web.Hosting namespace, there’s an important class, HostingEnvironment. According to the MSDN docs, this class…

Provides application-management functions and application services to a managed application within its application domain

This class has an important static method, RegisterObject. The MSDN description here isn’t super helpful.

Places an object in the list of registered objects for the application.

For us, what this means is that the RegisterObject method tells ASP.NET that, “Hey! Pay attention to this code here!” Important! This method requires full trust!

This method takes in a single object that implements the IRegisteredObject interface. That interface has a single method:

public interface IRegisteredObject
{
    void Stop(bool immediate);
}

When ASP.NET tears down the AppDomain, it will first attempt to call Stop method on all registered objects.

In most cases, it’ll call this method twice, once with immediate set to false. This gives your code a bit of time to finish what it is doing. ASP.NET gives all instances of IRegisteredObject a total of 30 seconds to complete their work, not 30 seconds each. After that time span, if there are any registered objects left, it will call them again with immediate set to true. This lets you know it means business and you really need to finish up pronto! I modeled my parenting technique after this method when trying to get my kids ready for school.

When ASP.NET calls into this method, your code needs to prevent this method from returning until your work is done. Levi showed me one easy way to do this by simply using a lock. Once the work is done, the code needs to unregister the object.

For example, here’s a simple generic implementation of IRegisteredObject. In this implementation, I simply ignored the immediate flag and try to prevent the method from returning until the work is done. The intent here is I won’t pass in any work that’ll take too long. Hopefully.

public class JobHost : IRegisteredObject
{
    private readonly object _lock = new object();
    private bool _shuttingDown;

    public JobHost()
    {
        HostingEnvironment.RegisterObject(this);
    }

    public void Stop(bool immediate)
    {
        lock (_lock)
        {
            _shuttingDown = true;
        }
        HostingEnvironment.UnregisterObject(this); 
    }

    public void DoWork(Action work)
    {
        lock (_lock)
        {
            if (_shuttingDown)
            {
                return;
            }
            work();
        }
    }
}

I wanted to get the simplest thing possible working. Note, that when ASP.NET is about to shut down the AppDomain, it will attempt to call the Stop method. That method will try to acquire a lock on the _lock instance. The DoWork method also acquires that same lock. That way, when the DoWork method is doing the work you give it (passed in as a lambda) the Stop method has to wait until the work is done before it can acquire the lock. Nifty.

Later on, I plan to make this more sophisticated by taking advantage of using a Task to represent the work rather than an Action. This would allow me to take advantage of task cancellation instead of the brute force approach with locks.

With this class in place, you can create a timer on Application_Start (I generally use WebActivator to register code that runs on app start) and when it elapses, you call into the DoWork method here. Remember, the timer must be referenced or it could be garbage collected.

Here’s a small example of this:

using System;
using System.Threading;
using WebBackgrounder;

[assembly: WebActivator.PreApplicationStartMethod(
  typeof(SampleAspNetTimer), "Start")]

public static class SampleAspNetTimer
{
    private static readonly Timer _timer = new Timer(OnTimerElapsed);
    private static readonly JobHost _jobHost = new JobHost();

    public static void Start()
    {
        _timer.Change(TimeSpan.Zero, TimeSpan.FromMilliseconds(1000));
    }

    private static void OnTimerElapsed(object sender)
    {
        _jobHost.DoWork(() => { /* What is it that you do around here */ });
    }
}

Recommendation

This technique can make your background tasks within ASP.NET much more robust. There’s still a chance of problems occurring though. Sometimes, the AppDomain goes down in a more abrupt manner. For example, you might have a blue screen, someone might trip on the plug, or a hard-drive might fail. These catastrophic failures can take down your app in such a way that leaves data in a bad state. But hopefully, these situations occur much less frequently than an AppDomain shutdown.

Many of you might be scratching your head thinking it seems weird to use a web server to perform recurring background tasks. That’s not really what a web server is for. You’re absolutely right. My recommendation is to do one of the following instead:

  • Write a simple console app and schedule it using Windows task schedule.
  • Write a Windows Service to manage your recurring tasks.
  • Use an Azure worker or something similar.

Given that those are my recommendations, why am I still working on a system for scheduling recurring tasks within ASP.NET that handles web farms and AppDomain shutdowns I call WebBackgrounder (NuGet package coming later)?

I mean, besides the fact that I’m thick-headed? Well, for two reasons.

The first is to make development easier. When you get latest from our source code, I just want everything to work. I don’t want you to have to set up a scheduled task, or an Azure worker, or a Windows server on your development box. A development environment can tolerate the issues I described.

The second reason is for simplicity. If you’re ok with the limitations I mentioned, this approach has one less moving part to worry about when setting up a website. There’s no need to configure an external recurring task. It just works.

But mostly, it’s because I like to live life on the edge.

Technorati Tags: asp.net,appdomain,web farms,background,threads,tasks

personal, code comments edit

Today, October 15 2011, marks four years of being a Microsoft employee for me. As such, it’s time for a little introspection, but in many ways, Tim Heuer already introspected for me. Much of what he writes echoes my own experience, thus leaving me with less to write about. Smile

microsoft-way It’s the Microsoft way, or the highway. Which is conveniently located near Microsoft Way. - Photo by Todd Bishop, CC BY 2.0

Looking back in my archives, I realized I haven’t written a whole lot about what it’s like to work here. I do have a few posts such as…

Regarding the second post, the funny thing is you never stop drinking from the fire hose here. At least I haven’t yet. And that’s both a good thing, but it can be wearying at times. I’ve been taking a lot of mini-vacations lately to keep my sanity.

So far, the past four years have been a real blast.

I’ve had a passion for open source for a very long time. When I started, ASP.NET MVC 1.0 was just getting going as a proprietary project. Very few teams at that time released their source code, much less under a proper OSS license. Although it involved sitting in a lot of meetings with lawyers, reviewing lots of dry legal documents, I loved the opportunity to help drive the process to get ASP.NET MVC licensed under the Ms-PL, a liberal OSI certified open source license. Announcing that release was a happy day for me.

Since that time, we’ve shipped four RTM releases of ASP.NET MVC (recall that we released ASP.NET MVC 3 twice), each incorporating more and more third-party open source software, another milestone. As they say, shipping is a feature! And the ASP.NET team, and the MVC team in particular, are all really great people to work with. Hat tip to them all!

In this time, I’ve also had the great pleasure to work on NuGet from its inception. NuGet goes one step further in that it’s not only an open source project under the Apache v2 license, but it accepts contributions. Microsoft contributed NuGet to the Outercurve Foundation (an independent open source foundation not unlike the Apache and Eclipse foundation that recently received its non-profit status!) early in its life allowing it to flourish as an open source project.

Microsoft has a team of employees who are allowed to spend work-time contributing to the NuGet project. All development, issue tracking, and discussion occurs in a public location, the NuGet CodePlex site, with Mercurial (hg) as the source code repository.

The NuGet team is a dedicated group of folks and it’s really a joy to work with them. The community involvement and feedback has been tremendous. I used to tell folks that I wanted to work on open source as my day job. That wish came true. It’s a real joy.

The past four years have also had their fair share of challenges behind the scenes. When you work with the intensely smart folks that I have the pleasure to work with, it’s hard not to feel the effects of the Impostor Syndrome, as Hanselman writes.  And with everything I work on, I have a keen eye for all the shortcomings and faults in what we produce. I find it hard to tout our releases as much as I could because I always wish we could have done better. Perhaps because I’m a perfectionist, but more likely due to my half-Asian upbringing. I’m forced to find fault in everything.

Despite all that, I do take pride in the great work that the teams I work with have done. Their efforts have been tremendous and they deserve all the credit. I only hope my contributions were indeed contributions and not just overhead.

And I want to thank many of you, who’ve offered us encouragement and constructive criticism via Twitter, your blogs, my blog, our forums, StackOverflow, and so on. All of it is very much appreciated! Without your help, I don’t think I would have done as well in the past year. Don’t be surprised when I come knocking on your door asking for more help. Did I mention already that NuGet accepts contributions?

asp.net mvc, asp.net, code comments edit

A long while ago I wrote about the potential dangers of Cross-site Request Forgery attacks, also known as CSRF or XSRF. These exploits are a form of confused deputy attack.

police-academyScreen grab from The Police Academy movie.In that post, I covered how ASP.NET MVC includes a set of anti-forgery helpers to help mitigate such exploits. The helpers include an HTML helper meant to be called in the form that renders a hidden input, and an attribute applied to the controller action to protect. These helpers work great when in a typical HTML form post to an action method scenario.

But what if your HTML page posts JSON data to an action instead of posting a form? How do these helpers help in that case?

You can try to apply the ValidateAntiForgeryTokenAttribute attribute to an action method, but it will fail every time if you try to post JSON encoded data to the action method. On one hand, the most secure action possible is one that rejects every request. On the other hand, that’s a lousy user experience.

The problem lies in the fact that the under the hood, deep within the call stack, the attribute peeks into the Request.Form collection to grab the anti-forgery token. But when you post JSON encoded data, there is no form collection to speak of. We hope to fix this at some point and with a more flexible set of anti-forgery helpers. But for the moment, we’re stuck with this.

This problem became evident to me after I wrote a proof-of-concept library to  ASP.NET MVC action methods from JavaScript in an easy manner. The JavaScript helpers I wrote post JSON to action methods in order to call the actions. So I set out to fix this in my CodeHaacks project.

There are two parts we need to tackle this problem. The first part is on the client-side where we need to generate and send the token to the server. To generate the token, I just use the existing @Html.AntiForgeryToken helper in the view. A little bit of jQuery code grabs the value of that token.

var token = $('input[name=""__RequestVerificationToken""]').val();

That’s easy. Now that I have the value, I just need a way to post it to the server. I choose to add it to the request headers. In vanilla jQuery (mmmm, vanilla), that looks similar to:

var headers = {};
// other headers omitted
headers['__RequestVerificationToken'] = token;

$.ajax({
  cache: false,
  dataType: 'json',
  type: 'POST',
  headers: headers,
  data: window.JSON.stringify(obj),
  contentType: 'application/json; charset=utf-8',
  url: '/some-url'
});

Ok, so far so good. This will generate the token in the browser and send it to the server, but we have a problem here. As I mentioned earlier, the existing attribute which validates the token on the server won’t look in the header. It only looks in the form collection. Uh oh! It’s Haacking time! I’ll write a custom attribute called ValidateJsonAntiForgeryTokenAttribute.

This attribute will call into the underlying anti-forgery code, but we need to get around that form collection issue I mentioned earlier.

Peeking into Reflector, I looked at the implementation of the regular attribute and followed its call stack. It took me deep into the bowels of the System.Web.WebPages.dll assembly, which contains a method with the following signature that does the actual work to validate the token:

public void Validate(HttpContextBase context, string salt);

Score! The method takes in an instance of type HttpContextBase, which is an abstract base class. That means we can can intercept that call and provide our own instance of HttpContextBase to validate the anti-forgery token. Yes, I provide a forgery of the request to enable the anti-forgery helper to work. Ironic, eh?

Here’s the custom implementation of the HttpContextBase class. I wrote it as a private inner class to the attribute.

private class JsonAntiForgeryHttpContextWrapper : HttpContextWrapper {
  readonly HttpRequestBase _request;
  public JsonAntiForgeryHttpContextWrapper(HttpContext httpContext)
    : base(httpContext) {
    _request = new JsonAntiForgeryHttpRequestWrapper(httpContext.Request);
  }

  public override HttpRequestBase Request {
    get {
      return _request;
    }
  }
}

private class JsonAntiForgeryHttpRequestWrapper : HttpRequestWrapper {
  readonly NameValueCollection _form;

  public JsonAntiForgeryHttpRequestWrapper(HttpRequest request)
    : base(request) {
    _form = new NameValueCollection(request.Form);
    if (request.Headers["__RequestVerificationToken"] != null) {
      _form["__RequestVerificationToken"] 
        = request.Headers["__RequestVerificationToken"];
    }
}

  public override NameValueCollection Form {
    get {
      return _form;
    }
  }
}

In general, you can get into all sorts of trouble when you hack around with the http context. But in this case, I’ve implemented a wrapper for a tightly constrained scenario that defers to default implementation for most things. The only thing I override is the request form. As you can see, I copy the form into a new NameValueCollection instance and if there is a request verification token in the header, I copy that value in the form too. I then use this modified collection as the Form collection.

Simple, but effective.

The custom attribute follows the basic implementation pattern of the regular attribute, but uses these new wrappers.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, 
    AllowMultiple = false, Inherited = true)]
public class ValidateJsonAntiForgeryTokenAttribute : 
    FilterAttribute, IAuthorizationFilter {
  public void OnAuthorization(AuthorizationContext filterContext) {
    if (filterContext == null) {
      throw new ArgumentNullException("filterContext");
    }

    var httpContext = new JsonAntiForgeryHttpContextWrapper(HttpContext.Current);
    AntiForgery.Validate(httpContext, Salt ?? string.Empty);
  }

  public string Salt {
    get;
    set;
  }
  
  // The private context classes go here
}

With that in place, I can now decorate action methods with this new attribute and it will work in both scenarios, whether I post a form or post JSON data. I updated the client script library for calling action methods to accept a second parameter, includeAntiForgeryToken, which causes it to add the anti-forgery token to the headers.

As always, the source code is up on Github with a sample application that demonstrates usage of this technique and the assembly is in NuGet with the package id “MvcHaack.Ajax”.

asp.net, asp.net mvc, code comments edit

redirect Go that way instead - Photo by JacobEnos CC some rights reserved

Update: It looks like ASP.NET 4.5 adds the ability to suppress forms authentication redirect now with the HttpResponse.SuppressFormsAuthenticationRedirect property.

In an ASP.NET web application, it’s very common to write some jQuery code that makes an HTTP request to some URL (a lightweight service) in order to retrieve some data. That URL might be handled by an ASP.NET MVC controller action, a Web API operation, or even an ASP.NET Web Page or Web Form. If it can return curly brackets, it can be respond to a JavaScript request for JSON.

One pain point when hosting lightweight HTTP services on ASP.NET is making a request to a URL that requires authentication. Let’s look at a snippet of jQuery to illustrate what I mean. The following code makes a request to /admin/secret/data. Let’s assume that URL points to an ASP.NET MVC action with the AuthorizeAttribute applied, which requires that the request must be authenticated.

$.ajax({
    url: '/admin/secret/data',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    statusCode: {
        200: function (data) {
            alert('200: Authenticated');
            // Bind the JSON data to the UI
        },
        401: function (data) {
            alert('401: Unauthenticated');
            // Handle the 401 error here.
        }
    }
});

If the user is not logged in when this code executes, you would expect that the 401 status code function would get called. But if forms authentication (often called FormsAuth for short) is configured, that isn’t what actually happens. Instead, you get a 200  with the contents of the login page (or a 404 if you don’t have a login page). What gives?

If you crack open Fiddler, it’s easy to see the problem. Instead of the request returning an HTTP 401 Unauthorized status code, it instead returns a 302 pointing to a login page. This causes jQuery (well actually, the XmlHttpRequest object) to automatically follow the redirect and issue another request to the login page. The login page handles this new request and return its contents with a 200 status code. This is not the desired result as the code expects JSON data to be returned in response to a 200 code, not HTML for the login page.

This “helpful” behavior when requesting a URL that requires authentication is a consequence of having the FormsAuthenticationModule enabled, which is the default in most ASP.NET applications. Under the hood, the FormsAuthenticationModule hooks into the request pipeline and changes any request that returns a 401 status code into a redirect to the login page.

Possible Solutions

I’m going to cover a few possible solutions I’ve seen around the web and then present the one that I prefer. It’s not that these other solutions are wrong, but they are only correct in some cases.

Remove Forms Authentication

If you don’t need FormsAuth, one simple solution is to remove the forms authentication module as this post suggests. This is a great solution if you’re sole purpose is to use ASP.NET to host a Web API service and you don’t need forms authentication. But it’s not a great solution if your app is both a web application and a web service.

Register an HttpModule to convert Redirects to 401

This blog post suggests registering an HTTP Module that converts any 302 request to a

  1. There are two problems with this approach. The first is that it breaks the case where the redirect is legitimate and not the result of FormsAuth. The second is that it requires manual configuration of an HttpModule.

Install-Package MembershipService.Mvc

My colleague, Steve Sanderson, has an even better approach with his MembershipService.Mvc and MembershipService.WebForms NuGet packages. These packages expose ASP.NET Membership as a service that you can call from multiple devices.

For example, if you want your Windows Phone application to use an ASP.NET website’s membership system to authenticate users of the application, you’d use his package. He provides the MembershipClient.WP7 and MembershipClient.JavaScript packages for writing clients that call into these services.

These packages deserve a blog post in their own right, but I’m going to just focus on the DoNotRedirectLoginModule he wrote. His module takes a similar approach to the previous one I mentioned, but he checks for a special value in HttpContext.Items, a dictionary for storing data related to the current request, before reverting a redirect back to a 401.

To prevent a FormsAuth redirect, an action method (or ASP.NET page or Web API operation) would simply call the helpful method DoNotRedirectToLoginModule.ApplyForRequest. This sets the special token in HttpContext.Items and the module will rewrite a 302 that’s redirecting to the login page back to a 401.

My Solution

Steve’s solution is a very good one. But I’m particularly lazy and didn’t want to have to call that method on every action when I’m writing an Ajax heavy application. So what I did was write a module that hooks in two events of the request.

The first event, PostReleaseRequestState, occurs after authentication, but before the FormsAuthenticationModule converts the status to a 302. In the event handler for this event, I check to see if the request is an Ajax request by checking that the X-Requested-With request header is “XMLHttpRequest”.

If so, I store away a token in the HttpContext.Items like Steve does. Then in the EndRequest event handler, I check for that token, just like Steve does. Inspired by Steve’s approach, I added a method to allow explicitly opting into this behavior, SuppressAuthenticationRedirect.

Here’s the code for this module. Warning: Consider this “proof-of-concept” code. I haven’t tested this thoroughly in a wide range of environments.

public class SuppressFormsAuthenticationRedirectModule : IHttpModule {
  private static readonly object SuppressAuthenticationKey = new Object();

  public static void SuppressAuthenticationRedirect(HttpContext context) {
    context.Items[SuppressAuthenticationKey] = true;
  }

  public static void SuppressAuthenticationRedirect(HttpContextBase context) {
    context.Items[SuppressAuthenticationKey] = true;
  }

  public void Init(HttpApplication context) {
    context.PostReleaseRequestState += OnPostReleaseRequestState;
    context.EndRequest += OnEndRequest;
  }

  private void OnPostReleaseRequestState(object source, EventArgs args) {
    var context = (HttpApplication)source;
    var response = context.Response;
    var request = context.Request;

    if (response.StatusCode == 401 && request.Headers["X-Requested-With"] == 
      "XMLHttpRequest") {
      SuppressAuthenticationRedirect(context.Context);
    }
  }

  private void OnEndRequest(object source, EventArgs args) {
    var context = (HttpApplication)source;
    var response = context.Response;

    if (context.Context.Items.Contains(SuppressAuthenticationKey)) {
      response.TrySkipIisCustomErrors = true;
      response.ClearContent();
      response.StatusCode = 401;
      response.RedirectLocation = null;
    }
  }

  public void Dispose() {
  }

  public static void Register() {
    DynamicModuleUtility.RegisterModule(
      typeof(SuppressFormsAuthenticationRedirectModule));
  }
}

There’s a package for that

Warning: The following is proof-of-concept code I’ve written. I haven’t tested it thoroughly in a production environment and I don’t provide any warranties or promises that it works and won’t kill your favorite pet. You’ve been warmed.

Naturally, I’ve written a NuGet package for this. Simply install the package and all Ajax requests that set that header (if you’re using jQuery, you’re all set) will not be redirected in the case of a 401.

Install-Package AspNetHaack

Note that the package adds a source code file in App_Start that wires up the http module that suppresses redirect. If you want to turn off this behavior temporarily, you can comment out that file and you’ll be back to the old behavior.

The source code for this is in Github as part of my broader CodeHaacks project.

Why don’t you just fix the FormsAuthenticationModule?

We realize this is a deficiency with the forms authentication module and we’re looking into hopefully fixing this for the next version of the Framework.

Update: As I stated at the beginning, a new property added in ASP.NET 4.5 supports doing this.

Tags: asp.net, aspnetmvc, formsauth, membership

asp.net mvc, asp.net, nuget comments edit

NOTE: This blog post covers features in a pre-release product, ASP.NET MVC 4 Developer Preview. You’ll see we call out those two words a lot to cover our butt. The specifics about the feature will change  and this post will become out-dated. You’ve been warned.

recipe All good recipes call for a significant amount of garlic.

Introduction

Last week I spoke at the //BUILD conference on building mobile web applications with ASP.NET MVC 4. In the talk, I demonstrated a recipe I wrote that automates the process to create mobile versions of desktop views.

view-mobilizer-recipe

Recipes are a great way to show off your lack of UI design skills like me!

In this blog post, I’ll walk through the basic steps to write a recipe. But first, what exactly is a recipe?

Obviously I’m not talking about the steps it takes to make a meatloaf surprise. In the roadmap, I described a recipe as:

An ASP.NET MVC 4 recipe is a dialog box delivered via NuGet with associated user interface (UI) and code used to automate a specific task.

If you’re familiar with NuGet, you know that a NuGet package can add new Powershell commands to the Package Manager Console. You can think of a recipe as a GUI equivalent to the commands that a package can add.

It fits so well with NuGet that we plan to add recipes as a feature of NuGet (probably with a different name if we can think of a better one) so that it’s not limited to ASP.NET MVC. We did the same thing with pre-installed NuGet packages for project templates which started off as a feature of ASP.NET MVC too. This will allow developers to write recipes for other project types such as Web Forms, Windows Phone, and later on, Windows 8 applications.

Getting Started

Recipes are assemblies that are dynamically loaded into Visual Studio by the Managed Extensibility Framework, otherwise known as MEF. MEF provides a plugin model for applications and is one of the primary ways to extend Visual Studio.

The first step is to create a class library project which compiles our recipe assembly. The set of steps we’ll follow to write a recipe are:

  1. Create a class library
  2. Reference the assembly that contains the recipe framework types. At this time, the assembly is Microsoft.VisualStudio.Web.Mvc.Extensibility.1.0.dllbut this may change in the future.
  3. Write a class that implements the IRecipe interface or one of the interfaces that derive from IRecipe such as IFolderRecipe or IFileRecipe. These interfaces are in the Microsoft.VisualStudio.Web.Mvc.Extensibility.Recipes namespace. The Developer Preview only supports the IFolderRecipe interface today. These are recipes that are launched from the context of a folder. In a later preview, we’ll implement IFileRecipe which can be launched in the context of a file.
  4. Implement the logic to show your recipe’s dialog. This could be a Windows Forms dialog or a Windows Presentation Foundation (WPF) dialog.
  5. Add the MEF ExportAttribute to the class to export the IRecipe interface.
  6. Package up the whole thing in a NuGet package and make sure the assembly ends up in the recipes folder of the package, rather than the usual lib folder.

The preceding list of steps itself looks a lot like a recipe, doesn’t it? It might be natural to expect that I wrote a recipe to automate those steps. Sorry, no. But what I did do to make it easier to build a recipe was write a NuGet package.

Why didn’t I write a recipe to write a recipe (inception!)? Recipes add a command intended to be run more than once during the life of a project. But that’s not the case here as setting up the project as a recipe is a one-time operation. In this particular case, a NuGet package is sufficient because it doesn’t make sense to convert a class library project into a recipe over and over gain.

That’s the logic I use to determine whether I should write a recipe as opposed to a regular NuGet package. If it’s something you’ll do multiple times in a project, it may be a candidate for a recipe.

A package to create a recipe

To help folks get started building recipes, I wrote a NuGet package, AspNetMvc4.RecipeSdk. And as I did in my //BUILD session, I’m publishing this live right now! Install this into an empty Class Library project to set up everything you need to write your first recipe.

The following screenshot shows an example of a class library project after installing the recipe SDK package.

recipe-class-lib

Notice that it adds a reference to the Microsoft.VisualStudio.Web.Mvc.Extensibility.1.0.dll assembly and adds a MyRecipe.cs file and a MyRecipe.nuspec file. It also added a reference to System.Windows.Forms.

Feel free to rename the files it added appropriately. Be sure to edit the MyRecipe.nuspec file with metadata appropriate to your project.

The interesting stuff happens within MyRecipe.cs. The following shows the default implementation added by the package.

using System;
using System.ComponentModel.Composition;
using System.Drawing;
using Microsoft.VisualStudio.Web.Mvc.Extensibility;
using Microsoft.VisualStudio.Web.Mvc.Extensibility.Recipes;

namespace CoolRecipe {
    [Export(typeof(IRecipe))]
    public class MyRecipe : IFolderRecipe {
        public bool Execute(ProjectFolder folder) {
            throw new System.NotImplementedException();
        }

        public bool IsValidTarget(ProjectFolder folder) {
            throw new System.NotImplementedException();
        }

        public string Description {
            get { throw new NotImplementedException(); }
        }

        public Icon Icon {
            get { throw new NotImplementedException(); }
        }

        public string Name {
            get { throw new NotImplementedException(); }
        }
    }
}

Most of these properties are self explanatory. They provide metadata for a recipe that shows up when a user launches the Add recipe dialog.

The two most interesting methods are IsValidTarget and Execute. The first method determines whether the folder that the recipe is launched from is valid for that recipe. This allows you to filter recipes. For example, suppose your recipe only makes sense when launched from a view folder. You can implement that method like so:

public bool IsValidTarget(ProjectFolder folder) {
    return folder.IsMvcViewsFolderOrDescendent();
}

The IsMvcViewsFolderOrDescendant is an extension method on the ProjectFolder type in the Microsoft.VisualStudio.Web.Mvc.Extensibility namespace.

The general approach we took was to keep the ProjectFolder interface generic and then add extension methods to layer on behavior specific to ASP.NET MVC. This provides a nice simple façade to the Visual Studio Design Time Environment (or DTE). If you’ve ever tried to write code against the DTE, you’ll appreciate this.

In this particular case, I recommend that you make the method always return true for now so your recipe shows up for any folder.

The other important method to implement is Execute. This is where the meat of your recipe lives. The basic pattern here is to create a Windows Form (or WPF Form) to display to the user. That form might contain all the interactions that a user needs, or it might gather data from the user and then perform an action. Here’s the code I used in my MVC 4 Mobilizer recipe.

public bool Execute(ProjectFolder folder) {
    var model = new ViewMobilizerModel(folder);
    var form = new ViewMobilizerForm(model);

    var result = form.ShowDialog();
    if (result == DialogResult.OK) {
        // DO STUFF with info gathered from the form
    }
    return true;
}

I create a form, show it as a dialog, and when it returns, I do stuff with the information gathered from the form. It’s a pretty simple pattern.

Packaging it up

Packaging this up as a NuGet package is very simple. I used NuGet.exe to run the following command:

nuget pack MyRecipe.nuspec

If it were any easier, it’d be illegal! I can now run the nuget push command to upload the recipe package to NuGet.org and make it available to the world. In fact, I did just that live during my presentation at BUILD.

Using a recipe

To install the recipe, right click on the solution node in Solution Explorer and select Manage NuGet Packages.

Find the package and click the Install button. This installs the NuGet package with the recipe into the solution.

To run the recipe, right click on a folder and select Add > Run Recipe. run-recipe-menu

Right now you’re probably thinking that’s an odd menu option to launch a recipe. And now you’re thinking, wow, did I just read your mind? Yes, we agree that this is an odd menu option. Did I mention this was a Developer Preview? We plan to change how recipes are launched. In fact, we plan to change a lot between now and the next preview. At the moment, we think moving recipes to a top level menu makes more sense.

The Run Recipe menu option displays the recipe dialog with a list of installed recipes that are applicable in the current context.

run-recipe-dialog

As you can see, I only have one recipe in my solution. Note that a recipe can control its own icon.

Select the recipe and click the OK button to launch it. This then calls the recipe’s Execute method which displays the UI you implemented.

Get the source!

Oh, and before I forget, the source code for the Mobilizer recipe is available on Github as part of my Code Haacks project!

asp.net, asp.net mvc comments edit

Today, during his //BUILD keynote, Scott Guthrie announced the availability of ASP.NET MVC 4 Developer preview. Note those words, developer preview. This is not even a Beta release. But there sure is a lot of cool stuff inside.

One great thing about this release is that the runtime libraries (our assemblies) as well as our JavaScript libraries are available as NuGet packages. So if you write packages that depend on the ASP.NET MVC 4 runtime, you can have them depend on our packages.

Also included in this release is NuGet 1.5 which was released just recently. If you already have NuGet 1.5 installed, you may notice there’s a new update available.  This new version includes support for Visual Studio 11 Developer Preview. There are no other changes in it.

I’m also giving a couple of talks at BUILD that you’ll be able to watch online that cover some of the features within ASP.NET MVC 4. To find out more about the release, visit our ASP.NET MVC 4 information page.

Install it

You can install it via the Web Platform installer:

Or if you prefer to download the installers directly, visit the download details page.

We also published an ASP.NET MVC 3 installer for Visual Studio 11 Developer Preview if you’d like to try that out.

Closing Thoughts

I’m excited about this release and will be interested to hear your feedback. I also want to recognize the heroic efforts of the ASP.NET MVC team (and NuGet and ASP.NET Web Pages) to get this release ready in time with all the features that it contains. I’m privileged to work with such great folks. Smile

Tags: aspnetmvc, asp.net, preview, nuget

asp.net, asp.net mvc comments edit

BUILD-speaker-blingIf you’re at the BUILD conference in Anaheim, I’ll be speaking in two sessions on Thursday.

Progressively enable the mobile web with ASP.NET MVC 4, HTML5, and jQuery Mobile Thursday, 9:00 AM

There are over a billion mobile devices with rich Web capabilities, yet many Websites look terrible on such devices, or worse, fail to work at all. As mobile devices become the primary way that most people access the Web, having a site that fails to deliver a rich experience on the Web using HTML5, JavaScript and jQuery Mobile is missing out on a huge opportunity. In this session, learn how ASP.NET MVC 4 leverages these next generation technologies enabling developers to build a single solution that targets multiple platforms and form factors such as mobile, tablet, and desktop devices.

UPDATE: Unfortunately, we had to cancel the second talk due to a family illness which required that Damian go home early. Damian and I plan to record the session later and post it on Channel 9.The second talk is a joint talk with Damian Edwards

Building IIS and ASP.NET apps with the power of asyncThursday, 2:30 PM

It’s well established from both theory and practice that Web sites and Web services achieve scale through asynchrony. If a dedicated thread is required per client connection to a server, scalability becomes limited by the number of threads the server system can support, which is typically far fewer than business requirements demand. Unfortunately, it’s also been difficult historically for developers to write asynchronous apps, due to the myriad of callbacks that have been necessary to program asynchrony successfully. Thus, businesses scale by investing in many more machines rather than by making better use of the ones they already have or the few they’re paying for use of in the cloud. All that changes with the next release of Visual Studio and .NET. New features in managed languages make writing asynchronous code as simple as writing synchronous code, thereby enabling both developer productivity and good return on investments. In this code-heavy session, learn how you can be the hero of your organization, building efficient and scalable server apps that best utilize your company’s resources.

If you’re here, I hope you can make it. I’ll be giving out NuGet stickers at my sessions. Smile

personal comments edit

I had a dry run today for an upcoming presentation that did not go quite as well as I would like, though I completely expected this as I was unprepared. The good news is, it was a dry run and not the real thing, so I have plenty of time to adjust.

Even so, there’s one thing I did wrong, that I should have known better than to do. In my crazy sleep deprived work frazzled mind, I broke the cardinal rule of a dry run – Treat it like the real thing!

flight Kitty Hawk by gilderm from sxc.huFor example, I have a little pre-flight checklist for every talk I give. I just place it in a file named preflight.txt in the root of each presentation folder and adapt it for each presentation. Even though I try to adapt it to each presentation, there is a core set of items that never really changes from one presentation to another. These are items that almost always apply and many are tips learned from other great presenters such as Scott Hanselman and Brad Wilson.

I thought this might be useful for others who find themselves in a position where they are giving presentations. Perhaps some of you will add to my checklist. I divided it into several categories. The last section isn’t actually a check-list, but a reminder of important keyboard shortcuts.

System

  • Set Notepad default font size to 16
  • Hide Desktop Icons
  • Close unnecessary toolbar/tray icons
  • Close all unecessary windows including Solution Explorer (use CTRL ALT L to show it)

Visual Studio

  • Launch Visual Studio
  • Set font size to 16
  • Drag necessary files into desktop
  • Start and minimize magnifier
  • Prepare snippets (if you use them)
  • Disable all unnecessary VS extensions
  • Or better yet, set up a DEMO instance of Visual Studio (thanks Mike Minutillo!)

General

  • Reset all demos. That might mean clearing cookies, clearing browser forms saved data, etc.
  • Open the PowerPoint deck to the right spot
  • Consolidate your demo scripts into a single document per talk
  • Print out notes (and don’t accidentally throw them away like I did)
  • Relax

Important Keyboard shortcuts

  • Window + to zoom in one level (and start magnifier)
  • Windows - to zoom out one level
  • Windows ESC to zoom fully out
  • CTRL . smart tag expansion
  • CTRL , Navigate to
  • SHIFT ALT K to display Solution Explorer (I remapped this on Brad’s advice because CTRL ALT L conflicts with Windows magnifier)
  • CTRL + and CTRL - change font size in NotePad2

I think this checklist nicely complements my presentation tips I learned from my (many) mistakes blog post. Did I forget an obvious preflight option? Do tell!

nuget, code comments edit

UPDATE: We found an issue with 1.5 when running behind some proxies that caused an “Arithmetic operation resulted in an overflow” exception message and another issue with signed PS1 scripts. We’ve now posted an update (NuGet 1.5.20902.9023) that fixes the issues.

I’m happy to announce the release of NuGet 1.5 just in time to make sure our roadmap isn’t a liar. I won’t bore you by repeating the details of the release, but instead direct you to the NuGet 1.5 release notes.

If you are running a private NuGet.Server repository, you’ll need to update that repository the latest version of NuGet.Server to connect to it using NuGet 1.5.

I’ve updated our roadmap to reflect what we’re thinking about next. The next release is going to focus more on continuous integration scenarios that we’ve heard from customers, pre-release “beta” packages and multiple UI improvements such as allowing folks to disable package sources.

Also, on occasion, the NuGet feature team hangs out in a home-grown IRC style web based chat application written by David Fowler in his spare time as a test app for SignalR. We’re contemplating the idea of making it a more regular thing if possible.

Tags: nuget, oss, open source, package manager

asp.net, asp.net mvc, code comments edit

In a recent blog post, I wrote a a controller inspector to demonstrate Controller and Action Descriptors. In this blog post, I apply that knowledge to build something more useful.

One pain point when you write Ajax heavy applications using ASP.NET MVC is managing the URLs that Routing generates on the server. These URLs aren’t accessible from code in a static JavaScript file.

There are techniques to mitigate this:

  1. Generate the URLs in the view and pass them into the JavaScript API. This approach has the drawback that it isn’t unobtrusive and requires some script in the view.
  2. If you prefer the unobtrusive approach, embed the URLs in the HTML in a logical and semantic manner and the script can read them from the DOM.

Both approaches get the job done, but they start to break down when you have a list. For example, suppose I have a page that lists comic books retrieved from the server, each with a link to edit the comic book. Do I then need to generate a URL for each comic on the server and pass it into the script?

That’s not necessarily a bad idea. After all, isn’t that how Hypertext is supposed to work? When you render a set of resources, shouldn’t the response include a navigation URL for each resource?

On the other hand, you might prefer your services to return just comic books and infer the URLs by convention.

How does MvcHaack.Ajax help?

Thinking about this problem led me to build up a quick proof-of-concept prototype based on something David Fowler showed me a long time ago.

The library provides a base controller class, I tentatively named JsonController (I could extend it to support other formats, but I wanted to keep this prototype focused on one common scenario). This class sets up a custom action invoker which does a lot of the work.

With this library in place, a <script> reference pointing to the controller itself generates a jQuery based JavaScript API with methods for calling controller actions.

This API enables passing JSON objects from the client to the server, taking advantage of ASP.NET MVC’s argument model binding.

Perhaps an illustration is in order.

Lets see some codez!

The first step is to write a controller. I’ll start simple and step it up a notch later.

The controller has a single action method that returns an enumeration of anonymous objects. Since I’m inheriting from JsonController, I don’t need to specify an action result return type. I could have returned real objects too, but for the sake of simplicity, I wanted to start here.

public class ComicsController : JsonController {
  public IEnumerable List() {
    return new[] {
      new {Id = 1, Title = "Groo"},
      new {Id = 1, Title = "Batman"},
      new {Id = 1, Title = "Spiderman"}
    };
  }
}

The next step is to make sure I have a route to the controller, and not to the controller’s action. The special invoker I wrote handles action method selection. This prototype lets you use a regular route, but the JsonRoute ensures correctness.

public static void RegisterRoutes(RouteCollection routes) {
  // ... other routes
  routes.Add(new JsonRoute("json/{controller}"));
  // ... other routes ...
}

As a reminder, this second step with the JsonRoute is not required!

With this in place, I can add a script reference to the controller from an HTML page and call methods on it from JavaScript. Let’s do that and display each comic book.

First, I’ll write the HTML markup.

<script src="/json/comics?json"></script>
<script src="/scripts/comicsdemo.js"></script>
<ul id="comics"></ul>

The first script tag references an interesting URL,/json/comics?json. That URL points to the controller (not an action of the controller), but passes in a query string value. This value indicates that the controller descriptor should short circuit the request and generate a JavaScript with methods to call each action of the controller using the same technique I wrote about before.

Here’s an example of the generated script. It’s very short. In fact, most of it is pretty statick. The generated part is the array of actions passed to the $.each block and the URL.

if (typeof $mvc === 'undefined') {
    $mvc = {};
}
$mvc.Comics = [];
$.each(["List","Create","Edit","Delete"], function(action) {
    var action = this;
    $mvc.Comics[this] = function(obj) {
        return $.ajax({
            cache: false,
            dataType: 'json',
            type: 'POST',
            headers: {'x-mvc-action': action},
            data: JSON.stringify(obj),
            contentType: 'application/json; charset=utf-8',
            url: '/json/comics?invoke&action=' + action
        });
    };
});

For those of you big into REST, you’re probably groaning right now with the RPC-ness of this API. It wouldn’t be hard to extend this prototype to take a more RESTful approach. For now, I stuck with this because it more closely matches the conceptual model for ASP.NET MVC out of the box.

Reference the script, and I can now call action methods on the controller from JavaScript. For example, in the following code listing, I call the List action of the ComicsController and append the results to an unordered list. Since I didn’t need to mix client and server code to write this script, I can place it in a static script file, comicsdemo.js.

$(function() {
    $mvc.Comics.List().success(function(data) {
        $.each(data, function() {
            $('#comics').append('<li>' + this.Title + '</li>');
        });

    });
});

One more thing

It’s easy to call a parameter-less action method, but what about an action that takes in a type? Not a problem. To demonstrate, I’ll create a type on the server first.

public class ComicBook {
    public int Id { get; set; }
    public string Title { get; set; }
    public int Issue { get; set; }
}

Great! Now let’s add an action method that accepts a ComicBook as an action method parameter. For demonstration purposes, the method just returns the comic along with a message. The invoker serializes the return value to JSON for you. There is no need to wrap the return value in a JsonResult. The invoker handles that for us.

public object Save(ComicBook book) {
    return new { message = "Saved!", comic = book };
}

I can now call that action method from JavaScript and pass in a a comic book. I just need to pass in an anonymous JavaScript object with the same shape as a ComicBook. For example:

$mvc.Comics.Save({ Title: 'Adventurers', Issue: 123 })
  .success(function(data) {
      alert(data.message + ' Comic: ' + data.comic.Title);
  });

The code results in the alert pop up. This proves I posted a comic book to the server from JavaScript.

Message from webpage
(2)

Get the codez!

Ok, enough talk! If you want to try this out, I have a live demo here. One of the demos shows how this can nicely fit in with KnockoutJS.

If you want to try the code yourself, it’s available in NuGet under the ID MvcHaack.Ajax.

The source code is up at Github. Take a look and let me know what you think. Should we put something like this in ASP.NET MVC 4?

asp.net mvc, asp.net, code comments edit

EDITOR’S NOTE:Microsoft has an amazing intern program. For a summer, these bright college students work with a feature crew getting real work done, all the while attending cool events nearly every week that, frankly, make the rest of us jealous! Just look at some of the perks listed in this news article!

This summer, the ASP.NET MVC is hosting an intern, Stephen Halter, who while very smart, doesn’t have a blog of his own (booo! hiss!). Being the nice guy that I am (and also being amenable to bribes), I’m letting him guest author a post on my blog (first guest post ever!) to talk about the cool project he’s been doing.

Editor Update:A lot of folks are wondering why we built our own grid. The plan is to build this on top of the jQuery UI Grid when it’s complete. It’s not done yet so we built a scaled down implementation to allow us to test out the interactions with ASP.NET MVC controllers and make sure everything is in place. It’s mostly T4 files that extends our existing Add Controller Scaffolding feature. You can tweak the T4 to build any kind of grid you want.

Hello everyone – my name is Stephen Halter, and I am a summer intern on the ASP.NET MVC team who is excited to show you the new Ajax grid scaffolder that I have been working on for ASP.NET MVC 4. Phil has graciously allowed me to use his blog to get the word out about my project.

We want to get some feedback before releasing the scaffolder as part of the MVC Framework, and we figured what better way to get feedback than to release a preview of the scaffolder as a NuGet package?

To install the package, search for “AjaxGridScaffolder” in the NuGet Package Manager dialog or just enter the following command

PM> Install-Package AjaxGridScaffolder

in the Package Manager Console to try it out.

The NuGet package, once installed, registers itself to the Add Controller dialog as a ScaffolderProvider named “Ajax Grid Controller.” When run, the scaffolder generates a controller and corresponding views for an Ajax grid representation of the selected model and data context class.

The Ajax grid controller scaffolder has many similarities to the current “Controller with read/write actions and views, using Entity Framework”, but it provides pagination, reordering and inline editing of the content using Ajax.

Add > Controller menu
selection

Template Selection - Ajax Grid
Controller

Currently, the Ajax Grid Scaffolder only generates C# code, but both Razor and ASPX views are supported. We’ll add VB.NET support later. If you selected “None” from the Views drop down in the Add Controller dialog, only the controller will be generated.

The generated controller has 8 actions. There is Index, Create (POST/GET), Edit (POST/GET), Delete (POST), GridData, and RowData. Most of these actions probably sound familiar, but there are a few that might not be obvious. The GET versions of Create and Edit provide editing widgets to the client using HtmlHelper.EditorFor or HtmlHelper.DropDownList if the property is a foreign key. The GridData action renders a partial view of a range of rows while RowData renders a partial view a specific row given its primary key. These *Data actions aren’t very verby (editor’s note: “verby?” Seriously?) and improved naming suggestions are welcome.

Solution explorer view of the project
structure

The scaffolder also provides three views: Index, GridData, and Edit. The Index view includes JavaScript and small amount of CSS required to make the Ajax grid usable. Due to all the possible ways a master or layout page can be done, it isn’t possible to ensure that JavaScript and CSS will be included in the <head> element of the document. However, we are looking at possible fixes for the MVC 4 release.

clip_image005

The GridData and Edit views are partial views that are rendered when retrieving non-editable and editable rows respectively via XMLHttpRequest instances (XHRs) using jQuery. Sending HTML snippets in response to XHRs (as opposed to JSON for example) makes using DisplayFor, EditorFor and ValidationFor more natural and progressive enhancement simpler.

With or without JavaScript, the Index view provides pagination and reordering by column. With JavaScript enabled, rows can be created/edited/deleted all inside the grid without ever leaving the index view.

Tell us what your thoughts are on the Ajax Grid Scaffolder. Is it important to you that we support editing without JavaScript? Do you want the back button to take you to your previous view of the grid? Do you have any suggestions on how to clean up the generated code? Did you encounter any bugs/issues? If so, we want to know.

Tags: aspnetmvc, asp.net, ajax, jquery, grid

code comments edit

This is an age old problem and one that’s probably been solved countless times before, but I’m going to write about it anyways.

Say you’re writing code like this:

<p>You have the following themes:</p>
<ul>
@foreach(var theme in Model) {
  <li>@theme.Id</li>
}
</ul>

The natural inclination for the lazy developer is to leave enough alone and stop there. It’s good enough, right? Right?

Sure, when the value of Model.Count is zero or larger than one. But when it is exactly one, the phrase is incorrect English as it should be singular “You have the following theme”.

I must fight my natural inclination here! On the NuGet team, we have a rallying cry intended to inspire us to strive for better, “Apple Polish!”. We tend to blurt it out at random in meetings. I’m thinking of purchasing each member of the team a WWSJD bracelet (What Would Steve Jobs Do?).

To handle this case, I wrote a simple extension method:

public static string CardinalityLabel(this int count, string singular,
    string plural)
{
    return count == 1 ? singular : plural;
}
    

Notice that I didn’t try automatic pluralization. That’s just a pain.

With this method, I can change the markup to say:

<p>You have the following 
  @Model.Count.CardinalityLabel("theme", "themes"):</p>

I’m still just not sure about the name of that method though. What should it be?

Do you have such a method? Or are you fine with the awkward phrasing once in a while?

humor, personal comments edit

Stumbling around the net, I ran into the “funny verticals” meme. These are typically a vertical strip of screenshots pulled from a movie or television with funny captions tacked on.

If you do an image search for “funny verticals”, you’ll see a whole slew of them. Be forewarned, there are some very crude and offensive ones.

For the lazy, here are a few representative ones I found to be funny. The first example is from the movie Inception:

blow-in-my-eyes

This is another one from Inception. There seems to be a lot using this specific sequence.

looking-for-asian-guy

And here’s one from the television show, LOST.

lost

On a lark, I thought it’d be funny to try and do a geek version of this meme. I chose two personalities in our community I figured would be very well known, Scott Hanselman and Scott Guthrie. This has absolutely nothing to do with Hanselman posting this photo on his blog because I’m not the vengeful type. Nosiree.

I’ll post my versions here as well as the raw image because I know you’ll do much better than me. I needed to keep it tame because I do enjoy my employer’s salary continuation plan.

job-search

Here’s another one using the same template.

Hawaii-Vertical

I tried changing this last one up a bit.

clone-vertical

It’s pretty challenging to do this with folks who are not television/movie celebrities because you have far fewer images to work from, so I did the best I could with what I could find.

If you think you can do a lot better, download the raw images and prove it! When you do, post a link in the comments so we can see it. Smile

asp.net mvc, asp.net comments edit

99.99999% of the time (yes, I measured it), a controller in ASP.NET MVC is a type, and an action is a method — with reflection as the glue that holds it all together. For most folks, that’s the best way to view how ASP.NET MVC works.

But some folks like to dig deeper and get their hands dirty a bit by taking a peek under the hood. Doing so reveals that while the reflection based mapping of controllers types and actions to methods is true by default, it can be easily changed to something else entirely.

ASP.NET MVC contains powerful abstractions for the controllers and actions via the ControllerDescriptor and ActionDescriptor classes. These abstractions make it possible to implement completely different underlying implementations of a controller and action. For example, one could implement a version of ASP.NET MVC on top of a dynamic language using the DLR such as the IronRuby ASP.NET MVC I wrote about a long time ago.

Using these abstractions, we can implement something useful like a Controller Inspector, a nice complement to the Route Debugger I wrote a while back.

Installing the Controller Inspector

Inspector-120x120The Controller Inspector is available as a NuGet package with the package id MvcHaack.ControllerInspector (my Paint.net skills are top notch!).

Install-Package MvcHaack.ControllerInspector

After installing the package, visit any URL in your application rendered by a controller action. For example, here’s a standard request for a boring action.

index-action

With the package installed and while running the site on localhost (it won’t work when the site is deployed), append the query string parameter ?inspect. For example, in my sample, I just visit: http://localhost:38249/?inspect and voila!

controller-inspector

I nicely formatted page that displays information about the controller and each of its actions. If you’re wondering, “hey, isn’t this like Glimpse!” please skip to the end of this blog post where I address that.

Here’s a look at an action method.

contorller-inspector-action-view

Notice that it conveniently shows the HTTP verbs next to the name to differentiate action methods of the same name. If an action method accepts a complex type as a parameter, the inspector displays details about that type (though not recursively yet).

action-with-model

Accessing controller metadata

The ControllerDescriptor class provides ways to get at metadata about the controller. The interesting members include:

  • ControllerName
  • ControllerType
  • GetCanonicalActions
  • GetCustomAttributes

The first two properties are self evident. The method GetCanonicalActions returns an enumeration of ActionDescriptor instances, each of which describes an action. GetCustomAttributes returns attributes applied to the controller. These are typically the filters applied to the controller itself.

In the case of the default controller descriptor, ReflectedControllerDescriptor, the filters returned by GetCustomAttributes are retrieved via reflection. But a custom descriptor could load those filters from elsewhere (as is the case with the IronRuby implementation).

The ActionDescriptor also has a few interesting properties.

  • ActionName
  • ControllerDescriptor
  • GetCustomAttributes
  • GetFilters
  • GetParameters
  • GetSelectors

Despite what you might expect, you can’t obtain everything you’d want to know from an ActionDescriptor. For example, if you’re interested in the return type of an action method, the ActionDescriptor won’t help? Why not? Well, it may be impossible to tell you that. For example, the type might not be known ahead of time because it requires the action method to be invoked first, as would be the case in a dynamically typed language.

So these abstractions were carefully designed not to assume too much about the underlying implementation of an action/controller.

But as we learned before, 99.99999% of the time we’re dealing with the default reflection based approach. So what the Controller Inspector does is to try and cast the ActionDescriptor to ReflectedActionDescriptor and if that succeeds, it can reflect over the action method normally to provide a lot more details.

Hooking itself up

To hook the code up that outputs all this information, I made use of David Ebbo’s WebActivator package. This allows me to run a bit of code at startup that replaces the current controller factory with an InspectorControllerFactory.

[assembly: PostApplicationStartMethod(typeof(AppStart), "Start")]
namespace MvcHaack.ControllerInspector {
  public static class AppStart {
    public static void Start() {
      var factory = ControllerBuilder.Current.GetControllerFactory();
      ControllerBuilder.Current.SetControllerFactory(
        new InspectorControllerFactory(factory));
      }
  }
}

The InspectorControllerFactory wraps the existing controller factory. All it does is call into the existing factory to create a controller, and if the request is a local request with the proper “inspect” query string parameter, it sets its invoker to be an InspectorActionInvoker. This way, for normal requests, there is pretty much no overhead.

public IController CreateController(RequestContext requestContext, 
    string controllerName) {
  var controller = _controllerFactory.CreateController(requestContext,
    controllerName);

  if (IsInspectorRequest(requestContext.HttpContext.Request)) {
    var normalController = controller as Controller;
    var invoker = normalController.ActionInvoker;
    normalController.ActionInvoker = new InspectorActionInvoker(invoker);
  }
  return controller;
}

private static bool IsInspectorRequest(HttpRequestBase httpRequest) {
  return httpRequest.IsLocal
    && httpRequest.QueryString.Keys.Count > 0
    && httpRequest.QueryString.GetValues(null).Contains("inspect");
}

What the InspectorActionInvoker does is build up a model of all the information we want to display and passes it to a precompiled Razor template using the approach I wrote about recently in Text Templating using Razor the easy way. I simply build up a huge anonymous class and pass it to a dynamic model in the template. Note that this probably won’t work in medium trust, but I can easily fix that later by either using an ExpandoObject or by using a strongly typed model. I was just being lazy as this is a proof of concept.

What about Glimpse?

As soon as I showed this to some co-workers they asked me why I was trying to re-implement Glimpse. If you haven’t heard of Glimpse, stop and go read this blog post. Glimpse is like a server-side Firebug for ASP.NET MVC applications. However, when I last checked, it didn’t have something exactly like this.

The point in writing this was to teach folks about the ControllerDescriptor and ActionDescriptor. I’ll make the code available later when I finish part three of this informal series and perhaps someone can help me turn this into a Glimpse plugin if that makes sense. In the meanwhile, I built the package with symbols so you can debug into it to see the source.

UPDATE: The code is available on Github!

In the third part, I blog about what originally lead me down this path to write about the descriptors, which in turn lead me down the path to write about the Razor Generator. Yes, I’m easily sidetracked!

As a reminder, to try it out, install the MvcHaack.ControllerInspector package then use the ?inspect query string parameter when viewing a page rendered by a controller.

asp.net, asp.net mvc, personal, tech, code comments edit

I hate code samples in technical books! No seriously, this is bile I’m not afraid to give a permalink to (nor am I afraid to end a sentence with a preposition, so there!).

Even the shortest code samples are a pain to type in. And if they show anything reasonably interesting, they’re probably too long to type in.

Of course, nobody actually types in the sample code, they grab the code from the companion CD (blech!) or download zip files containing the code from the companion website.

With Professional ASP.NET MVC 3 (print edition | kindle edition) we experimented with a different approach. We made our sample code available as NuGet packages.

It seemed fitting given that ASP.NET MVC 3 included NuGet 1.0 as part of the product. The benefit of this approach is that there’s no fiddling around with downloading and unpacking files and copying source files into the right place.

Throughout the book, you’ll run into a call-out with a command that says something like Install-Package Wrox.SomethingOrOther. If you’re following along with an ASP.NET MVC 3 project open in Visual Studio, it’s as easy as installing that package and you have the source code nicely organized and immediately runnable!

Along with the easily installable code samples, the book covers all the cool new features of ASP.NET MVC 3 including EF Code First Scaffolding, NuGet, and Razor.

For those that like to dig deeper, the book covers the concept of dependency injection and ASP.NET MVC 3’s support for it as well as Test Driven Development (TDD) with ASP.NET MVC. These chapters were written by Brad Wilson, who’s also a co-author of the xUnit.net unit test framework.

Along with Brad, I had the pleasure of also working with Jon Galloway and K. Scott Allen. This was a bit of a reunion for K. Scott, Jon, and I as we co-authored a book with Jeff Atwood (aka CodingHorror) a lifetime ago.

Since Brad and I are on the product team, we were able to sprinkle in behind-the-scene tidbits from the product team that provide insight into how or why certain decisions were made when it came to the product design.

If you read the book (again, available in both a print edition and a kindle edition. Don’t be shy about collecting them all! Winking
smile), please do write a review on Amazon.com. We appreciate all the feedback we can get and already have ideas on how to improve the next one!

Also, a lot of folks have asked me why the Kindle is priced more than the paperback in some areas. We’re not really in control of that. The suggested retail price of the two editions are exactly the same, but Amazon provides different discounts for each edition.

As to the question, why are the suggested retail prices the same? I really don’t know but I plan to suggest that the electronic edition ought to be cheaper.

personal comments edit

A few weeks ago I felt burned out and was in sore need of a vacation. I suggested to my wife that we take the kids somewhere and she sagely noted that taking the kids anywhere at their ages is not a vacation. Perhaps I should go somewhere on my own.

IMG_1551Like a deserted lighthouse!Did I mention she’s the best wife ever?

I decided to take a week off and mix a bit of “staycation” with my vacation. Spend a few days at home and maybe a couple of days away.

The first thing I did was call up Hanselman who was game for a trip to Los Angeles for E3. Unfortunately that fell through when we couldn’t score tickets (yes, we’re cheap). We did find some guy on Craigslist who could score us cheap tickets, but his badges looked hand-drawn and made me a wee bit suspicious. I seriously doubt E3 uses Comic Sans as their badge font.

After much deliberation, I decided to take a trip to the nearby San Juan Island for two nights. The plan was to go sea kayaking, but based on the glowing reports of my co-worker Brad Wilson, I also decided to try ziplining.

Kenmore Air

There are two ways to get to San Juan Island, take a ferry or fly. Well, you could also try to swim, but I wouldn’t much recommend it. A ferry is much cheaper, but it’ll take you three hours to get there. Not only that, the view doesn’t compare to that of an airplane that takes off and lands on water. So I went with a sea plane, figuring taking off and landing on water would be really fun.

The plane was cozy (aka small) which allowed me to sit right behind the cockpit and enjoy a panoramic view during the flight to the island. The landing was whisper soft and I barely noticed it.

IMG_1473So I wonder what this button does.I even had the opportunity to help out by holding the mooring rope for the pilot while he got in to start the plane and take off. I thought about holding onto the rope for an exhilarating ride, but my better judgment kicked in.

IMG_1507You’re going to tell me when to let go right? RIGHT?!

Friday Harbor House

It was a short walk to the Friday Harbor House, my lodgings for the trip. I splurged a bit for a room with a view overlooking the harbor, affording me a view of the incoming sea planes and ferries. I also had a view of the folks dining in the garden just outside the restaurant downstairs under my balcony.

IMG_1528 The view of the harbor from my room.

And their view was supplemented by a direct view into my room, keen as I was to keep my window open. Fortunately (for them or for me, I can’t decide), I noticed this before having the occasion to create a very awkward moment.

Unlike most vacations, I actually did spend a lot of time in my room curled up with a good book while enjoying a nice view, so the extra money for the view was well spent.

As a bonus, I learned that the restaurant just under my room was considered by many on the island to be one of the better restaurants.

Ziplining

If you find yourself on San Juan Island, I highly recommend setting apart a bit of time (around 3 hrs) to go ziplining with Zip San Juan. It’s a small operation run by a husband and wife team who exude competence while being extremely friendly. Pat even fashions himself to be a bit of a comedian. I’ll only say I was indeed entertained on the drive there and back.

IMG_3753
(2) You better believe I’m not letting go of this rope.

The group I ended up with was a rambunctious extended family on a trip from their home state of Ohio. They graciously treated me as part of their family which apparently means enduring sarcastic quips for the duration of the trip.

Flinging yourself off of a platform bolted 50 feet up a tree harnessed to a cable is surprisingly a lot of fun. Unless you’re deathly afraid of heights. We ran through eight different lines each more interesting than the previous.

Sea Kayaking

For sea kayaking I went with Discovery Sea Kayaks. They are an outfit that is committed to keeping the size of their tours small. My tour had five folks, not counting the guide. I saw another group with what looked like 12 people.

A tour starts with a brief tutorial on safety and proper paddling before setting out in a set of double canoes. We set out on the west side of the island with a nice view of Canada across the sound. We didn’t catch any whales but did see jellyfish, sea lions, and some doll porpoises.

IMG_1584Who said anything about having to actually paddle?

I was fortunate to be sharing a canoe with the guide ensuring I wouldn’t have any problems hearing the guide as he regaled us with interesting stories about the island’s history and our natural surroundings.

I spent two days and two nights on the Island before returning home feeling much refreshed. I look forward to the next opportunity to take such a trip and highly recommend it if you feel yourself being weighed down by work.

code, asp.net, razor comments edit

As a web guy, I’ve slung more than my fair share of angle brackets over the tubes of the Internet. The Razor syntax quickly became my favorite way of generating those angle brackets soon after its release. But its usefulness is not limited to just the web.

The ASP.NET team designed Razor to generate HTML markup without being tightly coupled to ASP.NET. This opens up the possibility to use Razor in many other contexts other than just a web application.

For example, the help documentation for NuGet.exe is written using the Markdown format that is produced by NuGet.exe. NuGet.exe reflects over its own commands and uses a Razor template to generate the properly formatted output.

The check-in that enabled this caught my eye and prompted me to write this blog post as it’s a very clean approach. I’ll show you how to do the same thing in no time at all.

RazorGenerator

The first step is to install the RazorGenerator extension from the Visual Studio Extension Gallery.

If you haven’t used the Extension Gallery before, within Visual Studio click on the Tools > Extension Manager menu option to launch the Extension Manager dialog. Select the Online tab and type in “RazorGenerator” (without the quotes) in the upper right search bar.

Make sure to install the one named “Razor Generator” (not to be confused with “Razor Single File Generator for MVC”).

razorgenerator-in-vs-extension-gallery

Create your application

For my sample application, I created a simple console application and added a reference to the following assemblies:

  • System.Web.WebPages.dll
  • System.Web.Helpers.dll
  • System.Web.Razor.dll

I then added a new text file and named it RazorTemplate.cshtml. You can name yours whatever you want of course.

Make sure to set the Custom Tool for the CSHTML file to be “RazorGenerator”. To do that, simply right click on the file and select the Properties menu option. Type in “RazorGenerator” (sans quotes) in the field labeled Custom Tool.

Razor-file-properties

I added the following code within the CSHTML file:


@* Generator : Template TypeVisibility : Internal *@
@functions {
  public dynamic Model { get; set; }
}
<ul>
@foreach (var item in Model) {
  <li>@item.Name (@item.Id)</li>  
}
</ul>

That first line is a generator declaration. It’s required to by the Razor Generator. I chose to make the generated template class internal.

The next line starts a functions block. I specify a property for the template named Model in there. If you’re not a fan of the dynamic keyword, please don’t freak out. At least not yet.

I simply chose a dynamic property for the purposes of demonstration, but I could have just as easily made it a strongly typed property. Well, not just as easily as I would have had to create a another type first. But you get the idea.

In fact, I could have added multiple properties to this template if so desired. These properties and methods added here will show up in the generated template class.

The next section is simply the usual razor syntax markup you know and love which is written against the property I defined. In case you’re out of practices with Razor, be sure to check out the C# Razor Syntax Quick Reference I wrote a while back.

Render the template

Now all we need to do is instantiate the template, populate the properties we defined in the template with real values, and we’re done!

So what exactly are we instantiating? The steps we took up until now results in the Razor file generating a template class. If you expand the CSHTML file, you can see the generated class.

Razor-Generated

That’s the class we need to instantiate. Here’s some code I added in Program.cs that makes use of this generated template class.

class Program {
    static void Main(string[] args) {
        var template = new RazorTemplate {
            Model = new[] { 
                new {Name = "Scott", Id = 1},
                new {Name = "Steve", Id = 2},
                new {Name = "Phil", Id = 3},
                new {Name = "David", Id = 4}
            }
        };
        Console.WriteLine(template.TransformText());
        Console.ReadLine();
    }
}

The code is very straightforward. It simply instantiates an instance of the RazorTemplate class and sets the Model property (which is the property I defined within the template) as an array of anonymous objects.

Again, for demonstration purposes, I’m using a dynamic property to access anonymous objects. You can just as well pass in and render strongly typed properties.

After instantiating the template instance, we simply call the TransformText method on it and write the response to the console.

razor-output

Easy as stepping on a Lego block in the dark!

Note that using Razor as a general text templating langage might not always produce the best results. It was heavily geared towards rendering markup (aka angle brackets) which it’s very good at. Your mileage may vary when attempting to render other types of textual output.

In a following post, I’ll show you a cool way I’m using this technique for a library I’ve been working on meant to demonstrate some cool internals of ASP.NET MVC.

Some of what I’ve shown here has been shown before in the context of ASP.NET MVC. Those other posts are worth reading as well. For example…

I hope you find this useful for your text templating needs!

asp.net, code, asp.net mvc comments edit

By default, ASP.NET MVC leverages Data Annotations to provide validation. The approach is easy to get started with and allows the validation applied on the server to “float” to the client without any extra work.

However, once you get localization involved, using Data Annotations can really clutter your models. For example, the following is a simple model class with two properties.

public class Character {
  public string FirstName { get; set; }
  public string LastName { get; set; }
}

Nothing to write home about, but it is nice, clean, and simple.  To make it more useful, I’ll add validation and format how the properties are displayed.

public class Character {
  [Display(Name="First Name")]
  [Required]
  [StringLength(50)]]
  public string FirstName { get; set; }
  
  [Display(Name="Last Name")]
  [Required]
  [StringLength(50)]]
  public string LastName { get; set; }
}

That’s busier, but not horrible. It sure is awful Anglo-centric though. I’ll fix that by making sure the property labels and error messages are pulled from a resource file.

public class Character {
  [Display(Name="Character_FirstName",
    ResourceType=typeof(ClassLib1.Resources))]
  [Required(ErrorMessageResourceType=typeof(ClassLib1.Resources), 
    ErrorMessageResourceName="Character_FirstName_Required")]
  [StringLength(50, ErrorMessageResourceType = typeof(ClassLib1.Resources),
    ErrorMessageResourceName = "Character_FirstName_StringLength")]
  public string FirstName { get; set; }

  [Display(Name="Character_LastName",
    ResourceType=typeof(ClassLib1.Resources))]
  [Required(ErrorMessageResourceType=typeof(ClassLib1.Resources), 
    ErrorMessageResourceName="Character_LastName_Required")]
  [StringLength(50,
    ErrorMessageResourceType = typeof(ClassLib1.Resources),
    ErrorMessageResourceName = "Character_LastName_StringLength")]
  public string LastName { get; set; }
}

Wow! I don’t know about you, but I feel a little bit dirty typing all that in. Allow me a moment as I go wash up.

So what can I do to get rid of all that noise? Conventions to the rescue! By employing a simple set of conventions, I should be able to look up error messages in resource files as well as property labels without having to specify all that information. In fact, by convention I shouldn’t even need to use the DisplayAttribute.

I wrote a custom PROOF OF CONCEPT ModelMetadataProvider that supports this approach. More specifically, mine is derived from the DataAnnotationsModelMetadataProvider.

What Conventions Does It Apply?

The nice thing about this convention based model metadata provider is it allows you to specify as little or as much of the metadata you need and it fills in the rest.

Providing minimal metadata

For example, the following is a class with one simple property.

public class Character {
  [Required]
  [StringLength(50)]
  public string FirstName {get; set;}
}

When displayed as a label, the custom metadata provider looks up the resource key, {ClassName}_{PropertyName},and uses the resource value as the label. For example, for the FirstName property, the provider uses the key Character_FirstName to look up the label in the resource file. I’ll cover how resource type is specified later.

If a value for that resource is not found, the code falls back to using the property name as the label, but splits it using Pascal/Camel casing as a guide. Therefore in this case, the label is “First Name”.

The error message for a validation attribute uses a resource key of {ClassName}_{PropertyName}_{AttributeName}. For example, to locate the error message for a RequiredAttribute, the provider finds the resource key Character_FirstName_Required.

Partial Metadata

There may be cases where you can provide some metadata, but not all of it. Ideally, the metadata that you don’t supply is inferred based on the conventions. Going back to previous example again:

public class Character {
  [Required(ErrorMessageResourceType=typeof(MyResources))]
  [StringLength(50, ErrorMessageResourceName="StringLength_Error")]
  [Display(Name="First Name")]
  public string FirstName {get; set;}
}

Notice that the first attribute only specifies the error message resource type. In this case, the specified resource type will override the default resource type. But the resource key is still inferred by convention (aka Character_FirstName_Required).

In contrast, notice that the second StringLengthAttribute, only specifies the resource name, and doesn’t specify a resource type. In this case, the specified resource name is used to look up the error message using the default resource type. As you might expect, if the ErrorMessage property is specified, that takes precedence over the conventions.

The DisplayAttribute works slightly differently. By default, the Name property is used as a resource key if a resource type is also specified. If no resource type is specified, the Name property is used directly. In the case of this convention based provider, an attempt to lookup a resource value using the Name property as a resource always occurs before falling back to the default behavior.

Configuration

One detail I haven’t covered yet is what resource type is used to find these messages? Is that determined by convention?

Determining this by convention would be tricky so it’s the one bit of information that must be explicitly specified when configuring the provider itself. The following code in Global.asax.cs shows how to configure this.

ModelMetadataProviders.Current = new ConventionalModelMetadataProvider(
  requireConventionAttribute: false,
  defaultResourceType: typeof(MyResources.Resource)
);

The model metadata provider’s constructor has two arguments used to configure it.

Some developers will want the conventions to apply to every model, while others will want to be explicit and have models opt in to this behavior. The first argument, requireConventionAttribute, determines whether the conventions only apply to classes with the MetadataConventionsAttribute applied.

The explicit folks will want to set this value to true so that only classes with the MetadataConventionsAttribute applied to them (or classes in an assembly where the attribute is applied to the assembly) will use these conventions.

The attribute can also be used to specify the resource type for resource strings.

The second property specifies the default resource type to use for resource strings. Note that this can be overridden by any attribute that specifies its own resource type.

Caveats, Issues, Potholes

This code is something I hacked together and there are a few issues to consider that I could not easily work around. First of all, the implementation has to mutate properties of attributes. In general, this is not a good thing to do because attributes tend to be global. If other code relies on the attributes having their original values, this could cause issues.

I think for most ASP.NET MVC applications (in fact most web applications period) this will not be an issue.

Another issue is that the conventions don’t work for implied validation. For example, if you have a property of a simple value type (such as int), the DataAnnotationsValidatorProvider supplies a RequiredValidator to validate the value. Since this validator didn’t come from an attribute, it won’t use my convention based lookup for its error messages.

I thought about making this work, but it the hooks I need to do this without a large amount of code don’t appear to be there. I’d have to write my own validator provider (as far as I can tell) or register my own validator adapters in place of the default ones. I wasn’t up to the task just yet.

Try it out

  • NuGet Package: To try it in your application, install it using NuGet: Install-Package ModelMetadataExtensions
  • Source Code:The source code is up on GitHub.

asp.net, asp.net mvc comments edit

It only feels like yesterday that we shipped ASP.NET MVC 3 followed by a release of updated Visual Studio tooling for ASP.NET MVC 3. But we’re not ones to sit on our hands for long and are busy at work on ASP.NET MVC 4.

In fact, almost immediately after shipping ASP.NET MVC 3, we started working through our backlog of bugs at the same time that we started general planning for the next major version.

Today, I’ve published the result of that planning in the form of a high-level roadmap for ASP.NET MVC 4.

There’s an important disclaimer I want to highlight in the roadmap:

It’s important to understand that we are in the early stagesof development on ASP.NET MVC 4 and that this roadmap is a planning document for the next release. It is not a specification of what is to come. We hope to implement most or all of the features listed here, but there are no guarantees. Plans can change. And you can help change them! Please visit our forums to provide feedback on our plans so that we have a better picture of what you want to see in the next release.

This roadmap is more detailed than roadmaps that we’ve written in the past. My hope is that it provides enough of a taste of the features to come that we can get feedback even earlier on features that we have yet to implement.

One of the cool new features I want to highlight is the feature we’re calling “Recipes”. In brief, a recipe is scaffolding on steroids. These are bits of UI delivered via NuGet for accomplishing common tasks. We put a few ideas in the roadmap, but would love to hear more ideas.

Not included in the roadmap are the many cool enhancements to Razor and other features being considered for the next version of ASP.NET Web Pages that ASP.NET MVC developers will get for free! Erik Porter (aka @humancompiler) and his team are hard at work on those features, so I won’t spoil the surprise.

UPDATE: We started a UserVoice site for ASP.NET MVC features.