ASP.NET - Jon Galloway

ASP.NET

Looking at ASP.NET MVC 5.1 and Web API 2.1 - Part 3 - Bootstrap and JavaScript enhancements

This is part 3 of a 4 part series covering some of the new features in the ASP.NET MVC 5.1 and Web API 2.1 releases.

In this post, we'll be focusing on some client-side improvements to ASP.NET MVC 5.1.

As a reminder if you haven't read the first post, these updates are currently delivered via a NuGet update to your existing ASP.NET MVC 5 / Web API 2 applications. They'll be part of the File / New Project templates included in an upcoming Visual Studio update.

EditorFor now supports passing HTML attributes - Great for Bootstrap

The new ASP.NET project templates all include Bootstrap themes. Bootstrap uses custom class names for everything - styling, components, layout, behavior. That made it frustrating that you couldn't pass classes down to the Html.EditorFor HTML helper: you either had to use specific HTML Helpers like Html.TextBoxFor (which do allow you to pass HTML attributes, but don't benefit from some of the other nice features in HTML.EditorFor, like Data Attribute support for display and input validation) or give up on using the Bootstrap classes and style things yourself.

In the 5.1 release, you can now pass HTML attributes as an additional parameter to Html.EditorFor, allowing you to get the best of both. Here's an example of why that's useful.

In the first post in the series, we scaffolded a simple create controller and associated views. The Create view ended up looking like this:

2014-01-28_10h51_55

That's okay, but it's not taking advantage of any of the Bootstrap form styling (e.g. focus indication, element sizing, groups, etc.) and it won't do anything special with custom Bootstrap themes. A great start would be just to add the "form-control" class to the form elements. That just involves changing from this:

@Html.EditorFor(model => model.FirstName)

to this:

@Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" }, })

When I make that update to the textboxes, I get this view:

2014-01-28_00h51_07

You'll notice some subtle improvements, like the focus highlight on the FirstName field, nicer textbox size and validation layout for Age, etc. These are just really simple things with a  very basic model, but they give a quick idea of the improvement here.

Also nice is that I can pass the attributes on Html.EditorFor when displaying the entire model. Here I've updated the entire form section to just use one EditorFor call, passing in the model:

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>Person</h4>
        <hr />
        @Html.ValidationSummary(true)
        @Html.EditorFor(model => model, new { htmlAttributes = new { @class = "form-control" }, })
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

Note that to make sure the Id property didn't display and to use the custom radio enum display template (as explained in the first post in the series), I added two annotations to my model. Here's how the model and associated Enum look:

public class Person
{
    [ScaffoldColumn(false)]
    public int Id { get; set; }
    [UIHint("Enum-radio")]
    public Salutation Salutation { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}
//I guess technically these are called honorifics
public enum Salutation : byte
{
    [Display(Name = "Mr.")]   Mr,
    [Display(Name = "Mrs.")]  Mrs,
    [Display(Name = "Ms.")]   Ms,
    [Display(Name = "Dr.")]   Doctor,
    [Display(Name = "Prof.")] Professor,
    Sir, 
    Lady, 
    Lord
}

That gives me the exact same output as shown above (the second, nicer screenshot). What's cool there is that the EditorFor method passed that form-control class to each element in the form, so each input tag got the form-control class. That means that I could apply additional Bootstrap classes, as well as my own custom classes, in that same call:

        @Html.EditorFor(model => model, new { htmlAttributes = new { @class = "form-control input-sm my-custom-class" }, })

You can see the code changes and associated tests for this EditorFor change on this commit on CodePlex.

Client-side validation for MinLength and MaxLength

This is a pretty straightforward one: we had client-side validation for StringLength before, but not for MinLength and MaxLength. Personally, I feel like it's a tossup on which to use - StringLength lets you set both min and max and is more widely supported, but MinLength and MaxLength allow you to specify them separately and give different validation messages for each. Regardless, the good news is that whichever you use, they're both supported on both server and client.

To test that out, we'll add some MinLength and MaxLength attributes to our Person class.

public class Person
{
    [ScaffoldColumn(false)]
    public int Id { get; set; }
    [UIHint("Enum-radio")]
    public Salutation Salutation { get; set; }
    [Display(Name = "First Name")]
    [MinLength(3, ErrorMessage = "Your {0} must be at least {1} characters long")]
    [MaxLength(100, ErrorMessage = "Your {0} must be no more than {1} characters")]
    public string FirstName { get; set; }
    [Display(Name = "Last Name")]
    [MinLength(3, ErrorMessage = "Your {0} must be at least {1} characters long")]
    [MaxLength(100, ErrorMessage = "Your {0} must be no more than {1} characters")]
    public string LastName { get; set; }
    public int Age { get; set; }
}

I get immediate feedback on what the website thinks of a potential stage name I've been considering:

2014-01-28_14h45_16

Here's the link to the work item, and here's the code diff for the commit.

Three small but useful fixes to Unobtrusive Ajax

There are a few fixes to Unobtrusive Ajax:

I thought the first fix was pretty interesting: a question came up on StackOverflow, someone posted a suggested one line fix on a CodePlex issue, and it got fixed in this commit.

This issue allows callbacks from Unobtrusive Ajax to have access to the initiating element.  That's pretty handy when you've got multiple potential callers, e.g. a list of items which contain Ajax.ActionLink calls. In the past, I've had to write unnecessarily complicated JavaScript to wire things up manually because I couldn't take advantage of the OnBegin, OnComplete, OnFailure and OnSuccess options, e.g.

<script type="text/javascript">
    $(function () {
        // Document.ready -> link up remove event handler
        $(".RemoveLink").click(function () {
            // Get the id from the link
            var recordToDelete = $(this).attr("data-id");
            if (recordToDelete != '') {
                // Perform the ajax post
                $.post("/ShoppingCart/RemoveFromCart", {"id": recordToDelete },
                    function (data) {
                        // Successful requests get here
                        // Update the page elements
                        if (data.ItemCount == 0) {
                            $('#row-' + data.DeleteId).fadeOut('slow');
                        } else {
                            $('#item-count-' + data.DeleteId).text(data.ItemCount);
                        }
                        $('#cart-total').text(data.CartTotal);
                        $('#update-message').text(data.Message);
                        $('#cart-status').text('Cart (' + data.CartCount + ')');
                    });
            }
        });
    });
</script>

Now with this change, I'd have the option of wiring up the Ajax call and success callbacks separately and tersely, since they'd have access to the calling element for the ID.

That's it for this post, in the next (and definitely last) post of this series I'll look at some ASP.NET Web API 2.1 improvements.

Posted by Jon Galloway | with no comments
Filed under: ,

Top things web developers should know about the Visual Studio 2013 release

ASP.NET and Web Tools for Visual Studio 2013 Release NotesASP.NET and Web Tools for Visual Studio 2013 Release NotesSummary for lazy readers:

  • Visual Studio 2013 is now available for download on the Visual Studio site and on MSDN subscriber downloads)
  • Visual Studio 2013 installs side by side with Visual Studio 2012 and supports round-tripping between Visual Studio versions, so you can try it out without committing to a switch
  • Visual Studio 2013 ships with the new version of ASP.NET, which includes ASP.NET MVC 5, ASP.NET Web API 2, Razor 3, Entity Framework 6 and SignalR 2.0
  • The new releases ASP.NET focuses on One ASP.NET, so core features and web tools work the same across the platform (e.g. adding ASP.NET MVC controllers to a Web Forms application)
  • New core features include new templates based on Bootstrap, a new scaffolding system, and a new identity system
  • Visual Studio 2013 is an incredible editor for web files, including HTML, CSS, JavaScript, Markdown, LESS, Coffeescript, Handlebars, Angular, Ember, Knockdown, etc.

Top links:

Okay, for those of you who are still with me, let's dig in a bit.

Quick web dev notes on downloading and installing Visual Studio 2013

I found Visual Studio 2013 to be a pretty fast install. According to Brian Harry's release post, installing over pre-release versions of Visual Studio is supported.  I've installed the release version over pre-release versions, and it worked fine.

If you're only going to be doing web development, you can speed up the install if you just select Web Developer tools.

Visual Studio 2013 installer

Of course, as a good Microsoft employee, I'll mention that you might also want to install some of those other features, like the Store apps for Windows 8 and the Windows Phone 8.0 SDK, but they do download and install a lot of other stuff (e.g. the Windows Phone SDK sets up Hyper-V and downloads several GB's of VM's). So if you're planning just to do web development for now, you can pick just the Web Developer Tools and install the other stuff later.

