Jon Galloway

5 Tricks for catching up on the Channel 9 event videos for Build 2014

Okay, you've had a week to digest all the video content from Build 2014? Done yet? Me, neither. Well, how about some tricks to make this easier?

I'd written up a few tips and tricks for catching up on Channel 9 event videos back in 2011, this is an update circa 2014.

Trick 1: Subscribe and watch at high speed in VLC

There are a lot of sessions, and watching even at 10% faster makes a difference. I think you'll be surprised at how, with a little practice, you can keep cranking the speed up and absorb the content at 2x or even faster. Note: Every time I tell people about high speed playback, people assume it's going to make the speakers sound like chipmunks. All of the high speed playback options I'm going to show are pitch corrected, so they don't raise the speakers' voices.

If you don't have VLC installed, I highly recommend it. It's lightweight and has a minimal interface, but is packed with codecs and advanced features when you need them. You can install via Chocolatey (cinst vlc), directly from http://www.videolan.org/, or from http://ninite.com.

Run VLC and pop into Playlist mode. You can do that from the View menu, hit Ctrl+L, or click on the Playlist icon at the bottom to do that.

2011-04-21 16h47_08

In the Playlist interface, expand the Internet group and click on + sign to the right of Podcasts.

2014-04-15_14h59_04

This brings up a prompt to enter the URL for the feed. Each Channel 9 event has a list of formats available under the "Subscribe to this event" link:

Channel 9 Event - RSS

You have a few options (the types are obvious from the last bit of the URL):

You can enter the format of your choice here - in my case I'm going to pick the MP4 HD feed: http://channel9.msdn.com/Events/Build/2014/RSS/mp4high. However, note that the MP3 format is available. We'll get back to that later.

That grabs the feed and builds a playlist for us, listing all the videos.

Note: nothing's been downloaded at this point, it's just showing the list from the RSS feed.

2014-04-15_15h06_24

Now I'll use the search section to filter on ASP.NET because I do love it so.

2014-04-15_15h16_09

Here's the key thing - when I double click the video to start streaming it, I'll switch to a faster speed. There are two ways to do that.

The easy way is to use the Playback / Speed menu.

2014-04-15_15h19_24

Once you get hooked on this, though, you can use the [ and ] hotkeys (speed up and slow down respectively). Now I'm watching this demo at 2x speed. You might start with 1.5x or so and crank it up as you get more used to it.

2014-04-15_15h20_16

Trick 2: Use high speed playback in the Channel 9 player

HTML5 video players in all the new browsers support high speed playback. Here's an example showing the Day 1 Keynote on the Channel 9 site; I've right clicked the video to bring up the context menu and I'm about to kick it up to 2x.

2014-04-15_15h24_19

That's it! Easy!

Trick 3: Subscribe to the MP3 feed on Windows Phone 8.1

One of my favorite sleeper features in Windows Phone 8.1 is support for high speed playback in the new Podcasts app. For this one, I wanted to add the MP3 URL for just the Build 2014 event: http://channel9.msdn.com/Events/Build/2014/RSS/mp3

But that's a bit long to type on the phone, so I made a special short URL: http://aka.ms/b14mp3

Then in the Podcasts app, I chose add by URL:

wp_ss_20140415_0002

That gave me a list of MP3's. In the podcast options, I can select to have it stream or download them. Now, once I started playing one, I clicked on the little 1.5x thing to the right of the video twice, toggling to 2x speed.

 wp_ss_20140415_0001

Yee haw!!!

Notes:

  • David Tesar reminded me that the Moliplayer video player app for Windows Phone has variable speed playback.
  • There are high speed playback options for other phones, too. On Android, the Astro Player app has great support for variable speed playback.

Trick 4: Downloading videos using a script

In the past, I've published some Powershell scripts for bulk downloading Channel 9 videos. Here' s one, updated for Build 2014. But don't run it just yet, because I think I've found a better options, which I'll show you next.

 

Trick 5: Downloading videos using a smarter script

That's fine, but it's kind of heavy handed. Let's be honest, have you actually watched all of the videos from an event before? It's more likely that you'll want to pick some based on the topic. I found a great site that builds customized feeds based on the session tags: http://dayngo.com/channel9/Events/a99db53e-aa3d-4089-9859-a2fe017ca357/Build_2014 

Disclaimer: This is some random site I found on the internet. Works on my machine. It does generate scripts, so you can see what it's doing.

Here I've filtered to show events tagged with ASP.NET, Web API, and Node.js.

2014-04-15_15h54_54

Clicking the download button lets me select the formats I want to download.

2014-04-15_15h56_40

That generates a custom PowerShell script (WGET is also an option) with just the content I picked:

$overwrite = $false
$webClient = New-Object System.Net.WebClient 
$feeds =  (("Take_Your_Solution_Worldwide_from_the_Start_with_Bing_Translator.mp4","http://video.ch9.ms/sessions/build/2014/2-656_LG.mp4"),("Continuous_Delivery_and_Continuous_Integration_with_Visual_Studio_Online_and_Microsoft_Azure.mp4","http://video.ch9.ms/sessions/build/2014/3-584_LG.mp4"),("What_s_New_for_ASP_NET_and_Web_in_Visual_Studio_2013_Update_2_and_Beyond.mp4","http://video.ch9.ms/sessions/build/2014/3-602_LG.mp4"),("Building_Web_APIs_for_Mobile_Apps_Using_ASP_NET_Web_API_2_1.mp4","http://video.ch9.ms/sessions/build/2014/3-603_LG.mp4"),("Deep_Dive_Improving_Performance_in_Your_ASP_NET_App.mp4","http://video.ch9.ms/sessions/build/2014/3-605_LG.mp4"),("Powerful_Mobile_Apps_with_Mobile_Services_and_ASP_NET_Web_API.mp4","http://video.ch9.ms/sessions/build/2014/3-623_LG.mp4"),("Using_Node_js_and_Python_in_Visual_Studio_and_on_Azure.mp4","http://video.ch9.ms/sessions/build/2014/3-631_LG.mp4"),("Building_a_Single_Page_Application_with_ASP_NET_and_AngularJS.mp4","http://video.ch9.ms/sessions/build/2014/3-644_LG.mp4"))  
$entries = $feeds.Length
$progress = 0 
$pagepercent = 0 
$dir = get-location
foreach ($item in $feeds){
    $name,$link = $item
    $saveFileName = join-path $dir $name
    if ((-not $overwrite) -and (Test-Path -path $saveFileName))     
    {        
        write-progress -activity "$saveFileName already downloaded" -status "$pagepercent% ($progress / $entries) complete" -percentcomplete $pagepercent    
    }    
    else     
    {        
        write-progress -activity "Downloading $saveFileName" -status "$pagepercent% ($progress / $entries) complete" -percentcomplete $pagepercent       
        &{#TRY
            $webClient.DownloadFile($link, $saveFileName)
        }
        trap [Exception]{
            write-host
            write-host ("Unable to download " + $saveFileName)
            continue; 
        }
    }    
    $pagepercent = [Math]::floor((++$progress)/$entries*100) 
}

 

Hope these tips help. Get to work!

Posted by Jon Galloway | with no comments

Looking at ASP.NET MVC 5.1 and Web API 2.1 - Part 4 - Web API Help Pages, BSON, and Global Error Handling

This is part 4 of a series covering some of the new features in the ASP.NET MVC 5.1 and Web API 2.1 releases. The last one! If you've read them all, you have earned twelve blog readership points... after you finish this one, of course. Here are the previous posts:

The sample project covering the posts in this series is here; other referenced samples are in the ASP.NET sample repository.

As a reminder, Part 1 explained that ASP.NET MVC 5.1 / Web API 2.1 is a NuGet update for the MVC 5 / Web API 2 releases that shipped with Visual Studio 2013. There will be a Visual Studio update that will make them the defaults when you create new projects.

In this post, we'll look at new features in ASP.NET Web API 2.1.

Attribute Routing

We already looked at the updates to Attribute Routing improvements for both ASP.NET Web API and MVC in the second post in this series, I just want to call it out again since this post is overviewing all of the other new features in ASP.NET Web API 2.1 and the Attribute Routing support for custom constraints is one of the top features in the ASP.NET Web API 2.1 release.

As a reminder, custom route constraints make it really easy to create wrap route matching logic in a constraint which can then be placed on ApiControllers or actions like this:

[VersionedRoute("api/Customer", 1)]
public class CustomerVersion1Controller : ApiController
{
    // controller code goes here
}
[VersionedRoute("api/Customer", 2)]
public class CustomerVersion2Controller : ApiController
{
    // controller code goes here
}

In that example, the custom VersionedRoute constraint looks for an api-version header and forwards the request to the correct controller. See the post for more information, including a link to the sample application.

Help Page improvements

Okay, let's dig into some of the cool new features we haven't seen yet. To start with, I'm going to scaffold out a new PersonApiController using the same Person class I've used earlier in this series, shown below:

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 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
}

And we're using the standard Web API scaffolding:

2014-01-30_16h11_27

Nothing has really changed for the top level ASP.NET Web API Help Page - you get a generated list of API calls for each API Controller.

2014-02-12_23h20_49

What has changed is what you see when you click through on one of the API calls, e.g. the PersonApi GET method. Here's how that looked in ASP.NET Web API 2.1:

2014-02-17_13h40_46

It shows sample data in JSON and XML, and you can kind of guess what they are if you've named your model properties well, but there's no information on type, model attributes, validation rules, etc.

Here's how it looks in ASP.NET Web API 2:

2014-02-17_13h41_45

The Response Formats section hasn't changed, but now we have a Resource Description area at the top. Let's take a closer look at that:

2014-02-17_13h53_18

Here we're clearly displaying both the type and validation rules.

Note that the Salutation type is hyperlinked, since it's using our custom Salutation enum. Clicking through shows the possible values for that enum:

2014-02-17_13h47_37

If you've done any work integrating with API's that had minimal or out of date documentation, hopefully the value of the above is really clear. What's great is that this is generated for me at runtime, so it's always up to date with the latest code. If my Web API is in production and I add a new Enum value or change a validation rule, the live documentation on the web site is immediately updated without any work or extra thought on my part as soon as I deploy the code.

Short detour: Filling in Descriptions using C# /// Comments

Now that we've got documentation for our model types, it's clear that we could improve it a bit. The most obvious thing is that there's no provided description. That's easy to add using C# /// comments (aka XML Comments). ASP.NET Web API Help Pages have had support for /// comments documentation for a while, it just hasn't been this obvious.

The ASP.NET Web API Help Pages are implemented in a really clear, open model: it's all implemented in an ASP.NET MVC Area within your existing site. If you're not familiar with ASP.NET MVC Areas, they're a way to allow you to segment your applications into with separate routes, models, views and controllers but still keep them in the same project so it's easier to manage, share resources, etc.

Here's the Help Page Area within the sample project we're working on:

2014-02-17_14h36_48

1. In the above screenshot, I've highlighted the \App_Start\HelpPageConfig.cs file because that's where we're going to set up the XML comments. There's a Register method right at the top with the following two lines:

//// Uncomment the following to use the documentation from XML documentation file.
//config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));

So to use that, we'll uncomment the second line, just as the instructions say.

2. Note that the comments are pointing to an XmlDocument.xml file. We need to check a box in the project settings to generate that XML file as shown below.

2014-02-17_14h46_38

That's it!

Once that's done, I'm going to throw the /// comments on the controller methods and model properties and generate XML comments. I used GhostDoc to generate the comments, then cleaned them up and editorialized a bit.

/// <summary>
/// This is an example person class. It artisanally crafted by a
/// bearded, bespeckled craftsman after being lovingly sketched
/// in a leather bound notebook with charcoal pencils.
/// </summary>
public class Person
{
    [ScaffoldColumn(false)]
    public int Id { get; set; }
    /// <summary>
    /// This uses a custom salution enum since there's apparently no ISO standard.
    /// </summary>
    /// <value>
    /// The person's requested salutation.
    /// </value>
    [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; }
    /// <summary>
    /// This is the person's actual or desired age.
    /// </summary>
    /// <value>
    /// The age in years, represented in an integer.
    /// </value>
    public int Age { get; set; }
}

And here's the updated help page with the descriptions:

2014-02-17_15h04_16

There are a ton of other features in the HelpPageConfig - you could pull your documentation from a database or CMS, for example. And since it's all implemented in standard ASP.NET MVC, you can modify the views or do whatever else you want. But it's nice to have these new features available out of the box.

BSON

BSON is a binary serialization format that's similar to JSON in that they both store name-value pairs, but it's quite different in how the data is actually stored. BSON serializes data in a binary format, which can offer some performance benefits for encode / decode / traversal.  It's been possible to hook up a custom BSON formatter in ASP.NET Web API before; Filip and others have written comprehensive blog posts describing how to do just that. It's even easier now - both for clients and servers - since the BSON formatter is included with ASP.NET Web API.

Important note: BSON isn't designed to be more compact than JSON, in fact it's often bigger (depending on your data structure and content). That's because, unlike JSON, BSON embeds type information in the document. That makes for fast scan and read, but it's holding more data than the equivalent JSON document. That means that it will be faster in some cases, but it may be slower in other cases if your messages are bigger. This shows the value of content negotiation and flexible formatters in ASP.NET Web API - you can easily try out different formatters, both on the client and server side, and use the best one for the job.

I'll look at two examples here.

Testing BSON with a text-heavy model

For the first example, I'll use the Person class we've been using for our previous examples. I'd like to have a lot more people in my database. I grabbed some absolutely silly code I wrote 7 years ago that generates fake surnames (Generate random fake surnames) and added a controller action to slam 500 new people with a first name of Bob but a random last name and age into the database. Then I clicked on it a few times.

2014-02-17_16h19_50

Turning on the BSON formatter is just a one line code change:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Formatters.Add(new BsonMediaTypeFormatter());
        // ...
    }
}

Now whenever a client sends an Accept header for application/bson, they'll get the data in BSON format. For comparison, I'm making two requests in Fiddler. Here's a request with no Accept header specified, so we get JSON:

2014-02-18_00h48_12

The content-length there is 118,353 bytes.

Now I'm setting an Accept header with application/bson:

2014-02-18_00h51_19

Notice that this BSON request is 134,395 bytes, or 13% larger. I've marked some of the type identifiers in there, but you can see there are a lot more since they're lined up in columns.

Place your bets: think the faster BSON serializer will be faster, despite the larger payload size? Before we answer that, we'll add in a second scenario that replaces our text-heavy Person class with a quite exciting BoringData class that's mostly numeric and binary data:

public class BoringData
{
    public int Id { get; set; }
    public long DataLong { get; set; }
    public byte[] DataBytes { get; set; }
    public DateTime DataDate { get; set; }
}

And here's the test we'll throw at both of these:

private HttpClient _client = new HttpClient();
static void Main(string[] args)
{
    try
    {
        Console.WriteLine("Hit ENTER to begin...");
        RunAsync().Wait();
    }
    finally
    {
        Console.WriteLine("Hit ENTER to exit...");
        Console.ReadLine();
    }
}
private async static Task RunAsync()
{
    using (HttpClient client = new HttpClient())
    {
        await RunTimedTest<BoringData>(client, new JsonMediaTypeFormatter(), "http://localhost:29108/api/BoringDataApi", "application/json");
        await RunTimedTest<BoringData>(client, new BsonMediaTypeFormatter(), "http://localhost:29108/api/BoringDataApi", "application/bson");
        await RunTimedTest<Person>(client, new JsonMediaTypeFormatter(), "http://localhost:29108/api/PersonApi", "application/json");
        await RunTimedTest<Person>(client, new BsonMediaTypeFormatter(), "http://localhost:29108/api/PersonApi", "application/bson");
    }
}
public static async Task RunTimedTest<T>(HttpClient _client, MediaTypeFormatter formatter, string Uri, string mediaHeader)
{
    int iterations = 500;
    _client.DefaultRequestHeaders.Accept.Clear();
    _client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(mediaHeader));
    MediaTypeFormatter[] formatters = new MediaTypeFormatter[] { formatter };
    var watch = Stopwatch.StartNew();
    for (int i = 0; i < iterations; i++)
    {
        var result = await _client.GetAsync(Uri);
        var value = await result.Content.ReadAsAsync<T[]>(formatters);
    }
    Console.WriteLine("Format: {0,-20} Type: {1,-15}\t Time (s):{2,10:ss\\.fff}", mediaHeader, typeof(T).Name, watch.Elapsed);
}