If you've got a fast internet connection, I recommend using the web installer instead of downloading the ISO. The ISO includes all the features, whereas the web installer just downloads what you're installing.

Visual Studio 2013 development settings and color theme

When you start up Visual Studio, it'll prompt you to pick some defaults. These are totally up to you -whatever suits your development style - and you can change them later.

Visual Studio 2013 color theme

As I said, these are completely up to you. I recommend either the Web Development or Web Development (Code Only) settings. The only real difference is that Code Only hides the toolbars, and you can switch between them using Tools / Import and Export Settings / Reset.

Web Development settings

Web Development settings

Web Development (code only) settings

Web Development (code only) settings

Usually I've just gone with Web Development (code only) in the past because I just want to focus on the code, although the Standard toolbar does make it easier to switch default web browsers. More on that later.

2013-10-17_09h24_56

Color theme

Sigh. Okay, everyone's got their favorite colors. I alternate between Light and Dark depending on my mood, and I personally like how the low contrast on the window chrome in those themes puts the emphasis on my code rather than the tabs and toolbars. I know some people got pretty worked up over that, though, and wanted the blue theme back. I personally don't like it - it reminds me of ancient versions of Visual Studio that I don't want to think about anymore.

So here's the thing: if you install Visual Studio Ultimate, it defaults to Blue. The other versions default to Light. If you use Blue, I won't criticize you - out loud, that is. You can change themes really easily - either Tools / Options / Environment / General, or the smart way: ctrl+q for quick launch, then type Theme and hit enter.

Signing in

During the first run, you'll be prompted to sign in. You don't have to - you can click the "Not now, maybe later" link at the bottom of that dialog. I recommend signing in, though. It's not hooked in with licensing or tracking the kind of code you write to sell you components. It is doing good things, like  syncing your Visual Studio settings between computers. More about that here. So, you don't have to, but I sure do.

Overview of shiny new things in ASP.NET land

There are a lot of good new things in ASP.NET. I'll list some of my favorite here, but you can read more on the ASP.NET site.

One ASP.NET

You've heard us talk about this for a while. The idea is that options are good, but choice can be a burden. When you start a new ASP.NET project, why should you have to make a tough decision - with long-term consequences - about how your application will work? If you want to use ASP.NET Web Forms, but have the option of adding in ASP.NET MVC later, why should that be hard? It's all ASP.NET, right?

Ideally, you'd just decide that you want to use ASP.NET to build sites and services, and you could use the appropriate tools (the green blocks below) as you needed them.

2013-10-17_09h56_49

So, here it is.

When you create a new ASP.NET application, you just create an ASP.NET application.

2013-10-17_09h59_58

Next, you can pick from some templates to get you started... but these are different. They're not "painful decision" templates, they're just some starting pieces. And, most importantly, you can mix and match. I can pick a "mostly" Web Forms template, but include MVC and Web API folders and core references.

2013-10-17_10h05_27

If you've tried to mix and match in the past, you're probably aware that it was possible, but not pleasant. ASP.NET MVC project files contained special project type GUIDs, so you'd only get controller scaffolding support in a Web Forms project if you manually edited the csproj file. Features in one stack didn't work in others. Project templates were painful choices. That's no longer the case. Hooray!

I just did a demo in a presentation last week where I created a new Web Forms + MVC + Web API site, built a model, scaffolded MVC and Web API controllers with EF Code First, add data in the MVC view, viewed it in Web API, then added a GridView to the Web Forms Default.aspx page and bound it to the Model. In about 5 minutes. Sure, it's a simple example, but it's great to be able to share code and features across the whole ASP.NET family.

Authentication

In the past, authentication was built into the templates. So, for instance, there was an ASP.NET MVC 4 Intranet Project template which created a new ASP.NET MVC 4 application that was preconfigured for Windows Authentication. All of that authentication stuff was built into each template, so they varied between the stacks, and you couldn't reuse them. You didn't see a lot of changes to the authentication options, since they required big changes to a bunch of project templates.

Now, the new project dialog includes a common authentication experience. When you hit the Change Authentication button, you get some common options that work the same way regardless of the template or reference settings you've made. These options work on all ASP.NET frameworks, and all hosting environments (IIS, IIS Express, or OWIN for self-host)

The default is Individual User Accounts:

2013-10-17_10h33_15

This is the standard "create a local account, using username / password or OAuth" thing; however, it's all built on the new Identity system. More on that in a second.

The one setting that has some configuration to it is Organizational Accounts, which lets you configure authentication using Active Directory, Windows Azure Active Directory, or Office 365.

2013-10-17_10h46_50

Identity

There's a new identity system. We've taken the best parts of the previous ASP.NET Membership and Simple Identity systems, rolled in a lot of feedback and made big enhancements to support important developer concerns like unit testing and extensiblity.

I've written long posts about ASP.NET identity, and I'll do it again. Soon. This is not that post. The short version is that I think we've finally got just the right Identity system. Some of my favorite features:

  • There are simple, sensible defaults that work well - you can File / New / Run / Register / Login, and everything works.
  • It supports standard username / password as well as external authentication (OAuth, etc.).
  • It's easy to customize without having to re-implement an entire provider. It's built using pluggable pieces, rather than one large monolithic system.
  • It's built using interfaces like IUser and IRole that allow for unit testing, dependency injection, etc.
  • You can easily add user profile data (e.g. URL, twitter handle, birthday). You just add properties to your ApplicationUser model and they'll automatically be persisted.
  • Complete control over how the identity data is persisted. By default, everything works with Entity Framework Code First, but it's built to support changes from small (modify the schema) to big (use another ORM, store your data in a document database or in the cloud or in XML or in the EXIF data of your desktop background or whatever).
  • It's configured via OWIN. More on OWIN and Katana later, but the fact that it's built using OWIN means it's portable.

You can find out more in the Authentication and Identity section of the ASP.NET site (and lots more content will be going up there soon).

New Bootstrap based project templates

The new project templates are built using Bootstrap 3. Bootstrap (formerly Twitter Bootstrap) is a front-end framework that brings a lot of nice benefits:

  • It's responsive, so your projects will automatically scale to device width using CSS media queries. For example, menus are full size on a desktop browser, but on narrower screens you automatically get a mobile-friendly menu.
  • The built-in Bootstrap styles make your standard page elements (headers, footers, buttons, form inputs, tables etc.) look nice and modern.
  • Bootstrap is themeable, so you can reskin your whole site by dropping in a new Bootstrap theme. Since Bootstrap is pretty popular across the web development community, this gives you a large and rapidly growing variety of templates (free and paid) to choose from.
  • Bootstrap also includes a lot of very useful things: components (like progress bars and badges), useful glyphicons, and some jQuery plugins for tooltips, dropdowns, carousels, etc.).

Here's a look at how the responsive part works. When the page is full screen, the menu and header are optimized for a wide screen display:

2013-10-17_12h14_50

When I shrink the page down (this is all based on page width, not useragent sniffing) the menu turns into a nice mobile-friendly dropdown:

2013-10-17_12h15_12

For a quick example, I grabbed a new free theme off bootswatch.com. For simple themes, you just need to download the boostrap.css file and replace the /content/bootstrap.css file in your project.

2013-10-17_12h27_44

Now when I refresh the page, I've got a new theme:

2013-10-17_12h27_33

Scaffolding

The big change in scaffolding is that it's one system that works across ASP.NET. You can create a new Empty Web project or Web Forms project and you'll get the Scaffold context menus.

2013-10-17_12h36_14

For release, we've got MVC 5 and Web API 2 controllers. We had a preview of Web Forms scaffolding in the preview releases, but they weren't fully baked for RTM. Look for them in a future update, expected pretty soon.

This scaffolding system wasn't just changed to work across the ASP.NET frameworks, it's also built to enable future extensibility. That's not in this release, but should also hopefully be out soon.

Project Readme page

This is a small thing, but I really like it. When you create a new project, you get a Project_Readme.html page that's added to the root of your project and opens in the Visual Studio built-in browser.

2013-10-17_14h25_35

I love it.

A long time ago, when you created a new project we just dumped it on you and left you scratching your head about what to do next. Not ideal.

Then we started adding a bunch of Getting Started information to the new project templates. That told you what to do next, but you had to delete all of that stuff out of your website. It doesn't belong there. Not ideal.

This is a simple HTML file that's not integrated into your project code at all. You can delete it if you want. But, it shows a lot of helpful links that are current for the project you just created. In the future, if we add new wacky project types, they can create readme docs with specific information on how to do appropriately wacky things.

Side note: I really like that they used the internal browser in Visual Studio to show this content rather than popping open an HTML page in the default browser. I hate that. It's annoying. If you're doing that, I hope you'll stop. What if some unnamed person has 40 or 90 tabs saved in their browser session? When you pop open your "Thanks for installing my Visual Studio extension!" page, all eleventy billion tabs start up and I wish I'd never installed your thing. Be like these guys and pop stuff Visual Studio specific HTML docs in the Visual Studio browser.

ASP.NET MVC 5

The biggest change with ASP.NET MVC 5 is that it's no longer a separate project type. It integrates well with the rest of ASP.NET.

In addition to that and the other common features we've already looked at (Bootstrap templates, Identity, authentication), here's what's new for ASP.NET MVC.

Attribute routing

ASP.NET MVC now supports attribute routing, thanks to a contribution by Tim McCall, the author of http://attributerouting.net. With attribute routing you can specify your routes by annotating your actions and controllers. This supports some pretty complex, customized routing scenarios, and it allows you to keep your route information right with your controller actions if you'd like.

Here's a controller that includes an action whose method name is Hiding, but I've used AttributeRouting to configure it to /spaghetti/with-nesting/where-is-waldo

public class SampleController : Controller
{

    [Route("spaghetti/with-nesting/where-is-waldo")]
    public string Hiding() 
    {
        return "You found me!";
    }
}

I enable that in my RouteConfig.cs, and I can use that in conjunction with my other MVC routes like this:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapMvcAttributeRoutes();

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

2013-10-17_14h06_56

You can read more about Attribute Routing in ASP.NET MVC 5 here.

Filter enhancements

There are two new additions to filters: Authentication Filters and Filter Overrides.

Authentication filters are a new kind of filter in ASP.NET MVC that run prior to authorization filters in the ASP.NET MVC pipeline and allow you to specify authentication logic per-action, per-controller, or globally for all controllers. Authentication filters process credentials in the request and provide a corresponding principal. Authentication filters can also add authentication challenges in response to unauthorized requests.

Override filters let you change which filters apply to a given action method or controller. Override filters specify a set of filter types that should not be run for a given scope (action or controller). This allows you to configure filters that apply globally but then exclude certain global filters from applying to specific actions or controllers.

ASP.NET Web API 2

ASP.NET Web API 2 includes a lot of new features.

Attribute Routing

ASP.NET Web API supports the same attribute routing system that's in ASP.NET MVC 5. You can read more about the Attribute Routing features in Web API in this article.

OAuth 2.0

ASP.NET Web API picks up OAuth 2.0 support, using security middleware running on OWIN (discussed below). This is great for features like authenticated Single Page Applications.

OData Improvements

ASP.NET Web API now has full OData support. That required adding in some of the most powerful operators: $select, $expand, $batch and $value. You can read more about OData operator support in this article by Mike Wasson.

Lots more

There's a huge list of other features, including CORS (cross-origin request sharing), IHttpActionResult, IHttpRequestContext, and more. I think the best overview is in the release notes.

OWIN and Katana

I've written about OWIN and Katana recently. I'm a big fan.

OWIN is the Open Web Interfaces for .NET. It's a spec, like HTML or HTTP, so you can't install OWIN. The benefit of OWIN is that it's a community specification, so anyone who implements it can plug into the ASP.NET stack, either as middleware or as a host.

Katana is the Microsoft implementation of OWIN. It leverages OWIN to wire up things like authentication, handlers, modules, IIS hosting, etc., so ASP.NET can host OWIN components and Katana components can run in someone else's OWIN implementation.

Howard Dierking just wrote a cool article in MSDN magazine describing Katana in depth: Getting Started with the Katana Project. He had an interesting example showing an OWIN based pipeline which leveraged SignalR, ASP.NET Web API and NancyFx components in the same stack.

If this kind of thing makes sense to you, that's great. If it doesn't, don't worry, but keep an eye on it. You're going to see some cool things happen as a result of ASP.NET becoming more and more pluggable.

Visual Studio Web Tools

Okay, this stuff's just crazy. Visual Studio has been adding some nice web dev features over the past few years, but they've really cranked it up for this release.

Visual Studio is by far my favorite code editor for all web files: CSS, HTML, JavaScript, and lots of popular libraries.

Stop thinking of Visual Studio as a big editor that you only use to write back-end code. Stop editing HTML and CSS in Notepad (or Sublime, Notepad++, etc.). Visual Studio starts up in under 2 seconds on a modern computer with an SSD. Misspelling HTML attributes or your CSS classes or jQuery or Angular syntax is stupid. It doesn't make you a better developer, it makes you a silly person who wastes time.

Browser Link

Browser Link is a real-time, two-way connection between Visual Studio and all connected browsers. It's only attached when you're running locally, in debug, but it applies to any and all connected browser, including emulators.

You may have seen demos that showed the browsers refreshing based on changes in the editor, and I'll agree that's pretty cool. But it's really just the start. It's a two-way connection, and it's built for extensiblity. That means you can write extensions that push information from your running application (in IE, Chrome, a mobile emulator, etc.) back to Visual Studio. Mads and team have showed off some demonstrations where they enabled edit mode in the browser which updated the source HTML back on the browser. It's also possible to look at how the rendered HTML performs, check for compatibility issues, watch for unused CSS classes, the sky's the limit.

New HTML editor

The previous HTML editor had a lot of old code that didn't allow for improvements. The team rewrote the HTML editor to take advantage of the new(ish) extensibility features in Visual Studio, which then allowed them to add in all kinds of features - things like CSS Class and ID IntelliSense (so you type style="" and get a list of classes and ID's for your project), smart indent based on how your document is formatted, JavaScript reference auto-sync, etc.

Here's a 3 minute tour from Mads Kristensen.

Integrated Windows Azure Web Site creation and publishing

The Windows Azure portal is good as websites go, but it's another step to have to go to the portal to create a site, then download the publish profile, then import it into my site. It's like ten clicks or something and it just gets really fatiguing and sometimes I need a nap.

They've updated the Server Explorer in Visual Studio 2013 so I can just right-click on the Windows Azure node to create a site. Then when I'm publishing, I can directly import the site publish profile and go. That means I can create a new Windows Azure Web Site, with a free 20 MB SQL Database, and publish it to Windows Azure all without leaving Visual Studio. That's really nice.

2013-10-17_15h56_26

More about that on this post: Creating New Windows Azure Web Site from Visual Studio 2013 RC

Lots more Visual Studio web dev features

That's just a sampling - there's a ton of great features for JavaScript editing, CSS editing, publishing, and Page Inspector (which shows real-time rendering of your page inside Visual Studio). Here are some more short videos showing those features.

Lots, lots more

Okay, that's just a summary, and it's still quite a bit. Head on over to http://asp.net/vnext for more information, and download Visual Studio 2013 now to get started!

Getting up to speed with Katana

You may have heard some talk about OWIN and the Katana Project over the past few years. Let's get the (kind of boring and abstract) definitions out of the way, then talk about why they're exciting and how you can learn more.

OWIN (Open Web Interface for .NET) defines a standard interface between .NET web servers and web applications. The goal of the OWIN interface is to decouple server and application, encourage the development of simple modules for .NET web development, and, by being an open standard, stimulate the open source ecosystem of .NET web development tools.

The Katana Project provides a set of OWIN implementations for Microsoft servers and frameworks.

In case it's not immediately obvious why those things are actually useful, let's throw some colorful pictures at the problem. Here's how ASP.NET has always worked:

Traditional ASP.NET Hosting Model

In this model, you work in a sandbox that provided you some known extension points. Creating a new ASP.NET application creates a special .NET project which has been tightly wired to the ASP.NET runtime, which in turn is pretty tightly wired to IIS. ASP.NET can be extended via with handlers and modules and the various ASP.NET frameworks (ASP.NET Web Forms, ASP.NET MVC, ASP.NET Web API, etc.) provide hooks that let you override or configure the way things work (IIS provides some extensibility points as well) but you're always aware that you're being hosted by ASP.NET and IIS.

OWIN defines a flexible, pluggable stack with a lightweight interface for web applications.

ASP.NET hosting under OWIN and Katana