The BoringDataApi controller's GET method returns lots of data, as you'd expect:

public class BoringDataApiController : ApiController
{
    static Random rng = new Random(Guid.NewGuid().GetHashCode());
    public IEnumerable<BoringData> GetBoringData()
    {
        return GetLotsOfBoringData(100);
    }
    private IEnumerable<BoringData> GetLotsOfBoringData(int quantity)
    {
        byte[] buf1 = new byte[10000];
        byte[] buf2 = new byte[64];

        for (int i = 1; i < quantity; i++)
        {
            rng.NextBytes(buf1);
            rng.NextBytes(buf2);
            yield return new BoringData
            {
                Id  = i,
                DataBytes = buf1,
                DataDate = DateTime.UtcNow,
                DataLong = BitConverter.ToInt64(buf2,0)
            };
        }
    }
}

So, big picture, the test harness will run 500 end to end tests on both controllers, requesting both Person and BoringData as both JSON and BSON. What we're not comparing is the difference between the Person and BoringData responses, we're just looking for some general trends to see if BSON is faster than JSON for a mostly-textual and mostly-binary model. Yes, Kelly Sommers will beat me up for this, and I'm okay with that. My goal is to get some basic guidelines on when BSON works better than JSON.

The real point here is that you won't know how your API or a specific content type will perform until you test it.

So how'd we do?

2014-02-18_17h13_33

In this case (and I ran this test many times with the same general result) BSON was a lot faster for mostly binary/numeric data, and a little slower for mostly textual data. In this pretty random example, BSON was 140% faster for the mostly binary case and and 21% slower for the mostly-textual case. That's because both serialize textual data to UTF-8, but BSON includes some additional metadata.

So, very generally speaking, if your service returns a lot of binary / numeric / non-textual data, you should really look at BSON. If you're looking for a silver bullet, you may have to pony up for some silver.

Easier implementations due to BaseJsonMediaTypeFormatter

Yes, that's the most boring heading you'll ever see. But it's hopefully true. The new BaseJsonMediaTypeFormatter has been designed to make it easier to implement new different serialization formats easier, since the the internal JSON formatters have been redesigned to make it easier to extend. I asked Doug, the dev that did most of the work for this BSON update, about his commit message saying recent changes will make it easier to make other formatters like MessagePack happen and he said:

Yes.  BaseJsonMediaTypeFormatter introduces a few Json.Net types and concepts.  But it also provides solid and reusable async wrappers around easier-to-implement sync methods.

The main thing I've noticed there is the common BaseJsonMediaTypeFormatter. There's not a whole lot of code in the BsonMediaTypeFormatter, since a lot of it's in the common base and in other support classes.

And while I'm mentioning MessagePack, I think it's another great option that's really worth looking at, since (unlike BSON) MessagePack is designed for small message size. There's a MsgPack formatter available now in the WebApiContrib formatters collection, and Filip Woj. wrote a nice blog post overview here: Boost up your ASP.NET Web API with MessagePack.

Global Error Handling

The last feature we'll look at is Global Error Handling. The name's pretty self-descriptive: it lets you register handlers and loggers which will respond to any unhandled exceptions across your entire Web API application.

Global error handling is especially useful in Web API because of the way the parts are so loosely coupled and composable - you've got all kinds of different handlers and filters, wired together with a very configurable system that encourages dependency injection... There's a lot going on.

ASP.NET Web API Poster

Note: You can download the PDF of this poster from the ASP.NET site.

That provides you tons of flexibility when you're building HTTP services, but it can make it hard to find out what's wrong when there's a problem. Exception filters help, but as David Matson notes, they don't handle:

  1. Exceptions thrown from controller constructors
  2. Exceptions thrown from message handlers
  3. Exceptions thrown during routing
  4. Exceptions thrown during response content serialization

I recommend David Matson's Web API Global Error Handling wiki article entry in the ASP.NET repository for more information on design and technical implementation. The short excerpt is that you can register one IExceptionHandler and multiple IExceptionLogger instances in your application, and they'll respond to all Web API exceptions.

There's already a pretty clear sample in the Web API samples which shows a GenericTextExceptionHandler (which returns a generic exception message for unhandled exceptions) and an ElmahExceptionLogger (which implements logging using the popular ELMAH logging system). I've been trying to come up with some other use cases, but I think they captured the main ones here - usually if you have an unhandled exception, you want to log it and make sure you return some sort of useful message to your client.

Both of these interfaces are really simple - they both have a single async method (LogAsync and HandleAsync, respectively) which are passed an ExceptionContext and a CancellationToken.

public interface IExceptionLogger
{
    Task LogAsync(ExceptionLoggerContext context, CancellationToken cancellationToken);
}
public interface IExceptionHandler
{
    Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken);
}

The ExceptionContext includes the exception as well as a lot of other useful context information:

  • Exception (Exception)
  • Request (HttpRequestMessage)
  • RequestContext ()
  • ControllerContext (HttpControllerContext)
  • ActionContext (HttpActionContext)
  • Response (HttpResponseMessage)
  • CatchBlock (string)
  • IsTopLevelCatchBlock (bool)

They're registered in your WebApiConfig like this:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
        // There can be multiple exception loggers. (By default, no exception loggers are registered.)
        config.Services.Add(typeof(IExceptionLogger), new ElmahExceptionLogger());
        // There must be exactly one exception handler. (There is a default one that may be replaced.)
        // To make this sample easier to run in a browser, replace the default exception handler with one that sends
        // back text/plain content for all errors.
        config.Services.Replace(typeof(IExceptionHandler), new GenericTextExceptionHandler());
    }
}

There are a few areas to possibly add to, but I'm going to pass on actually implementing them so I can get this series wrapped before ASP.NET Web API 2.2 ships. Maybe an exercise for the reader?

Damien (damienbod) has a nice overview of Web API Exception handling, complete with a lot of references: Exploring Web API Exception Handling

More features to read about

We've looked at several of the top features in this release, but there are a lot more. Here's a list with links to the documentation:

ASP.NET MVC 5.1

ASP.NET Web API 2.1

ASP.NET Web Pages 3.1

Hope you enjoyed the series. As a reminder, you can grab the source for my samples here and the official ASP.NET / Web API samples in the ASP.NET sample repository.

Posted by Jon Galloway | with no comments

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: ,

Looking at ASP.NET MVC 5.1 and Web API 2.1 - Part 2 - Attribute Routing with Custom Constraints

I'm continuing a series looking at some of the new features in ASP.NET MVC 5.1 and Web API 2.1. Part 1 (Overview and Enums) explained how to update your NuGet packages in an ASP.NET MVC application, so I won't rehash that here.

The sample project covering the posts in this series is here; other referenced samples are in the ASP.NET sample repository.

In this post, we'll look at improvements to attribute routing for both ASP.NET MVC and ASP.NET Web API. First, a quick review of what routing constraints are used for.

Intro to Routing Constraints

ASP.NET MVC and Web API have both offered both simple and custom route constraints since they first came out. A simple constraint would be something like this:

routes.MapRoute("blog", "{year}/{month}/{day}",
    new { controller = "blog", action = "index" },
    new { year = @"\d{4}", month = @"\d{2}", day = @"\d{2}" });

In the above case, "/2014/01/01" would match but "/does/this/work" would not since the values don't match the required pattern.  If you needed something more complex than a simple pattern match, you'd use a custom constraint by implementing IRouteConstraint and defining the custom logic in the Match method - if it returns true, the route is a match.

public interface IRouteConstraint
{
    bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection);
}

Route Constraints in Attribute Routing

One of the top new features in ASP.NET MVC 5 and Web API 2 was the addition of Attribute Routing. Rather than defining all your routes in /App_Start/RouteConfig.cs using a series of routes.MapRoute() calls, you can define routes using attributes on your controller actions and controller classes. You can take your pick of whichever works better to you: continue to use traditional routing, use attribute routing instead, or use them both.

Attribute routing previously offered custom inline constraints, like this:

[Route("temp/{scale:values(celsius|fahrenheit)}")]

Here, the scale segment has a custom inline Values constraint which will only match if the the scale value is in the pipe-delimited list, e.g. this will match temp/celsius and /temp/fahrenheit but not /temp/foo. You can read more about the Attribute Routing features that shipped with ASP.NET MVC 5, including inline constraints like the above, on this post by Ken Egozi: Attribute Routing in ASP.NET MVC 5.