Each component in the stack just needs to implement a function which accepts a dictionary (holding the application state) and returning a task. This flexible interface between layers provides a lot of benefits:

  • Fast - This is a really lightweight interface that doesn't need to bring along the whole ASP.NET / IIS party to every request, so it's really tight and can run really, really fast.
  • Pluggable - The middleware section in the above diagram shows more than one component. You can easily plug in lightweight components which modify your how your application runs. Middleware can handle all kinds of scenarios, including authentication and security, optimization, response modification, etc.
  • Flexible - You can mix and match anything that implements the OWIN spec, meaning you could drop ASP.NET applications with Katana on another server or host as well as host other .NET web frameworks (e.g. NancyFx, ServiceStack, Fubu, etc.) on any OWIN compatible server, with the flexibility to use any OWIN compatible middleware.

The Katana team is working to enable several really exciting scenarios, including hosting ASP.NET applications on OWIN hosts and plugging in OWIN middleware to existing ASP.NET applications.

Interested?

Great, because I've got a bunch of fresh, new recommendations on where you can find out more.

Whitepaper: An Overview of Project Katana

We just published a new whitepaper by Howard Dierking on the ASP.NET site: An Overview of Project Katana

Howard goes into a lot more detail about why Project Katana was started, how Project Katana implements OWIN, and how you can get started with Project Katana (complete with a nice walkthrough).

Video overview on Web Camps TV

Brady Gaster and Cory Fowler just interviewed Howard on Web Camps TV (Channel 9) last week. In this 45 minute video, Howard talks about Katana Project, builds out an application showing OWIN self hosting with an ASP.NET Web API application, and explains what's next for Project Katana.

The Katana Project - OWIN for ASP.NET

Podcast

We just interviewed Louis DeJardin (Principal SDE on the Katana team, @loudej, blog) on the Herding Code podcast last month. Detailed show notes are available here.

Download / Listen

Herding Code 164: OWIN and Katana with Louis DeJardin

What are you still doing here?

Go read, watch, and listen!

Posted by Jon Galloway | 4 comment(s)
Filed under:

Building Web Apps with ASP.NET Jump Start - Over 6 hours of free ASP.NET video training

Last Friday Microsoft Learning hosted Scott Hansleman, Damian Edwards and me for a full day live video Jump Start event titled Building Web Apps with ASP.NET. We had a nice crowd of about 2,300 attendees joining us during the event - but we were really excited about ending up with a full day of top quality training on ASP.NET 4.5, ASP.NET MVC 4, ASP.NET Web API, SignalR, and Visual Studio - all updated for the ASP.NET and Web Tools 2012.2 release. The Microsoft Learning team has a great studio, event platform, and team, and I think the videos turned out great.

Thanks

This wouldn't have been possible without the heroic efforts of both Scott Hanselman and Damian Edwards. Scott hadn't been feeling well earlier that week, but presented an entire day of training immediately after a full week at the MVP Summit. Damian wasn't originally scheduled for this, but he was free that day and jumped right in - originally Scott and I invited him just to do the SignalR talk, but when we found he was available the whole day we asked him to help on a bunch of other sessions.

Thanks also to the whole Microsoft Learning team, especially Frank Gartland for setting this up. The Microsoft Virtual Academy puts out a lot of great content, including full courses which help you keep up with new releases (and prepare for certification exams if you're interested).

Content and Sample Code

This content was based on the courseware I just helped update for our current Web Camps tour. A lot of the demos are available in the Web Camps Training Kit, available here. We've got a bunch of free, one day Web Camp events going on over the next few months - with several more being added as we finalize dates and locations.

Videos

All nine sessions (over six hours) are up on Channel 9 - you can watch them online (HTML5 video or Silverlight) or download them in a bunch of MP4 or WMV formats. I've got them embedded below, too.

(01) What's New in ASP.NET 4.5

Sections:

[02:51] - Web development overview

This session starts by overviewing what we're going to cover in the series. The only way I can keep up with all the new releases the ASP.NET and Web Tools teams keep cranking out is to work out a mental map of how it all fits together. For the purpose of this day, we broke things into foundations and scenarios. The foundations include One ASP.NET (including ASP.NET Web Forms, ASP.NET MVC, ASP.NET Web API, and SignalR), Visual Studio, NuGet, and Azure - specifically Windows Azure Web Sites). After covering those tools, we look at using using them in some modern web development scenarios, such as social web applications, mobile web development, etc.

[10:48] - ASP.NET Web Forms model binding

ASP.NET 4.5 includes what I consider the biggest, most fundamental and transformative change to Web Forms since it was first released - model binding. I would have loved to have this years ago, and if you're doing ASP.NET Web Forms and not taking advantage of the new data control features, I really think you're both working too hard and writing lower quality code than you should be. The ASP.NET and Web Tools 2012.2 release includes Friendly URLs support, which gives you the full benefits of URL routing - both cleaner URLs and binding of URL values to control data access methods. My demo shows using the models from the MVC Music Store tutorial in an ASP.NET Web Forms application; it's available in the Web Camps Training Kit.

[20:27] - Bundling and Optimization

Bundling and Optimization is built in to ASP.NET 4.5, so it works across the platform. Scott shows a great example demonstrating bundling and optimization extensibility with both CoffeeScript and LESS minification.

[39:53] - Page inspector

The Visual Studio 2012 Page Inspector lets you interact with the output of your web pages inside of Visual Studio. It's conceptually similar to browser dev tools, but since it's integrated to your source it can give you a lot better information and feedback, answering questions like "Which view / partial view / user control / etc. is actually generating this HTML?" I demo'd the basic features, then showed the new live update feature in the ASP.NET and Web Tools 2012.2 release.

[43:58] - Async

ASP.NET 4.5 includes support for Async just about everywhere, including ASP.NET Web Forms, ASP.NET MVC controllers, etc. Scott shows a nice, simple example in which he changes three synchronous operations to run in parallel in an ASP.NET Web Form.

(02) Building and Deploying Websites with ASP.NET MVC 4

Okay, this one was fun up until my demo fail cliff hanger right at the end. I started with File / New Project, built out a simple ASP.NET MVC site, and deployed it to Windows Azure Web Sites.

[01:26] - Intro to ASP.NET MVC

No ASP.NET MVC talk is compete without a few diagrams, so I start with a review of the how ASP.NET MVC works, complete with some fancy animated diagrams.

[03:58] - Creating a new ASP.NET MVC site

In this part of the talk, I show the different ASP.NET MVC project template, tour through the folder structure, show how routing works, explain the standard conventions used in ASP.NET MVC, and show how the controllers and views work together.

[15:19] - Adding a model, controller, view

This part of the presentation shows how to work with data in an ASP.NET MVC application using models and scaffolding, with data backed by Entity Framework Code First. I set up Entity Framework Code First Migrations to keep changes to my data model synchronized with my database over time.

[34:57] - Deploying to Windows Azure Web Sites

With a complete, working application, it's time to deploy. To the cloud! Well, kind of. I was aware that if people are accessing your URL during a first deployment it can cause problems, but I'd never seen it in practice. Someone F5 bombed me and the deploy failed, which, was corrected by redeploying an unchanged web.config file to refresh the site. But, the cool part is that we built and deployed a site - complete with database and migrations - in under an hour. One of our attendees was so inspired that he created another site to encourage Scott to survive the day: http://scottwillpullthrough.azurewebsites.net/

(03) Creating HTML5 Applications with jQuery

[02:31] - Introduction to HTML5

Scott and Damian explain what HTML5 is, and what it means to you as a web developer, including an overview of modern web development features like responsive design.

[13:13] - HTML5 markup

Scott and Damian show how HTML5 semantic tags are included in ASP.NET MVC 4 and ASP.NET Web Forms 4.5 templates and explain why they're useful. They explain why feature detection is preferable to useragent sniffing and show how Modernizr makes doing the right thing easy.

[27:06] - jQuery overview

Scott and Damian show why everyone's using jQuery and overview the basics. Damian showed off a simple demo I put together that's up on jsbin: http://jsbin.com/ijucaq/2/edit (play along at home!)

[48:04] - Visual Studio web tools

Scott shows off a bunch of great new web development features in Visual Studio 2012 (including the 2012.2 updates and the Web Essentials extension) with some cool examples like HTML5 form elements and the new Single Page Application templates.

(04) Building a Service Layer with ASP.NET Web API

This is a whirlwind tour of ASP.NET Web API, including some new features in 2012.2 (Help Pages, Tracing, and OData).

[01:32] - Introduction to Web API

We start by looking at the File / New Project experience for the Web API template, covering Help Pages and Tracing.

[14:40] - Consuming Web API from jQuery

This sample showed using jQuery and the OData query syntax to page through server-side data.

[20:44] - Consuming Web API from Windows 8

One of the key reasons for using ASP.NET Web API is that you're able to work with any client type that can "speak HTTP" - including mobile and desktop applications. In this sample, I demonstrated a Windows Store application that was calling back into an ASP.NET Web API service.

(05) Leveraging Your ASP.NET Development Skills to Build Office Apps

You might not have heard that you can write Apps for Office using web technologies like HTML5, jQuery, and ASP.NET. It's really pretty slick. I thought it was so cool, I squeezed in a quick 15 minute talk to show it off.

[01:25] - HTML5 and jQuery for Office 2013

I start by showing a simple Hello World example, using jQuery to read and write Excel data into a task pane. Note: my demos require the Microsoft Office Developer Tools for Visual Studio 2012.

[07:53] - Adding ASP.NET Web API

This demo goes a bit further by showing an Excel Task Pane app that posts data back to a backing ASP.NET Web API service, then displays the result. Brady Gaster wrote this demo; it's available in the Web Camps Training Kit.

[12:24] - What is an App for Office

After having explained the model, I showed how you can get and sell Apps for Office in the store, then showed where you can find more information.

(06) Building and Leveraging Social Services in ASP.NET

Several people told me this was their favorite session. The scripted part is good - it shows how to let your users log into your ASP.NET applications using OAuth and OpenID, then explains the new Facebook app template in the 2012.2 release.

But our live viewers really liked watching the unscripted part, when Scott and Damian troubleshot a problem with Twitter app setup because Twitter wouldn't allow an authentication callback to Scott's laptop. Hilarity - but also some pretty slick, on the fly troubleshooting - ensued.

03:02] - OAuth flow

Scott and Damian explain how OAuth works, and how you can use it to enable users to log into your ASP.NET sites without a password.

[06:34] - Demo - OAuth and OpenID

Scott and Damian set up Twitter and Google authentication for an ASP.NET application.

[27:47] - Facebook applications

Scott and Damian explain how Facebook Aps work, then show how the new Facebook app template makes it a lot easier to develop Facebook applications and interact with the Facebook "social graph".

(07) Building for the Mobile Web

Scott shows three options for how to deal with the the ever-growing percentage of mobile browsers: do nothing, change the client (adaptive rendering), or change the server (display modes or using jQuery Mobile)

08:24] - Adaptive rendering - change the client

Scott shows you can use CSS @media queries to adapt the HTML for different display dimensions.

[11:24] - Display modes and jQuery Mobile - change the server

Scott shows how you can use ASP.NET MVC 4 display modes to create generic mobile views or custom, device specific views. He demonstrates how to use mobile browser emulators to test how the display modes will work on the target device. You can find out more about mobile device simulators here: http://www.asp.net/mobile/device-simulators

Scott's walkthrough on working with jQuery Mobile in ASP.NET is really worth watching - he demonstrates how to take advantage of some more advanced jQuery mobile features using the ASP.NET MVC 4 Mobile template. You can find out more about using the some of the techniques Scott demonstrates in this tutorial: ASP.NET MVC 4 Mobile Features.

(08) Real-time Communication with SignalR

SignalR makes it easy to do real-time web applications in ASP.NET. If you want to learn about SignalR - and I'd suggest that you do - Damian is the guy. He and David Fowler started developing SignalrR as an open source library two years ago, and he gives a really clear explanation that's both deeply technical and understandable.

[08:00] - Demo - Move shape

Damian shows a nice visual example with two browsers communicating via a SignalR backend; moving a shape in one browser instantly moves it in the other browser. You can find the code for this demo in the SignalR ASP.NET samples, titled ShapeShare.

[29:18] - Connecting to SignalR with C# and JavaScript clients

Damian demonstrates concurrent connections to the same hub from a WPF client and several different browsers.

[36:56] - Real-time gaming: ShootlR

Damian shows off the ShootR multiplayer HTML5 game, with over 260 live players. He explains the mechanics, including the different game loops and how they optimize for realtime multiplayer games. The code for ShootR is available here.

[44:20] - Chat application: JabbR

Damian shows off the JabbR chat system and talks about scaling with backplanes, then shows off some new features they're working on.

(09) Taking Advantage of Windows Azure Services

[01:20] - Azure signup

I explain the Azure signup process and talk about what you can get for free. Scott and I talked about how little it costs, and talked about how caching can make that even lower.

[05:00] - DevCamps.ms

I talk about how we've been using Windows Azure Web Sites for the DevCamps.ms site, and Scott and I talk about the ability to scale up and down. I also explain how we use separate Windows Azure Web Sites instances for QA and Staging on DevCamps.ms, using Git deploy. Scott and I discuss the ability to be able to roll back to previous Git deployments if needed.

[08:45] - Single serving sites

I show off a quick example of a "single serving" site for quick code demos.

[09:40] - Windows Azure Store

Scott and I talk about services - many free - which are available in the Windows Azure Store. I show off a demo what you get in the free version of New Relic.

[15:36] - Azure command line

Scott shows off all the sites he's running in Windows Azure and demonstrates how he can use the Azure command line to manage his sites. He explains that they're written in JavaScript and run cross-platform; for more information on that, see this tutorial: How to use the Windows Azure Command-Line Tools for Mac and Linux

[20:06] - Wrap-up

Scott, Damian and I wrap up the day with an overview of what we've covered and where you can go for more information.

Guest (and occasional co-host) on Jesse Liberty's Yet Another Podcast

I was a recent guest on Jesse Liberty's Yet Another Podcast talking about the latest Visual Studio, ASP.NET and Azure releases.

Download / Listen:

Yet Another Podcast #75–Jon Galloway on ASP.NET/ MVC/ Azure

Co-hosted shows:

Jesse's been inviting me to co-host shows and I told him I'd show up when I was available. It's a nice change to be a drive-by co-host on a show (compared with the work that goes into organizing / editing / typing show notes for Herding Code shows). My main focus is on Herding Code, but it's nice to pop in and talk to Jesse's excellent guests when it works out. Some shows I've co-hosted over the past year:

Yet Another Podcast #76–Glenn Block on Node.js & Technology in China

Yet Another Podcast  #73 - Adam Kinney on developing for Windows 8 with HTML5

Yet Another Podcast #64 - John Papa & Javascript

Yet Another Podcast #60 - Steve Sanderson and John Papa on Knockout.js

Yet Another Podcast #54–Damian Edwards on ASP.NET

Yet Another Podcast #53–Scott Hanselman on Blogging

Yet Another Podcast #52–Peter Torr on Windows Phone Multitasking

Yet Another Podcast #51–Shawn Wildermuth: //build, Xaml Programming & Beyond

And some more on the way that haven't been released yet. Some of these I'm pretty quiet, on others I get wacky and hassle the guests because, hey, not my podcast so not my problem.