While inline constraints allow you to restrict values for a particular segment, they're both a little limited (e.g. they can't operate over the entire URL, and some more complex thing that aren't possible at that scope). To see more about what changed and why, see the issue report and changed code for this commit.

Now with ASP.NET MVC 5.1, we can create a new attribute that implements a custom route constraint. Here's an example.

ASP.NET MVC 5.1 Example: Adding a custom LocaleRoute

Here's a simple custom route attribute that matches based on a list of supported locales.

First, we'll create a custom LocaleRouteConstraint that implements IRouteConstraint:

public class LocaleRouteConstraint : IRouteConstraint
{
	public string Locale { get; private set; }
	public LocaleRouteConstraint(string locale)
	{
		Locale = locale;
	}
	public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
	{
		object value;
		if (values.TryGetValue("locale", out value) && !string.IsNullOrWhiteSpace(value as string))
		{
			string locale = value as string;
			if (isValid(locale))
			{
				return string.Equals(Locale, locale, StringComparison.OrdinalIgnoreCase);
			}
		}
		return false;
	}
	private bool isValid(string locale)
	{
		string[] validOptions = "EN-US|EN-GB|FR-FR".Split('|') ;
		return validOptions.Contains(locale.ToUpper());
	}
}

IRouteConstraint has one method, Match. That's where you write your custom logic which determines if a set of incoming route values, context, etc., match your custom route. If you return true, routes with this constraint are eligible to respond to the request; if you return false the request will not be mapped to routes with this constraint.

In this case, we've got a simple isValid matcher which takes a locale string (e.g. fr-fr) and validates it against a list of supported locales. In more advanced use, this may be querying against a database backed cache of locales your site supports or using some other more advanced method. If you are working with a more advanced constraint, especially a locale constraint, I recommend Ben Foster's article Improving ASP.NET MVC Routing Configuration.

It's important to see that the real value in this case is running more advanced logic than a simple pattern match - if that's all you're doing, you could use a regex inline route constraint (e.g. {x:regex(^\d{3}-\d{3}-\d{4}$)}).

Now we've got a constraint, but we need to map it to an attribute to use in attribute routing. Note that separating constraints from attributes gives a lot more flexibility - for instance, we could use this constraint on multiple attributes.

Here's a simple one:

public class LocaleRouteAttribute : RouteFactoryAttribute
{
	public LocaleRouteAttribute(string template, string locale)
		: base(template)
	{
		Locale = locale;
	}
	public string Locale
	{
		get;
		private set;
	}
	public override RouteValueDictionary Constraints
	{
		get
		{
			var constraints = new RouteValueDictionary();
			constraints.Add("locale", new LocaleRouteConstraint(Locale));
			return constraints;
		}
	}
	public override RouteValueDictionary Defaults
	{
		get
		{
			var defaults = new RouteValueDictionary();
			defaults.Add("locale", "en-us");
			return defaults;
		}
	}
}

Now we've got a complete route attribute we can place on a controller or action:

using System.Web.Mvc;
namespace StarDotOne.Controllers
{
    [LocaleRoute("hello/{locale}/{action=Index}", "EN-GB")]
    public class ENGBHomeController : Controller
    {
        // GET: /hello/en-gb/
        public ActionResult Index()
        {
            return Content("I am the EN-GB controller.");
        }
    }
}

And here's our FR-FR controller:

using System.Web.Mvc;
namespace StarDotOne.Controllers
{
    [LocaleRoute("hello/{locale}/{action=Index}", "FR-FR")]
    public class FRFRHomeController : Controller
    {
        // GET: /hello/fr-fr/
        public ActionResult Index()
        {
            return Content("Je suis le contrôleur FR-FR.");
        }
    }
}

Before running this, we need to verify that we've got Attribute Routes enabled in our RouteConfig:

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 }
        );
    }
}

Now a request to /hello/en-gb/ goes to our ENGBController and a request to /hello/fr-fr/ goes to the FRFRController:

2014-01-24_11h18_03

Because we've set the default locale in the LocaleRouteAttribute to en-us, we can browse to it using either /hello/en-us/ or just /hello:

2014-01-24_11h20_05

If you've been paying close attention, you may be thinking that we could have accomplished the same thing using an inline route constraint. I think the real benefit over a custom inline constraint is when you're doing more than operating on one segment in the URL: preforming logic on the entire route or context. One great example there would be using a custom attribute based on a user's locale selection (set in a cookie, perhaps) or using a header.

So, to recap:

  • You could write custom route constraints before in "Traditional" code-based routing, but not in attribute routing
  • You could write custom inline constraints, but they mapped just to a segment in the URL
  • Custom route constraints now can operate at a higher level than just a segment on the URL path, e.g. headers or other request context

A very common use case for using headers in routing is versioning by header. We'll look at that with ASP.NET Web API 2.1 next. Keep in mind that, while the general recommendation is to use ASP.NET Web API for your HTTP APIs, many APIs are still running on ASP.NET MVC for a variety of reasons (existing / legacy systems APIs built on ASP.NET MVC, familiarity with MVC, mostly-MVC applications with relatively few APIs that want to stay simple, developer preferences, etc.) and for that reason, versioning ASP.NET MVC HTTP APIs by headers is probably one of the top use cases of custom route attribute constaints for ASP.NET MVC as well.

ASP.NET Web API 2.1 Custom Route Attributes example: Versioning By Header

Note: The example I'm showing here is in the official samples list on CodePlex. There's a lot of great examples there, including some samples showing off some of the more complex features you don't hear about all that often. Since the methodology is almost exactly the same as what we looked at in ASP.NET MVC 5.1 and the sample's available, I'll go through this one a lot faster.

First, the custom constraint:

internal class VersionConstraint : IHttpRouteConstraint
{
    public const string VersionHeaderName = "api-version";
    private const int DefaultVersion = 1;
    public VersionConstraint(int allowedVersion)
    {
        AllowedVersion = allowedVersion;
    }
    public int AllowedVersion
    {
        get;
        private set;
    }
    public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection)
    {
        if (routeDirection == HttpRouteDirection.UriResolution)
        {
            int version = GetVersionHeader(request) ?? DefaultVersion;
            if (version == AllowedVersion)
            {
                return true;
            }
        }
        return false;
    }
    private int? GetVersionHeader(HttpRequestMessage request)
    {
        string versionAsString;
        IEnumerable<string> headerValues;
        if (request.Headers.TryGetValues(VersionHeaderName, out headerValues) && headerValues.Count() == 1)
        {
            versionAsString = headerValues.First();
        }
        else
        {
            return null;
        }
        int version;
        if (versionAsString != null && Int32.TryParse(versionAsString, out version))
        {
            return version;
        }
        return null;
    }
}

This is similar to the simpler LocaleConstraint we looked at earlier, but parses an integer version number from a header. Now, like before, we create an attribute to put this constraint to work:

    internal class VersionedRoute : RouteFactoryAttribute
    {
        public VersionedRoute(string template, int allowedVersion)
            : base(template)
        {
            AllowedVersion = allowedVersion;
        }
        public int AllowedVersion
        {
            get;
            private set;
        }
        public override IDictionary<string, object> Constraints
        {
            get
            {
                var constraints = new HttpRouteValueDictionary();
                constraints.Add("version", new VersionConstraint(AllowedVersion));
                return constraints;
            }
        }
    }
}

And with that set up, we can just slap the attribute header on a couple different ApiControllers:

[VersionedRoute("api/Customer", 1)]
public class CustomerVersion1Controller : ApiController
{
    // controller code goes here
}
[VersionedRoute("api/Customer", 2)]
public class CustomerVersion2Controller : ApiController
{
    // controller code goes here
}

That's it - now requests to /api/Customer with the api-version header set to 1 (or empty, since it's the default) go to the first controller, and with api-version set to 2 go to the second controller. The sample includes a handy test client console app that does just that:

2014-01-24_14h58_06

Okay, let's wrap up there for now. In the next (probably final) post, we'll take a quick high level look at some of the other features in this release.

Recap:

  • Custom route constraints let you run custom logic to determine if a route matches as well as other things like compute values that are available in the matching controllers
  • The previous release allowed for custom inline route constraints, but they only operated on a segment
  • This *.1 release includes support for full custom route constraints