Show notes from the ASP.NET / MVC / Azure show:

  • What was just released
    • Visual Studio 2012 Web Developer features
    • ASP.NET 4.5 Web Forms
      • Strongly Typed data controls
      • Data access via command methods
      • Similar Binding syntax to ASP.NET MVC
      • Some context: Damian Edwards and WebFormsMVP
      • Two questions from Jesse:
        • Q: Are you making this harder or more complicated for Web Forms developers?
          • Short answer: Nothing's removed, it's just a new option
          • History of SqlDataSource, ObjectDataSource
        • Q: If I'm using some MVC patterns, why not just move to MVC?
          • Short answer: This works really well in hybrid applications, doesn't require a rewrite
          • Allows sharing models, validation, other code between Web Forms and MVC
    • ASP.NET MVC
      • Adaptive Rendering (oh, also, this is in Web Forms 4.5 as well)
      • Display Modes
      • Mobile project template using jQuery Mobile
      • OAuth login to allow Twitter, Google, Facebook, etc. login
    • Jon (and friends') MVC 4 book on the way: Professional ASP.NET MVC 4
    • Windows 8 development
      • Jesse and Jon announce they're working on a new book: Pro Windows 8 Development with XAML and C#
      • Jon and Jesse agree that it's nice to be able to write Windows 8 applications using the same skills they picked up for Silverlight, WPF, and Windows Phone development.
    • Compare / contrast ASP.NET MVC and Windows 8 development
      • Q: Does ASP.NET and HTML5 development overlap?
        • Jon thinks they overlap in the MVC world because you're writing HTML views without controls
        • Jon describes how his web development career moved from a preoccupation with server code to a focus on user interaction, which occurs in the browser
        • Jon mentions his NDC Oslo presentation on Learning To Love HTML as Beautiful Code
      • Q: How do you apply C# / XAML or HTML5 skills to Windows 8 development?
      • Q: If I'm a XAML programmer, what's the learning curve on getting up to speed on ASP.NET MVC?
        • Jon describes the difference in application lifecycle and state management
        • Jon says it's nice that web development is really interactive compared to application development
      • Q: Can you learn MVC by reading a book? Or is it a lot bigger than that?
    • What is Azure, and why would I use it?
      • Jon describes the traditional Azure platform mode and how Azure Web Sites fits in
      • Q: Why wouldn't Jesse host his blog on Azure Web Sites?
        • Domain names on Azure Web Sites
        • File hosting options
      • Q: Is Azure just another host? How is it different from any of the other shared hosting options?
        • A: Azure gives you the ability to scale up or down whenever you want
        • A: Other services are available if or when you want them
Posted by Jon Galloway | 4 comment(s)
Filed under: , ,

Adding an Admin user to an ASP.NET MVC 4 application using a single drop-in file

I'm working on an ASP.NET MVC 4 tutorial and wanted to set it up so just dropping a file in App_Start would create a user named "Owner" and assign them to the "Administrator" role (more explanation at the end if you're interested).

There are reasons why this wouldn't fit into most application scenarios:

  • It's not efficient, as it checks for (and creates, if necessary) the user every time the app starts up
  • The username, password, and role name are hardcoded in the app (although they could be pulled from config)
  • Automatically creating an administrative account in code (without user interaction) could lead to obvious security issues if the user isn't informed

However, with some modifications it might be more broadly useful - e.g. creating a test user with limited privileges, ensuring a required account isn't accidentally deleted, or - as in my case - setting up an account for demonstration or tutorial purposes.

Challenge #1: Running on startup without requiring the user to install or configure anything

I wanted to see if this could be done just by having the user drop a file into the App_Start folder and go. No copying code into Global.asax.cs, no installing addition NuGet packages, etc. That may not be the best approach - perhaps a NuGet package with a dependency on WebActivator would be better - but I wanted to see if this was possible and see if it offered the best experience.

Fortunately ASP.NET 4 and later provide a PreApplicationStartMethod attribute which allows you to register a method which will run when the application starts up. You drop this attribute in your application and give it two parameters: a method name and the type that contains it. I created a static class named PreApplicationTasks with a static method named, then dropped this attribute in it:

[assembly: PreApplicationStartMethod(typeof(PreApplicationTasks), "Initializer")] 

That's it. One small gotcha: the namespace can be a problem with assembly attributes. I decided my class didn't need a namespace.

Challenge #2: Only one PreApplicationStartMethod per assembly

In .NET 4, the PreApplicationStartMethod is marked as AllMultiple=false, so you can only have one PreApplicationStartMethod per assembly. This was fixed in .NET 4.5, as noted by Jon Skeet, so you can have as many PreApplicationStartMethods as you want (allowing you to keep your users waiting for the application to start indefinitely!).

The WebActivator NuGet package solves the multiple instance problem if you're in .NET 4 - it registers as a PreApplicationStartMethod, then calls any methods you've indicated using [assembly: WebActivator.PreApplicationStartMethod(type, method)]. David Ebbo blogged about that here:  Light up your NuGets with startup code and WebActivator.

In my scenario (bootstrapping a beginner level tutorial) I decided not to worry about this and stick with PreApplicationStartMethod.

Challenge #3: PreApplicationStartMethod kicks in before configuration has been read

This is by design, as Phil explains. It allows you to make changes that need to happen very early in the pipeline, well before Application_Start. That's fine in some cases, but it caused me problems when trying to add users, since the Membership Provider configuration hadn't yet been read - I got an exception stating that "Default Membership Provider could not be found."

PreApplicationStartMethod fires before config is loaded

The solution here is to run code that requires configuration in a PostApplicationStart method. But how to do that?

Challenge #4: Getting PostApplicationStartMethod without requiring WebActivator

The WebActivator NuGet package, among other things, provides a PostApplicationStartMethod attribute. That's generally how I'd recommend running code that needs to happen after Application_Start:

[assembly: WebActivator.PostApplicationStartMethod(typeof(TestLibrary.MyStartupCode), "CallMeAfterAppStart")]

This works well, but I wanted to see if this would be possible without WebActivator. Hmm.

Well, wait a minute - WebActivator works in .NET 4, so clearly it's registering and calling PostApplicationStartup tasks somehow. Off to the source code! Sure enough, there's even a handy comment in ActivationManager.cs which shows where PostApplicationStartup tasks are being registered:

public static void Run()
{
    if (!_hasInited)
    {
        RunPreStartMethods();

        // Register our module to handle any Post Start methods. But outside of ASP.NET, just run them now
        if (HostingEnvironment.IsHosted)
        {
            Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(StartMethodCallingModule));
        }
        else
        {
            RunPostStartMethods();
        }

        _hasInited = true;
    }
}

Excellent. Hey, that DynamicModuleUtility seems familiar... Sure enough, K. Scott Allen mentioned it on his blog last year. This is really slick - a PreApplicationStartMethod can register a new HttpModule in code. Modules are run right after application startup, so that's a perfect time to do any startup stuff that requires configuration to be read. As K. Scott says, it's this easy:

using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;

[assembly:PreApplicationStartMethod(typeof(MyAppStart), "Start")]

public class CoolModule : IHttpModule
{
    // implementation not important 
    // imagine something cool here
}

public static class MyAppStart
{
    public static void Start()
    {
        DynamicModuleUtility.RegisterModule(typeof(CoolModule));
    }
}

Challenge #5: Cooperating with SimpleMembership

The ASP.NET MVC Internet template includes SimpleMembership. SimpleMembership is a big improvement over traditional ASP.NET Membership. For one thing, rather than forcing a database schema, it can work with your database schema. In the MVC 4 Internet template case, it uses Entity Framework Code First to define the user model. SimpleMembership bootstrap includes a call to InitializeDatabaseConnection, and I want to play nice with that.

There's a new [InitializeSimpleMembership] attribute on the AccountController, which calls \Filters\InitializeSimpleMembershipAttribute.cs::OnActionExecuting(). That comment in that method that says "Ensure ASP.NET Simple Membership is initialized only once per app start" which sounds like good advice. I figured the best thing would be to call that directly:

new Mvc4SampleApplication.Filters.InitializeSimpleMembershipAttribute().OnActionExecuting(null);

I'm not 100% happy with this - in fact, it's my least favorite part of this solution. There are two problems - first, directly calling a method on a filter, while legal, seems odd. Worse, though, the Filter lives in the application's namespace, which means that this code no longer works well as a generic drop-in.

The simplest workaround would be to duplicate the relevant SimpleMembership initialization code into my startup code, but I'd rather not. I'm interested in your suggestions here.

Challenge #6: Module Init methods are called more than once

When debugging, I noticed (and remembered) that the Init method may be called more than once per page request - it's run once per instance in the app pool, and an individual page request can cause multiple resource requests to the server. While SimpleMembership does have internal checks to prevent duplicate user or role entries, I'd rather not cause or handle those exceptions. So here's the standard single-use lock in the Module's init method:

void IHttpModule.Init(HttpApplication context)
{
    lock (lockObject)
    {
        if (!initialized)
        {
            //Do stuff
        }
        initialized = true;
    }
}

Putting it all together

With all of that out of the way, here's the code I came up with:

The Verdict: Is this a good thing?

Maybe.

I think you'll agree that the journey was undoubtedly worthwhile, as it took us through some of the finer points of hooking into application startup, integrating with membership, and understanding why the WebActivator NuGet package is so useful

Will I use this in the tutorial? I'm leaning towards no - I think a NuGet package with a dependency on WebActivator might work better:

  • It's a little more clear what's going on
  • Installing a NuGet package might be a little less error prone than copying a file
  • A novice user could uninstall the package when complete
  • It's a good introduction to NuGet, which is a good thing for beginners to see
  • This code either requires either duplicating a little code from that filter or modifying the file to use the namespace

Honestly I'm undecided at this point, but I'm glad that I can weigh the options.