Posted by Jon Galloway | with no comments

Looking at ASP.NET MVC 5.1 and Web API 2.1 - Part 1 - Overview and Enums

This is the first in a four part series covering ASP.NET MVC 5.1 and Web API 2.1

The sample project covering the posts in this series is here; other referenced samples are in the ASP.NET sample repository.

ASP.NET MVC 5.1, Web API 2.1 and Web Pages 3.1 were released on January 20. I call it the star-dot-one release, not sure if that one's going to stick. Here are the top links to find out more:

Release notes

Let's run through what's involved in getting them and trying some of the new features.

Nothing to Install, just NuGet package updates

As I mentioned in my last post, ASP.NET has moved from a "big thing" that you install every few years. The ASP.NET project templates are now mostly a collection of composable NuGet packages, which can be updated more frequently and used without needing to install anything that will affect your dev environment, other projects you're working on, your server environment, or other applications on your server.

You don't need to wait for your hosting provider to support ASP.NET MVC 5.1, ASP.NET Web API 2.1 or ASP.NET Web Pages 3.1 - if they supported 5/2/3 they support 5.1/2.1/3.1. Easier said, if your server supports ASP.NET 4.5, you're set.

However, there are some new features for ASP.NET MVC 5.1 views that require you to be running the most recent Visual Studio update to get editing support. You're installing the Visual Studio updates when they come out so that's not a problem, right?

Okay, Let's Have a Look Then

Game plan: I'm going to take an ASP.NET MVC 5 + Web API 2 project, update the NuGet packages, and then throw some of my favorite features in there.

In this case, I'm opting for the "mostly Web API template" since it includes both MVC and Web API, and it includes help pages right out of the box. I could go with "mostly MVC" + Web API, but then I'd need to install the Web API Help Page NuGet package and I might strain a muscle.

2014-01-20_16h31_07

Now I'll open the Manage NuGet Packages dialog and check for updates. Yup, there they are.

2014-01-20_16h37_07

Since this is a throw-away project I'll throw caution to the wind and click Update All. If this were a real project, I might just update the three new releases so as not to pick an unnecessary fight with JavaScript libraries. But I'm feeling lucky today so Update All it is.

2014-01-20_16h42_15

Wow, look at them go! jQuery 2.0.3 even. It's a party. (anti-party disclaimer for those who might be getting carsick: I didn't have to update to jQuery 2.0.3 or any of that other stuff to use the 5.1/2.1 stuff).

Enum Support in ASP.NET MVC Views

Okay, I'll start by creating a Person model class with a Salutation enum:

using System.ComponentModel.DataAnnotations;
namespace StarDotOne.Models
{
    public class Person
    {
        public int Id { get; set; }
        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
    {
        [Display(Name = "Mr.")]
        Mr,
        [Display(Name = "Mrs.")]
        Mrs,
        [Display(Name = "Ms.")]
        Ms,
        [Display(Name = "Dr.")]
        Doctor,
        [Display(Name = "Prof.")]
        Professor,
        Sir,
        Lady,
        Lord
    }
}

Note that I'm using the Display attribute on a few that I want to abbreviate.

Next, I delete my HomeController and views and scaffold a new HomeController using the Person class. Caution to the wind being our theme, I'll run it.

2014-01-21_00h04_50

Oh no! No dropdown on Salutation!

Just kidding. That's to be expected. To get the dropdown, we need to change the scaffolded view code for the Salutation from the generic Html.EditorFor to use the new Html.EnumDropDownListFor helper.

So in my Create.cshtml, I need to change this line:

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

to this:

@Html.EnumDropDownListFor(model => model.Salutation)

Okay, with that done I'll refresh the page:

2014-01-21_00h09_53

And there it is.

"Now, Jon," you say, "That's really nice, but it would have been absolutely perfect if the scaffolder or EditorFor or something had seen the Enum property and just done the right thing."

You're right. I'm told that will all magically work in an update on the way soon. For now, though, it's easy to get that behavior using some simple EditorTemplates and DisplayTemplates. You can find examples of them in this EnumSample on CodePlex. So I grabbed those templates and copied them into the /Views/Shared directory in my project:

2014-01-21_00h18_21

And I'll change my Create.cshtml view back how it was originally scaffolded, using Html.EditorFor. That way the view engine will look for a matching EditorTemplate for the object type, find Enum.cshtml, and use that to render all Enum model properties.

2014-01-21_00h51_35

Blam!

Okay, one more fun thing in that EnumSample. There's an override in Html.EditorFor that lets you specify the EditorTemplate you'd like to be used. So I'll change that line to this:

@Html.EditorFor(model => model.Salutation, templateName: "Enum-radio")

And now we are truly dropping science like Galileo dropped the orange:

2014-01-21_00h57_41

Recap so far:

  • We updated to the new NuGet packages
  • We saw that we can now use a new helper to render dropdowns for enums: Html.EnumDropDownListFor
  • We saw that we can use EditorTemplates (and, trust me, DisplayTemplates as well) to encapsulate that so any call to Html.EditorFor will intelligently display enum properties

Here's the next post in the series: Looking at ASP.NET MVC 5.1 and Web API 2.1 - Part 2 - Attribute Routing with Custom Constraints

ASP.NET - A last look back at 2013, looking ahead to 2014

There's something about getting into a new year that makes us step back and consider the bigger picture. Where is it all headed? Am I making the most out of my life? What web tools and products has Microsoft released lately?

I got to present a few Web Camps in December, in Oslo and Vancouver. I was reminded that there are some people - we'll call them normal developers who have work to do - don't sit there refreshing the Microsoft downloads new releases page all day. I don't understand them, but I appreciate that they exist.

We announce stuff all the time, but it's hard to keep up with what's important, what you need to know, and stuff you should start paying attention to because it's going to be a big deal really soon. So here's my quick summary of the important things that happened in 2013 and what I think it suggests we watch for in 2014.

The Big Picture

One ASP.NET

This has been a thing for brewing for a bit, but really came together in 2013. With Visual Studio 2013, you really can mix and match ASP.NET MVC + Web API + Web Forms + SignalR + "your framework here" and they all get along. This has been a lot of work over several releases: breaking out functionality out into packages, setting up common components like routing and identity so they're universal, moving to common HTML and CSS for the project templates, Visual Studio tooling changes, etc. That all culminated with the Visual Studio 2013 release, where we finally have just one ASP.NET project with a la carte support for Web Forms, MVC, Web API, and more.

What's probably more important is that you can also add functionality after you've created a project, so if you decide later to add MVC libraries to your Web Forms project it's no big deal.

Visual Studio as a great editor for front-end (HTML / CSS / JavaScript) files

Again, this one has been growing over time: Visual Studio 2012 introduced new JavaScript and CSS editors. The JavaScript editor added tons of new features like ECMAScript 5 support, code outlining, brace matching, go to definition, dynamic IntelliSense. The CSS editor added things like much better IntelliSense, color picker, snippets, lots of HTML5 / modern web development support. It also included Page Inspector - a built-in browser view that shows a running view of your site (e.g. live data from the database, JavaScript is evaluated, everything's running end to end) and allows you to click on an an element and find the line of code that produced the HTML. But the HTML editor in Visual Studio 2012 was old, and that prevented adding modern web development features.

In Visual Studio 2013, the HTML editor was completely rewritten to allow for the cool (MEF based) extensibility that the CSS editor in Visual Studio 2012 leveraged so heavily. That allowed for new support for all kinds of new modern features like IntelliSense for AngularJS, built-in CoffeeScript and LESS editor support and more. The HTML editor features in Visual Studio 2013 get even better with the Web Essentials extension, which I'll talk about in a minute.

And we haven't even mentioned Browser Link yet! Browser Link takes the smarts that went into Page Inspector, hooks it up with a real-time Web Socket connection (powered by SignalR) that's hosted inside of Visual Studio, and gives me real-time, two-way interactivity between my server-side code and any running browser. That means I can run my site in Visual Studio, pop open Chrome or Opera or Firefox or IE or some mobile emulator, hover over an element in the browser and see the source of that HTML highlighted in Visual Studio. That is a huge, huge timesaver I've been wanting for a very long time.

The point is that Visual Studio 2013 ships with newly rewritten, advanced editors for your front-end web files. Like me, you may have seen Visual Studio as an editor for back-end code but went to a lightweight notepad style text editor for HTML / CSS / JavaScript / modern web language of the week. But I think it's time to change that way of thinking - Visual Studio gives me the benefits of a lightweight editor (starts up in 2-3 seconds on a modern computer, has a light UI that gets out of my way), but helps me spot misspellings, get the right vendor prefixes, use JavaScript libraries without having to dig through source code and docs more than I want to, etc.

Web Essentials as "Visual Studio web dev labs"

Web Essentials is a side project run by Mads Kristensen, the project manager for the web developer features that ship with Visual Studio. While Visual Studio's new ship schedule means you get a new version yearly and updates several times throughout the year, Web Essentials ships as often as Mads wants to. Which turns out to be pretty often - often every two or three weeks.

Some features in Web Essentials are prototypes which might land in the next version of Visual Studio - an example is the Paste JSON as Classes feature. This allows you to get your hands on them right away, give feedback on how they work, and then see them graduate to full Visual Studio support.

Web Essentials also includes some interesting features which are useful to web developers who are engaged enough to spend a minute to install and extension, but might not be for everyone. Zen Coding might be an example of that - I don't know if it'll ever ship in Visual Studio, but it's a useful feature if you're an HTML focused web developer and into the new, new stuff. Since web development techniques and metalanguages come out so frequently and change so rapidly, it's great to have a lightweight extension that can keep up with them until they're mature enough to maybe ship with Visual Studio.

Release and update speed

When Visual Studio 2012 was launched in September 2012, Soma announced that they were shifting to a faster release cadence which would include both more frequent full releases and regular smaller updates to deliver features throughout the year. An important point there is that these aren't just service packs with bug fixes, they include useful features. We really saw that come together in 2013. The best example of that was the ASP.NET and Web Tools 2012.2 release in February 2013. I list some of the features below, but it was a pretty big batch: new templates for both ASP.NET Web Forms and MVC, Page Inspector and more. As of now, there have been a total of 5 updates for Visual Studio 2012; the latest added some support for ASP.NET MVC 5 (albeit only with an empty MVC 5 template) to Visual Studio 2012.

I think that's a great thing. The technologies, browsers and languages we need to work with as web developers move really quickly, and we need tools that keep up. Two or three years between releases doesn't work for me, and even yearly is pushing it. I expect to see this update cycle continue in 2014 and beyond. For instance, we've already got the release candidates for ASP.NET MVC 5.1, Web API 2.1 and Web Pages 3.1 - expect the final release very soon. [Update: the final version was released on January 20, read my post series on the new features here.]

Note: In case you didn't know - if you've got Visual Studio 2012 Professional, you can upgrade to Visual Studio 2013 Professional for $99 now.

Again, thinking beyond Visual Studio, the rest of the ASP.NET dev landscape is moving very quickly. Windows Azure has releases roughly every three weeks. Web Essentials and SideWaffle have release updates measured in weeks. NuGet packages update constantly.

Do you have to keep up to date with all of the new things? No, of course not. But since web development technologies and requirements move rapidly, it's good to know that you're generally not going to be waiting on Visual Studio or ASP.NET when you do need the features. And of course, there are lots of benefits (in addition to the big flashy new features) to being on the newest version, e.g. scaffolding in ASP.NET MVC now whitelists your parameters to prevent overposting.

Externalization of ASP.NET

ASP.NET used to be pretty monolithic. You'd get one big ASP.NET release and it did everything. You could plug into it - using things like control events, membership provider hooks, modules and handlers, but you were just plugging into the big ASP.NET thing.

That's really changed over the years.

When you look at what's installed in a new ASP.NET project, it's almost all NuGet packages. That's a big part of what made it possible for the One ASP.NET thing to happen: ASP.NET MVC, Web Forms, Web API, and Web Pages all share common NuGet packages. That definitely includes new features, like the new ASP.NET Identity system.

Side note: You can use these packages individually, or even create your own versions (since they're a permissive under open source license). You can grab nightly builds and which include changes as they're committed.

The tooling (Microsoftese, generally meaning "Visual Studio support") for ASP.NET has also been externalized over the past few years. If you poke around in the Visual Studio program directory (e.g. \Common7\IDE\Extensions\Microsoft\Web Tools), you'll see features are being built using the standard VSIX / MEF extensibility points. That's good because it means things can ship and update more quickly, and the hooks they're using are available to you. Heck, the source is even available to you if you pop them open in a tool like ILSpy or Reflector.

Things are also being built using OWIN (Open Web Interfaces for .NET) now. I've written before about why I think OWIN and Katana are important. The result is that core functionality like authentication is now being plugged into ASP.NET as portable middleware rather than shipped in a big monolithic framework that hides somewhere in your GAC.

Oh, and SideWaffle. What on earth is a SideWaffle?!? Well, just like NuGet externalized ASP.NET dependencies and VSIX externalized tooling, SideWaffle externalizes templates. The idea is that, unlike waiting for new ASP.NET project templates in Visual Studio releases or updates, you install the SideWaffle extension and get (or contribute) Visual Studio templates that are updated more rapidly.

Releases

I've already talked about what these release mean in a big picture sense, so I'll just list them out in linked bullet point form.

ASP.NET and Web Tools 2012.2 (Feb 2013, included with Visual Studio Update 2)

Visual Studio 2013 (Oct 2013)

ASP.NET and Web Tools 2013.1 for Visual Studio 2012

Windows Azure updates

  • Tons of releases throughout the year, but here are some of what I think are the top features for ASP.NET developers:
    • Remote debugging (was in Web Roles, now it's available in Windows Azure Web Sites)
    • Create and publish to Windows Azure Web Sites from Visual Studio
    • Right-click on VM, RDP
    • MDSN benefits / price cuts / run VS in cloud (also VS Online)
    • Web Socket support
    • Windows Server 2012 R2
    • General Availability (Web Sites, Mobile Services, IAAS)

Web Essentials

Side Waffle

NuGet

  • There were lots throughout the year, but I think the main feature for web developers was that Package Restore is enabled by default in NuGet 2.7

Portable class libraries

  • This is a big step forward for portable libraries - both community open source libraries and Microsoft provided libraries - to work cross platform

New Stuff That You Really Need To Understand

ASP.NET Identity

We had an old ASP.NET Membership system that worked for a while, but was definitely showing its age. It didn't support claims and social authentication, it didn't work well with custom membership data, it was hard to extend. Then we got Simple Membership in ASP.NET MVC 4, which was simple but hard to extend. A lot of work went into the new Identity system to make sure it both did simple things well and was wasn't hard to extend later.

There's a lot of documentation out there on the new Identity system, and more on the way at http://www.asp.net/identity

Also, I recommend K. Scott Allen's recent posts exploring ASP.NET Identity, such as  Customization Options With ASP.NET Identity.

Bootstrap

All of the new web project templates are built using Bootstrap. I overviewed that a little in a previous post, but there's a lot more to it. The top benefits I see are:

  • It's popular across the web development community, so we're able to take advantage of community support for things like themes, documentation, tutorials, etc.
  • It's responsive and mobile-first, so it's very easy to build sites that work well at narrow (mobile) screen resolutions, intermediate screen resolutions like tablets, and on widescreen displays
  • It's got a lot of components and jQuery based plugins that handle common web developer concerns

Other Neat Stuff That You Should Start Paying Attention To

Scaffolding

We've had scaffolding in ASP.NET before, but it was framework specific - there was MVC scaffolding, Web API scaffolding, and nothing else if you were working on another project type. The scaffolding system in Visual Studio 2013 (and now available in 2012, as mentioned above) has been updated so it works in any ASP.NET project, and it's been built to be easily extensible (the extensibility bit will be shipped and documented in a Visual Studio update early this year).

Some good references:

ASP.NET MVC 5.1, Web API 2.1 and Web Pages 3.1

The release candidates have already shipped and the final release will be out very extremely soon. Some of the new features:

  • ASP.NET MVC 5.1
    • Attribute Routing support for constraints
    • Bootstrap support for HTML helpers (allowing HTML attributes in Html.EditorFor)
    • Support for Enums
  • ASP.NET Web API 2.1
    • Global Error Handling
    • Attribute Routing support for constraints
    • BSON media type formatter
    • Async filters
    • Help Page improvements

OWIN and Katana

I mentioned these earlier. If you've been putting this on your "I'll ignore this until it starts getting important" list, it's time. The new Identity system is wired into the ASP.NET project templates using OWIN, and new things will be moving that direction.

Visual Studio Online

I think Visual Studio Online - including the Monaco editor - is getting pretty interesting. It's definitely useful for web developers. See my post here: A look at the new Visual Studio Online "Monaco" code editor

Node Tools for Visual Studio

Node (and NPM) are getting to be pretty big in the web development world, and I think it's important to keep up with where it's going. It hasn't been that hard: Node's pretty lightweight, runs well on Windows for a while now, and is incredibly easy to run in Windows Azure Web Sites. But, it's gotten incredibly easy now that they've built pretty impressive support for Node.js into Visual Studio. I think it's worth taking some time and getting a little familiarity with Node.js if you haven't yet. Don't get me wrong, I'm in no way pushing Node.js over ASP.NET development, I'm just saying that I personally think it's a good idea to keep up with as a professional web developer.

See Scott Hanselman's post (Introducing node.js Tools for Visual Studio) and give it a look.

Keeping Up With The New Stuff

That's a condensed list of what I think's important circa January 2014, and it's a lot. How on earth can we keep up with all of this?

Here are some resources I recommend:

All right! Go to it! Let's do this!

Posted by Jon Galloway | with no comments

Two great Kickstarter projects ending soon: Durandal JavaScript framework and bitCommander File Manager

I like Kickstarter. It's not a store, it's an easy way to help fund creative projects. You back projects you find exciting at different reward levels, and then follow along with the project's progress. I blogged about the AGENT watch last June and was excited to see them hit 10x their goal - I'm really looking forward to getting my AGENT watch when they ship.

Preemptive disclaimer: As I said, it's not a store. You're funding a project with goals and risks and target timelines. The average contribution amounts aren't that high and I fund projects that I want to support, so I'm okay with that. If you're not, Kickstarter's not your thing, and that's fine too.

I wanted to help get the word out about two recent Kickstarter projects I've backed (and been tweeting about): Durandal and bitCommander. Both end soon (bitCommander ends on Jan 9, Durandal ends on Jan 10).

Durandal

Durandal is an open source JavaScript framework that helps you build full-featured single page applications. Ward Bell summed up what's unique about Durandal pretty well:

What’s so great about it? What’s distinctive about it? Rob has his inventory of laudable features (and its impressive). Here are some of the aspects of nextGen Durandal that I love … and that have no equal among alternative frameworks:

  • Convention over configuration – I hate writing and maintaining “switch board” code to connect FooViewModel to FooView and FooRoute etc. I want to say “Foo” and be done with it … until and unless I have a compelling reason to break convention.
  • Customizable conventions – Rob makes good choices but I’m free to define my own.
  • Page life-cycle – Durandal has baked in understanding of the birth and death of “pages” so I don’t have to make up my own hacks to ensure that new pages are initialized on creation and cleaned up on destruction.
  • Asynchrony throughout – Need to wait for the user to confirm or cancel before moving off the page? That’s easy in Durandal because asynchrony is plumbed through the page life-cycle and everywhere else. Dynamically load optional modules on-demand? Easy.
  • Diagnostics – With debug mode turned on the console tells me exactly what choices Durandal is making for me as they happen. I can tap into that logging pipeline with my own diagnostics.
  • Write less, do more – You all know what I mean. We all want to write less code. That’s the motherhood and apple pie that every framework promises. They usually deliver something else. Check out the nextGen Durandal sample video and tell me what other technology is that clear and concise.

We talked to Rob Eisenberg about what he wants to accomplish on the Durandal Kickstarter on Herding Code: Herding Code 182: Durandal Kickstarter with Rob Eisenberg

Download / Listen:

One of the things that really stood out for me was what Rob's doing with cutting edge browser and JavaScript technologies for the Durandal nextGen. He's investing heavily in a module system that works with ES6 modules, AMD and CommonJS. He's building on HTML Templates and Web Components. In addition to light weight, modular code, he's seeing 2-3x performance benefits over AngularJS. And it's all polyfilled so it works in current browsers while waiting for these features to ship. The result is that this is a great investment not only in a great next-generation SPA framework, but in the web in general: by backing Rob, you're getting real-world implementation of these specs early so we can get them right the first time.

The main benefit of backing this Kickstarter is that you free Rob up from consulting work so Durandal gets these amazing features faster. The secondary benefit for backers is that Rob will be producing some great training series - video and source code included.

As of now, there's still a good way to go on getting this funded. Pitch in and tell someone else to do so, too!

bitCommander

bitCommander is a really interesting file manager for Windows. It's already hit its funding goal as I write this. If you beat the end of the Kickstarter campaign, you can get a discount on it, and if not you'll want to pay the full price for it because this thing is looking really cool.

I like the recent changes to the Windows File Explorer in Windows 8 - the ribbon's really nice, and the file copy experience is vastly improved, for instance. But when you're doing things that involve multiple simultaneous views - like assembling a lot of files, for instance - having several instances of File Explorer open gets clunky.

Check out how browsing in bitCommander looks (all images below from the bitCommander website):

2014-01-08_13h36_32

You might think it's just Miller columns (recently popularized as the OS X Finder columns view mode, but dates all the way back to 1980). That alone would be pretty nice, but there's a lot more to it. There are tons of other great features, but I think my favorite is the temp list and batch support.

There's a lot of other cool stuff, like tabs, nice thumbnail display (with details), intelligent filename shortening and more. I think what I like most about this is that it adds a lot of features but keep the design simple and focused. See what I mean on the bitCommander website.

Here's mockup of a possible additional feature that Milos is looking at adding: integrated command windows, sync'd to the current browsing directory:

Un-disclaimer: I backed both of these projects and don't get anything for talking about them. I just like them.

Go back bitCommander and Durandal!

Posted by Jon Galloway | with no comments

A look at the new Visual Studio Online "Monaco" code editor

One of the most interesting announcements at the Visual Studio 2013 Launch today was the Monaco editor in Visual Studio Online.

I've seen little hints of this coming - for example, Scott Hanselman's post in August: A rich new JavaScript code editor spreading to several Microsoft web sites. And if you looked around the command-line Kudu interface on an Azure Web Site (available at https://<SITENAME>.scm.azurewebsites.net) there's been a lightweight file editor available for a little while.

After the announcement today, I dug up enough info to be dangerous and took it for a quick spin. Quick disclaimer: this is me playing around for a bit, it's not an official announcement.

Some top Monaco editor links

Visual Studio 2013 Launch: Announcing Visual Studio Online - Soma's announcement post gives a quick overview. More importantly, it links to a series of videos on Channel 9 which overview the Monaco editor and demonstrate using it in a few different scenarios.

Channel 9 series: Visual Studio Online "Monaco"

I'll embed some of these videos at the end of the post - not here, or you'd get distracted and you'd never read the rest of the post, right?

The big one: Visual Studio Online updates post on the Visual Studio Online features timeline news feed thing. Can I call it a blog? I just don't know. But it's wonderful.

Specifically, the Announcing Visual Studio Online “Monaco” section shows how to turn it on and get started.

Walkthrough: Editing an ASP.NET site in the browser

Full disclosure: I tried bumbling my way through this and made a mess, then went crying to David Ebbo for help. He set me straight.

Step 1: Set up a Windows Azure Web Site with git deployment

First, I'm going to create a new ASP.NET site in Visual Studio 2013 and deploy it to git. Now, I could use Visual Studio Online's git hosting - of course it works well, and works with the Visual Studio Online Monaco editor. But you'd suspect some tricky business, so I'm going to use a GitHub repository.

So, I'm creating a simple ASP.NET MVC 5 application (with no authentication so I don't need to deploy a database) and pushing it to a GitHub repository.

2013-11-13_11h21_09

2013-11-13_11h22_11

Now I'm dropping in a standard .gitignore and initializing the repo, then pushing to GitHub.

git init
git add .
git commit -m "Initial commit"
git remote add github https://github.com/jongalloway/PlayingWithMonacoEditor.git
git push -u github master

Now I'm going to create a new Windows Azure Web Site using that GitHub repo as the source. This has been available for a long time, but I'm showing the steps in case it's new to you.

2013-11-13_18h06_26

2013-11-13_18h08_04

2013-11-13_18h10_21

2013-11-13_18h16_54

Step 2: Set up for editing using Visual Studio Online

Okay, we've got a live repo and the site's deployed. Now we want to edit that source using Visual Studio Online.

Here's the trick I learned from David Ebbo - you want to create another Windows Azure Web Site that's just associated with the source, not the deployment. So I head back into the portal and create a new Web Site just for source editing.

2013-11-13_18h20_03

Oops, I created it in Western Europe. Good thing the internets are fast.

Now, in the new site, I head over to the Configure tab and enable "Edit in Visual Studio Online".

2013-11-13_18h41_38

Can you feel it? We're almost there. Promise.

Now I head over to the Dashboard tab, and click on the Edit in Visual Studio Online link. Like you, I can hardly contain my excitement! What will happen?

2013-11-13_14h59_14

Oh, a login prompt. Hmm.

2013-11-13_15h00_26

Fortunately, I know my username and password. If you forget, you can reset your password in the portal, on the Dashboard tab. Okay, with that done, here's what we get:

2013-11-13_15h04_13

Hooray! Yeah, science!

Step 3: Appeal to the hipster demographic

Wait, you're not impressed because I used IE, is that it? You wanted me to see if it worked in another browser?

Yeah, maybe this is an opportunity to dust off that Mac Mini to see how it does there. Hold on, it's over here somewhere. Under the... oh, that bill's overdue. Hm. Behind the... oh, there it is. Okay!

So I log back in to the Azure portal on click that same Edit In Visual Studio Online link. Hey, there it is again! I'll show this screenshot bigger this time.

2013-11-13_18h49_05

Step 4: Clone the repo

Now I click on the git icon on the left side and enter my git url, then hit clone.

2013-11-13_19h00_18

And here it goes...

2013-11-13_19h01_58

Okay, that looks really cool, and my code's visible on the left. Before I start editing, I want to make sure I can build it. In the console window, I'm going to type in "msbuild" and cross my fingers.

2013-11-13_19h09_25

Well, we couldn't expect it to work on the first shot, could we? I...

Oh, it did work. Well, hey there.

So, back on my Windows box, here's what the site looks like in IE11.

2013-11-13_19h47_36

Step 5: Do some editing. That's what started this whole mess, remember?

I'm going to head back over to the Mac and edit some code. To make this interesting, I'm going to edit C#, CSHTML, CSS and JavaScript. What could go wrong?

First I edit the HomeController to add something to the ViewBag.

2013-11-13_20h04_39

Next I edit the CSHTML, adding in some HTML and C# changes.

2013-11-13_21h23_39

Finally, I make some CSS edits.

I'm kind of rushing through this, but there's code completion and IntelliSense all along the way. For instance, when I start editing a CSS color, I get a dropdown with available colors.

2013-11-13_20h14_44

When I select a color, I can see what it will look like in the editor.

2013-11-13_20h15_02

Now I build to make sure it's all still good.

2013-11-13_20h50_22

Step 6: Deploy

And git push to deploy.

2013-11-13_20h51_44

Step 7: Full circle, with a pirouette and a lemon twist

And hopping back to my Windows / IE 11 browser, we can see that it works.

2013-11-13_21h22_15

What's the point?

Why did we do this? What did it buy us?

Well, for one thing, we grabbed an ASP.NET repo from GitHub in a browser, on a Mac, made some code changes, and deployed it. If you've got a browser (free) and a Windows Azure account (free), you can edit and deploy an ASP.NET site. You could do it on an Android tablet, on an iPad, in a boat, with a goat.

Even if you're on Windows, note that the Visual Studio Online experience didn't require me to sign up for or pay anything. Visual Studio Online is free for projects with five or fewer users, and didn't make me jump through any hoops to get going. That means you can get started using it. If you want more Visual Studio Online or Windows Azure services, you can get them, but there's no roadblock to creating / editing / deploying / maintaining a site right now.

Oh, and this was ASP.NET MVC 5 - so, all the new stuff works out of the box. Yes, you'd expect that, but it's worth pointing out.

Recap and regrets

Yes, we've arrived. We deployed code to GitHub, pulled it into a Windows Azure Web Site, edited it in a browser, on a Mac (demo bingo, everyone drink), and saw it automatically deployed and running in a browser. Neat.

What I didn't have time to show you was all the cool features in the Monaco editor.

For instance, you can click on the settings gear in the upper right corner and switch to the Visual Studio dark theme, which is so much cooler.

2013-11-13_21h46_07

I regret that we didn't have time to look at all of the cool editor features, like the editor commands shown when you hit ctrl+E.

2013-11-13_21h48_36

I wish we'd had time to look at the fancy IntelliSense features, including support for jQuery function overloads.

2013-11-13_21h50_33

And it would have been neat to cover the cool diff-on-commit view.

2013-11-13_21h52_46

But, alas, it was not to be.

For those features, and many more, I recommend you check out the videos I referenced earlier. I'll even embed some of those in the next section, because this post wasn't quite long enough.

Neat Videos You Should Watch

All of the Monaco videos are good, but these are some of my favorite.

First Steps

Editor Tips And Tricks

Getting Started With PHP

Debugging node.js

And last, but not least, Getting started with TypeScript. Why? Because the Monaco editor was written in TypeScript!

Posted by Jon Galloway | with no comments

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!

Free 6 hour online course - Developing ASP.NET MVC 4 Web Applications Jump Start

The videos for the Developing ASP.NET MVC 4 Web Applications Jump Start Jump Start event are live on Microsoft Virtual Academy. This is an entire 9 session course, covering the official ASP.NET MVC certification course material.

If you've been wanting to learn more about ASP.NET MVC - or are perhaps studying for the ASP.NET MVC 4 certification (70-486), this is a great way to get started.

If you have friends or co-workers who are learning ASP.NET MVC, please share this with them.

I had the privilege of working with Christopher Harrison, an actual professional trainer who knows this course material pretty well. I think the end result turned out really well - just as I was typing this post I heard from someone who told me how much they enjoyed it:  "It's definitely a solid ramp up for people who are new (like myself) to MVC. Also, much more entertaining then most other tutorials I've seen around." That's exactly what we were hoping for - serious training that's fun to watch.

For example, there were several surprise spaghetti awards given out by the video crew during the day.

Bonus spaghetti at MVA ASP.NET MVC 4 Jump Start

Take the course

The Microsoft Virtual Academy site has a nice system that tracks which modules you've completed, lets you download the slides for each course, etc. You can skip through the sessions as you want, and there's no big registration to go through to get started.

So hop on over: Developing ASP.NET MVC 4 Web Applications Jump Start

What we covered

Here's a high level overview of what we covered:

  • Overview of ASP.NET MVC
    • What is ASP.NET MVC?
    • How is ASP.NET MVC different from Web Forms?
    • Why use ASP.NET MVC?
  • Developing ASP.NET MVC 4 Controllers and Models
    • Creating Controllers
    • Adding Actions
    • Creating MVC Models
    • Working with Code First
  • Developing ASP.NET MVC 4 Views
    • Razor Syntax
    • HTML Helpers
    • Partial Views
  • Integrating JavaScript and MVC
    • Using AJAX
    • Using jQuery
  • Implementing Web APIs
    • Developing Web API Controllers
    • Calling HTTP Services from Client-Side Code
  • Deploying ASP.NET MVC Site Walkthrough
    • Creating a site on Windows Azure Web Sites
    • Deploying an ASP.NET MVC Application with Visual Studio Web Deploy
  • What’s Next and Resources
    • Sneak peak at Visual Studio 2013 (Preview) and ASP.NET MVC 5 tooling
    • A look at real-time communications with SignalR
    • Resources for keeping up with new ASP.NET releases

Source Code

The source code for the session is available here: sdrv.ms/1bHo6rU

No warranties  or anything on this - it's just what we built during the day. It is, however, based on the official ASP.NET MVC 4 course work, so if you do take the course it will be familiar.

Video from the course introduction

If you need a little more convincing, here's a video of the 30 minute introduction.

Disclaimer: This module starts with a quick introduction to ASP.NET MVC in general before we move systematically through the other components. Don't worry if it's too slow - or too fast - for you, the rest of the course goes more slowly and in more depth through each topic.  

Let us know!

Did you like this course? Want to see more, or something different? Please leave feedback on the course page - click the "Send feedback to the course owner" link.

More Posts Next page »