If you're interested: Why are you doing this?

I'm updating the MVC Music Store tutorial to ASP.NET MVC 4, taking advantage of a lot of new ASP.NET MVC 4 features and trying to simplify areas that are giving people trouble. One change that addresses both needs us using the new OAuth support for membership as much as possible - it's a great new feature from an application perspective, and we get a fair amount of beginners struggling with setting up membership on a variety of database and development setups, which is a distraction from the focus of the tutorial - learning ASP.NET MVC.

Side note: Thanks to some great help from Rick Anderson, we had a draft of the tutorial that was looking pretty good earlier this summer, but there were enough changes in ASP.NET MVC 4 all the way up to RTM that there's still some work to be done. It's high priority and should be out very soon.

The one issue I ran into with OAuth is that we still need an Administrative user who can edit the store's inventory. I thought about a number of solutions for that - making the first user to register the admin, or the first user to use the username "Administrator" is assigned to the Administrator role - but they both ended up requiring extra code; also, I worried that people would use that code without understanding it or thinking about whether it was a good fit.

Posted by Jon Galloway | 1 comment(s)
Filed under: ,

Guest on Cloud Cover Show: What's new in Visual Studio 2012, ASP.NET 4.5, ASP.NET MVC 4 and Windows Azure Web Sites

I was the guest star on the Cloud Cover Show this past week talking about what's new for web developers in Visual Studio 2012, ASP.NET 4.5, ASP.NET MVC 4, and Windows Azure Web Sites. As a remote presenter (I recorded my screencast while at ThatConference in Wisconsin Dells), I was given the floating head treatment when first introduced:

I gave a 20 minute walkthrough, showing the following highlights:

  • File / New Project with ASP.NET 4.5
    • NuGet packages in the default template (and why that's good)
    • Adaptive rendering in the default ASP.NET 4.5 project template
    • A few Visual Studio 2012 web developer features (CSS color picker, fonts, HTML5 snippets)
    • Strongly typed data control
    • Model binding support
    • Note: ASP.NET 4.5 requires .NET 4.5, will be supported in Azure some time after .NET 4.5 GA
  • File / New Project with ASP.NET MVC 4
    • Supports both .NET 4 and .NET 4.5
    • New ASP.NET MVC 4 project types
    • Same template experience as ASP.NET 4.5 Web Forms - adaptive rendering, etc.
    • Code-based configuration moved to App_Start
    • OAuth login support
    • Add new ASP.NET Web API controller
    • Show Web API
  • Deploy MVC 4 Application to Windows Azure Web Sites
    • Create new website in Windows Azure Web Sites portal, download publish profile
    • Visual Studio 2012 Web Publish dialog
    • Publish and demo site

Thanks to Nick and Cory for inviting me on the show. I hope my disembodied head will be invited back on Cloud Cover again soon.

Posted by Jon Galloway | with no comments

ASP.NET 4.5, ASP.NET MVC 4, ASP.NET Web Pages 2, and Visual Studio 2012 for web developers: Part 1

Wow, yesterday was a big day for ASP.NET developers! In addition to some other very cool things, Microsoft announced Visual Studio 2012, ASP.NET 4.5, ASP MVC 4 were released to manufacturing. Hooray! So what now?

Get The Bits

The easiest way to get all the new goodies is to install Visual Studio 2012. You've got a few options there:

We've got the top download links listed for you on the ASP.NET site as well.

Note: Just install what you'll use

As before, my personal recommendation is to just install the Visual Studio components you're expecting to use. If you never do C++ development, installing all the C++ support just means that your install will take longer, take up more space, make service packs take longer to install, increase the Windows Updates you'll encounter, etc. You can always modify the installed features if you need to later. Here's what I'm installing (I'm including Blend because I've been doing a bit of Windows 8 app development - it works with both both XAML and HTML Windows Store apps).

Here's what I've got selected:

Visual Studio 2012 Install

Learning Resources On The New Stuff

There is a ton of new stuff, and it's easy to get overwhelmed. Here's a quick overview of some of the top resources before we dig into specifics:

ASP.NET 4.5

Model Binding and Strongly Typed Data Controls

The Model Binding and Strongly Typed Data Controls in ASP.NET Web Forms are really cool. Damian Edwards (who helped found the Web Forms MVP project before joining the ASP.NET team) and team pulled of an amazing feat: they brought the model binding and strong typing features of ASP.NET MVC into ASP.NET Web Forms in a way that still fits with Web Forms. Essentially, it's something like an object data source approach, but so much smoother.

First, the strongly typed data controls allow you to define a model type for a control. That allows you to replace string-based data binding expressions with strongly typed binding expressions:

Hooray!

Also, notice that the FormView above isn't binding to a data source, it's got methods defined for Select / Insert / Update. The select method looks like this:

public Issue GetIssue([Control("issuesGrid")]int? id)
{
    return _db.Issues.Find(id);
}

The Insert and Update methods take advantage of the binding features in MVC, allowing you to bind to control values, URL and other contextual values, and custom value providers:

public void InsertIssue()
{
    var issue = new Issue();

    TryUpdateModel(issue);

    if (ModelState.IsValid)
    {
        _db.Issues.Add(issue);
        SaveChanges(issue);
    }
}

This eliminates all the tedious and error-prone "this parameter equals that control value, this other parameter equal that other control value, kill me now" type code. Note that TryUpdateModel call (familiar to MVC devs) which will automatically apply any validation rules defined via data annotations on the model class.

I gave a presentation this week at ThatConference looking at the feasibility of mixing ASP.NET Web Forms and MVC in the same project, and my conclusion was that the best way to get started is to get your Web Forms apps on ASP.NET 4.5 so you can start sharing models and converting traditional Web Forms code towards this approach, which is a lot more similar to MVC.

Bundling and Optimization

Bundling and Optimization in ASP.NET 4.5 and ASP.NET MVC 4 is based on an optimization system the MSN team developed called WebGrease. The core has been battle tested (MSN is a top 20 site) and performs really well. The bundling and optimization system optimizes user experience by compressing and combining CSS and JavaScript so your users get a faster experience and you minimize your bandwidth.

You'll see default bundles defined in \App_Start\BundleConfig.cs in an ASP.NET 4.5 Web Forms or ASP.NET MVC 4 application. Here's what it looks like in Web Forms:

public static void RegisterBundles(BundleCollection bundles)
{
    bundles.Add(new ScriptBundle("~/bundles/WebFormsJs").Include(
          "~/Scripts/WebForms/WebForms.js",
          "~/Scripts/WebForms/WebUIValidation.js",
          "~/Scripts/WebForms/MenuStandards.js",
          "~/Scripts/WebForms/Focus.js",
          "~/Scripts/WebForms/GridView.js",
          "~/Scripts/WebForms/DetailsView.js",
          "~/Scripts/WebForms/TreeView.js",
          "~/Scripts/WebForms/WebParts.js"));

    bundles.Add(new ScriptBundle("~/bundles/MsAjaxJs").Include(
        "~/Scripts/WebForms/MsAjax/MicrosoftAjax.js",
        "~/Scripts/WebForms/MsAjax/MicrosoftAjaxApplicationServices.js",
        "~/Scripts/WebForms/MsAjax/MicrosoftAjaxTimer.js",
        "~/Scripts/WebForms/MsAjax/MicrosoftAjaxWebForms.js"));

    // Use the Development version of Modernizr to develop with and learn from. Then, when you’re
    // ready for production, use the build tool at http://modernizr.com to pick only the tests you need
    bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
        "~/Scripts/modernizr-*"));
}

Now you can just use any of those bundles in your application:

 <asp:PlaceHolder runat="server">        
         <%: Scripts.Render("~/bundles/modernizr") %>
         <%: Scripts.Render("~/bundles/jquery") %>
         <%: Scripts.Render("~/bundles/jqueryui") %>
</asp:PlaceHolder>

One of my favorite parts about this is that we can make bundles that accomodate version numbers in script names, so updating jQuery (maybe via NuGet if you're awesome) doesn't require *any* code / markup changes:

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
            "~/Scripts/jquery-{version}.js"));

bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
            "~/Scripts/jquery-ui-{version}.js"));

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
            "~/Scripts/jquery.unobtrusive*",
            "~/Scripts/jquery.validate*"));

For more on using Bundling and Minification in Web Forms, see Adding Bundling and Minification to Web Forms (Rick Anderson) or either of the following videos:

Quick intro by Scott Hanselman:

Deep Dive by Howard Dierking:

Updated Project Templates (Adaptive Rendering)

Both the new ASP.NET Web Forms and MVC project templates have been redesigned. They don't just look nicer, they leverage web standards to automatically adapt to screen resolution (HTML and CSS only, no JavaScript or server-side code required).

Here's how the default template looks in a wide screen (> 850px):

2012-08-16_16h50_39

Resizing the screen automatically applies new styles via CSS media queries so it's easier to read and navigate:

2012-08-16_16h50_47

I wrote about how this works in pretty gory detail in the context of ASP.NET MVC 4, but it's working exactly the same in ASP.NET Web Forms 4.5.

OAuth and OpenID support

The default project templates now have built-in support for user registration and log in via OAuth and OpenID. They're making use of the excellent DotNetOpenAuth library, included as  a NuGet package so you can update later if you'd like.

Your OAuth and OpenID providers are registerd in \AppStart\AuthConfig.cs. Initially there are some examples that are all commented out (this is something you should do explicitly, and OAuth providers require you fill in an app id and app secret):

public static void RegisterOpenAuth()
{
    // See http://go.microsoft.com/fwlink/?LinkId=252803 for details on setting up this ASP.NET
    // application to support logging in via external services.

    //OpenAuth.AuthenticationClients.AddTwitter(
    //    consumerKey: "your Twitter consumer key",
    //    consumerSecret: "your Twitter consumer secret");

    //OpenAuth.AuthenticationClients.AddFacebook(
    //    appId: "your Facebook app id",
    //    appSecret: "your Facebook app secret");

    //OpenAuth.AuthenticationClients.AddMicrosoft(
    //    clientId: "your Microsoft account client id",
    //    clientSecret: "your Microsoft account client secret");

    //OpenAuth.AuthenticationClients.AddGoogle();
}

Uncommenting and filling in the key / secret information for OAuth clients changes your Log In screen to allow users to access your site as members without creating an account:

2012-08-16_16h59_15

For more information on configuring specific clients, see Pranav's blog post: OAuth/OpenID Support for WebForms, MVC and WebPages.

And much more...

There's of course a lot more, these are just some of my favorite features. Let's move on to ASP.NET MVC 4!

ASP.NET MVC

Mobile Features

ASP.NET MVC 4 has several great options to help you build sites that work well on mobile devices. Here's a diagram that helps illustrate it:

2012-08-16_19h10_27

I talked about all three of these and overviewed ASP.NET MVC 4 mobile features at aspConf:

We've already talked about adaptive rendering in Web Forms, it works the same here.

Display Modes allow you to create views which are served to mobile devices, and you can create your own display modes to target specific devices. Since the display modes are defined in code, they can be based on any logic you want - database queries, user cookies, day of the week, whatever. Here's how a display mode is defined:

DisplayModeProvider.Instance.Modes.Insert(0, new 
DefaultDisplayMode("iPhone") 
{ 
    ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf 
        ("iPhone", StringComparison.OrdinalIgnoreCase) >= 0) 
 });

Finally, the mobile template (based on jQuery Mobile) makes it easy to create web applications that are optimized for mobile users.

To learn more about what you can do using the Mobile Project Template, see Rick Anderson's tutorial: ASP.NET MVC 4 Mobile Features.

K. Scott Allen did a great presentation on the Mobile Project Template and jQuery Mobile at NDC 2012:

Scott Allen - ASP.NET MVC and jQuery Mobile from NDCOslo on Vimeo.

Async Support

ASP.NET MVC has had async support since MVC 2, but it was hard. It gets a lot easier in MVC 4 due to async and await. Once again, I'll refer to Rick Anderson's excellent tutorial: Using Asynchronous Methods in ASP.NET MVC 4. Here's an example of an async controller method that calls three long running services and returns to the user when all three are complete:

public async Task<ActionResult> PWGasync() 
{ 
    ViewBag.SyncType = "Asynchronous"; 
    var widgetService = new WidgetService(); 
    var prodService = new ProductService(); 
    var gizmoService = new GizmoService(); 
 
    var widgetTask = widgetService.GetWidgetsAsync(); 
    var prodTask = prodService.GetProductsAsync(); 
    var gizmoTask = gizmoService.GetGizmosAsync(); 
 
    await Task.WhenAll(widgetTask, prodTask, gizmoTask); 
 
    var pwgVM = new ProdGizWidgetVM( 
       widgetTask.Result, 
       prodTask.Result, 
       gizmoTask.Result 
       ); 
 
    return View("PWG", pwgVM); 
}

OAuth and OpenID support

Yes, already mentioned before in Web Forms, but it's also in MVC 4, and it's really cool.

The ASP.NET MVC 4 Release Notes cover these and other features in more detail.

ASP.NET Web API

ASP.NET Web API is officially released! I did a series of screencasts earlier this year that introduce ASP.NET Web API. They're slightly out of date on a few technical details (I'll be updating them soon) but explain what it is and why you'd use it; here's the first in the series:

[Video and code on the ASP.NET site]

The team wrote some great posts on recent features:

Wow, that's a lot, and we didn't even get into Visual Studio 2012 features for Web Developers! Looks like it's time for a break, with a part 2 to follow...

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

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

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

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

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

These are very bad approaches, for two important reasons:

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

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

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

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

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

Step Zero: Do you need to customize anything?

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

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

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

Quick Note: Authentication and Authorization

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

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

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

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

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

A simple key based AuthorizeAttribute

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

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

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

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

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

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

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

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

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

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

Handling Authorization Failures

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

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

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

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

Many more examples

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

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

Subclass AuthorizeAttribute or Implement FilterAttribute, IAuthorizationFilter?

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

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

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

Using AuthorizeAttribute with ASP.NET Web API

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

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

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

Fluent Security

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

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

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

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

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

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

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

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

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

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

Extending the Forms Authentication provider

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

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

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

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

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

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

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

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

The important points here:

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

The ASP.NET Roles and Membership System

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

ASP.NET Membership

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

ASP.NET Role Management

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

Customizing Membership in ASP.NET

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

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

Implementing your own Membership Provider

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

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

Simple Membership

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

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

Wrapping Up

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

For further study:

Posted by Jon Galloway | 4 comment(s)
Filed under: ,

Upcoming Web Camps

We've got some great, free Web Camps headed your way!

Web Camps are free, fun, no-fluff events for developers, by developers. Show up for the day, leave infused with a crazy amount of web dev info. Did I mention these are free?

My teammate Brady Gaster has put together some phenomenal new content, and I'm really looking forward to presenting at some of these.

Web Camps Locations

So far the following locations have been announced:

Location Date Registration Notes
Brussels, Belgium 3-May-12 Register Here With Brady Gaster and Matthew Osborn... and there's still room!
Waltham, MA 10-May-12 Register Here I'll be here! Also starring Chris Bowen and Jim O'Neil!
Mountain View, CA 14-May-12 Register Here With the amazing Doris Chen!
Denver, CO 18-May-12 Register Here Also Doris Chen!
Phoenix, AZ 25-May-12 Register Here Also Doris Chen! Wow, she's busy!
Mountain View, CA 29-May-12 Register Here I'll be here! Maybe someone else, too.

There are a bunch more that are in the works but not quite ready to be announced yet - I'll update here, but the best place to keep up to date is at http://www.devcamps.ms/web

Oh, and I believe there's still room at the Web Camp in Brussels on May 3.

Web Camps Content

I've reviewed and contributed a bit to the Web Camps content that Brady's put together, and it's really, really good. There's a ton of information packed in. Here's an overview of the agenda (see the registration link for the exact agenda at each location):

  • Welcome Back to the Microsoft Web Stack
  • Integrating Your Site with Internet Explorer 9
  • Top 10 Things You Didn't Know about WebMatrix 2
  • Creating Rich HTML 5 Experiences
  • Building Web Sites Using ASP.NET 4.5
  • Building a Service Layer with ASP.NET Web API
  • Deploying ASP.NET Apps to the Cloud

You can read more about those topic at http://www.devcamps.ms/web/agenda.

Infomercial!

Now if you're almost convinced, but on the edge, and you need a video to push you over the top, you watch Brady and me announcing the Web Camps tour on Web Camps TV a few weeks ago:

Yes, if you read my blog you'll have noticed that this video is a repeat. That's how infomercials work.

Posted by Jon Galloway | with no comments
Filed under:
More Posts Next page »