4 Comments

Last October I wrote about my road to Visual Studio 2013 which was one big diary entry for an entire year in my professional life. This is such an incredible time to be working on the Visual Studio Web Tools Team and I’m so proud to work with some of the smartest people in the industry.

This time last year, we were almost ready to ship Visual Studio 2013, so here’s what has happened since then.

A few months before shipping Visual Studio 2013 we already started the work on Update 2. We decided not to be part of the first update to VS2013 because we had some rather large features that we knew wouldn’t be ready before Update 2.

sassOne of those features was the Sass editor because we had received a lot of feature requests for it. It was the most requested feature on the Web Essentials UserVoice page in fact.

In Visual Studio 2012 Update 2 we released the LESS editor so we had plenty of experience with this type of CSS based language. Peter could reuse a lot of the code from the LESS editor (which he also implemented), so the iterations went pretty fast. Sass has a lot more features than LESS, so there was still a lot of new code and concepts to implement.

The funny thing about both LESS and Sass is that they evolve very rapidly. It’s not like web standards from the W3C which can be years in the making. These two languages introduce new features and concepts many times a year, so it is a bigger challenge to keep the editors up-to-date. We’re still working on updating both implementations for VS14 in order to keep up with the changes and we will continue to do so going forward.

We had one additional editor to implement for Update 2 and that was for JSON. Visual Studio never had a JSON editing experience before and we felt it was important to have one. Alex had been working on the support for auto-updating the _references.js file up until Christmas 2013, so the work on the JSON editor didn’t start until December 28.

We were very ambitious with the JSON editor, because we wanted more than just syntax highlighting. We also wanted schema based Intellisense, validation, formatting and more. A full language service was needed. We broke it down into several pieces:

  • Basic language service
    • Syntax highlighting
    • Formatting
    • Syntax validation
    • Brace completion/matching
  • JSON Schema Intellisense
    • Draft v3 and v4 support
  • JSON Schema validation
    • Enables more accurate Intellisense

We knew we couldn’t do all of that for Update 2, so both Mike and Todd helped out with the JSON Schema support while Alex was implementing the language service and Anh was testing it all. We refer to the Update 2 JSON editor as version 1.0. In Update 3 we added better formatting and other important tweaks and in Update 4 we’re adding the validator. This will be version 2.0.

imageI sent a pull request to the official JSON Schema website that added Visual Studio as the only editor that supports JSON Schema. To this day it’s still the only one. We’re not done yet and will continue to improve the editor in VS14 and beyond.

Our team is now responsible for 7 separate editors. The highest number by any Visual Studio team. The editors are:

  1. CSS
  2. LESS
  3. Sass
  4. CoffeeScript
  5. Web Forms
  6. HTML
  7. JSON

It’s quite the task to keep them all up-to-date with every release of Visual Studio and its quarterly updates. It’s sometimes a little overwhelming.

imageTo make the experience with JSON Schemas even better, I started working on a website for storing various JSON Schema files. It’s called SchemaStore.org and is completely open source. Web Essentials will automatically download the schema files stored on SchemaStore.org and bind them to known JSON files such as package.json, bower.json etc. In VS14 we’ll build this feature in and open it up for custom schema catalogs as well. We’re even working on a SublimeText plugin that will do the same.

SchemaStore.org used to be hosted on my personal Azure server, but we’ve now moved it over the the ASP.NET team’s Azure subscription so we can scale it out for the load it will get in the near future. I feel very proud about that since it is just one of my side projects, not controlled by Microsoft, 100% open source and now being incorporated into Visual Studio. It’s not the old Microsoft anymore!

Project Aurora

Early in 2014 we started a new effort spanning both the ASP.NET and the Visual Studio Web Tools teams. The mission is to bring modern web development concepts to Visual Studio and ASP.NET in a way that makes them easy to use. An effort that looks at the entire end-to-end experience. The effort is called Project Aurora.

Modern web development concepts include tools like Grunt, Gulp, Bower and npm and frameworks such as AngularJS and Bootstrap. On top of that, it also includes LESS/Sass/TypeScript/CoffeeScript compilation, bundling and minification, image optimization, spriting etc. The individual pieces are simple enough when you first get to know them, but to orchestrate a coherent story that integrates all of them into Visual Studio is a tougher challenge.

One of the main challenges is to write tooling on top of Grunt/Gulp and surface it elegantly inside Visual Studio without compromising the power and flexibility of those tools. And at the same time make them much easier to use for existing Visual Studio users.

Project Aurora is a key element on the road to VS14 and ASP.NET vNext in that it pushes requirements to the various feature crews in our team to ensure the coherent story comes to live.

The “S” word

Instead of writing long specifications (the “S” word) for all of this, we started releasing prototypes to get feedback much earlier than we normally would. This includes contributing to existing Visual Studio extensions. Grunt Launcher was one of those extensions that we contributed to.

We also released the Package Intellisense that would give live Intellisense for npm and Bower packages directly in the new JSON editor. Notice how these things all come together to form a better end-to-end story.

bowerThe Package Intellisense extension is right now being implemented in Visual Studio 14 with all the feedback that we got early on from it. This is a much better way of writing software.

We also released the Task Runner Explorer extension to get early feedback on our Grunt/Gulp support in VS. Read Hanselman’s blog post about these three extensions.

We’re also rolling in other features that were first introduced in side projects such as Web Essentials and SideWaffle. Templates and snippets for Angular are coming from SideWaffle (thanks to John Papa). Angular and Bootstrap Intellisense icons are coming from Web Essentials.

The pace of which we’re able to introduce new features and react to feedback is astonishing and so much faster then just a few years ago. Early prototypes have proven to be key, so expect a lot more of those going forward.

Coding

As a program manager I don’t get to write any production code. That’s probably a good thing. The only code I’m allowed to write for Visual Studio is the XML schema files that make up HTML and CSS Intellisense and validation. I update these files several times per month with the latest and greatest from the W3C and the browser vendors.

Just a few months ago, I coded up a feature for the new JSON editor that would give Intellisense for the $schema property. This was done in C#. After writing the feature I submitted it to code review and crossed my fingers hoping the developers would take the code. They did! It was a great personal achievement even though it was a very small feature.

So coding is not what I do most while at work, but I’ve been a developer my entire adult life, so I just can’t stop coding. I need coding projects. In the past year I’ve released a few websites, worked on some Visual Studio extensions and a number of open source contributions.

Web related:

Visual Studio extensions:

Open source contributions:

  • Grunt Launcher
    • Added support for Bower and npm
  • EditorConfig
    • Added syntax highlighting, Intellisense and validation
  • DartVS – a Dart editor for VS
    • Added syntax highlighting
  • Grunt-tv4 JSON Schema validator in node.js
    • Added support for BOM (byte order mark)
  • GitHub for Windows
    • Updates to the default .gitignore file
  • Contributed JSON Schema files for:
    • Swagger 2.0
    • resume.json
    • CoffeeLint
    • JSHint
    • JSON-LD

These things are all open source and combined they put me in the top 100 of the most active GitHub users (#94). So even if I don’t get to code much at work, I make up for it in my spare time. See all the projects on my GitHub profile.

The road ahead

As various pieces are coming together to form the next generation of web tooling, a lot is still to be done. One thing that’s on the top of my to-do list is to port Web Essentials to VS14. The approach we’re taking with Web Essentials is to bring it back to the basic features of extending the editing experience. This means that a lot of features will be removed.

We’re getting rid of all the node.js based tooling in Web Essentials, such as LESS/Sass/CoffeeScript compilers, minification, JSHint/JSCS integration etc. We are doing that because we’re taking a bet on Grunt/Gulp for those scenarios in VS14. One of the things we’ve learned by having those features in Web Essentials is that they are difficult to maintain, don’t have MSBuild/CI support, are not very flexible, are not cross-platform and error prone.

The rest of the web industry has adopted Grunt/Gulp to handle all these features, and they add all the flexibility that Web Essentials can’t. Removing all this from Web Essentials gives a much higher stability to Visual Studio as well. It will also shrink the extension from around 13MB down to around 800Kb.

Stability has been the top issue for Web Essentials 2013 and it’s my top priority to do something about it for the new version. Removing the node.js based features will address this issue.

We’re also looking into improving the Angular and Bootstrap story significantly in Visual Studio, both supporting the current versions but also making sure that Angular 2.0 is fully supported with Intellisense etc. It’s a big task. In Visual Studio 2013 Update 4 we already made modifications to improve the Angular experience. The HTML editor no longer complains about custom elements and attributes and the {{}} templating support has been reimplemented to be more flexible.

Right now is the most exciting time for me at Microsoft as a web developer. The new version of ASP.NET as well as Visual Studio is now mature enough for us to take web development to new heights and break into the future with renewed confidence.

I’m looking forward to Visual Studio 14 and I hope you’ll enjoy it too. It will be glorious.

5 Comments

HTML5 and CSS3 introduces some new file types that enables us to create even better websites. We are now able to embed video, audio and custom fonts natively to any web page. Some of these file types are relatively new and not supported by the IIS web server by default. It’s file types like .m4v, .webm and .woff.

When a request is made to the IIS for these unsupported file types, we are met with the following error message:

HTTP Error 404.3 - Not Found

The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.

The problem is that the IIS doesn’t know how to serve these new files unless we tell it how. This can be easily done in the web.config’s <system.webServer> section by adding the following snippet:

<staticContent>
    <mimeMap fileExtension=".mp4" mimeType="video/mp4" />
    <mimeMap fileExtension=".m4v" mimeType="video/m4v" />
    <mimeMap fileExtension=".ogg" mimeType="video/ogg" />
    <mimeMap fileExtension=".ogv" mimeType="video/ogg" />
    <mimeMap fileExtension=".webm" mimeType="video/webm" />

    <mimeMap fileExtension=".oga" mimeType="audio/ogg" />
    <mimeMap fileExtension=".spx" mimeType="audio/ogg" />

    <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
    <mimeMap fileExtension=".svgz" mimeType="image/svg+xml" />

    <remove fileExtension=".eot" />
    <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
    <mimeMap fileExtension=".otf" mimeType="font/otf" />
    <mimeMap fileExtension=".woff" mimeType="font/x-woff" />
</staticContent>

The above snippet includes support for most video, audio and font file types used by HTML5 and CSS3.

13 Comments

This year at the //build/ conference I gave a session on Visual Studio Web Tools and Web Essentials. It’s now online on Channel 9 in case you want to watch it.

I was using a few extensions that are great for any web developer using Visual Studio 2013. I’ve compiled the list of extensions here and added a few additional ones that are really useful as well.

Web Essentials

logoThis is the ASP.NET and Web Tools team’s official unofficial playground – owned and driven by the open source community. It adds a huge number of features relevant for web developers, such as LESS/Sass/CoffeeScript compilers, code linters, additional Intellisense for JavaScript/CSS/HTML/JSON, validators, image sprite creation and a lot more.

Website: http://vswebessentials.com
Download: Web Essentials in the VS Gallery

SideWaffle

imageA delicious side dish for Visual Studio. This is an awesome template pack containing both Project Templates, Item Templates and Snippets for a wide variety of scenarios. From building Angular.js apps, Nancy FX projects, Browser Link and Chrome extensions and a lot more.

Website: http://sidewaffle.com
Download: SideWaffle in the VS Gallery

File Nesting

imageThis extension let’s you manually nest and unnest files in Solution Explorer. It also has an option for doing the nesting automatically based on file naming conventions. This is great for nesting *.min.js and other related files under parent files.

Download: File Nesting in the VS Gallery

JSON Schema Generator

json-logoVisual Studio 2013 will provide full Intellisense and tooltips for any JSON file that is associated with a schema. This extension lets you right-click directly on a JSON file in Solution Explorer and generate a schema file based on the source JSON file.

Download: JSON Schema Generator in the VS Gallery

Here are some additional extensions that might be of interest to you as well.

WebJobsVS

imageIn the Day 2 Keynote I showed how to create a C# console application project and use it as an Azure Webjob. To associate the console application with my web application, I used this extension. It was developed by folks working in the Azure team.

Download: WebJobsVS in the VS Gallery

SlowCheetah – XML transforms

Slow CheetahA great extension that enables you to transform your app.config or any other XML file based on the build configuration. Basically, this extension enables scenarios for XML transforms that are currently only available for web.config files.

Download: SlowCheetah in the VS Gallery

GruntLauncher

If you’re working with Grunt, Gulp, NPM or Bower, then this extension is for you. It allows you to easily run Grunt/Gulp tasks directly from Solution Explorer as well as update Bower components.

Download: GruntLauncher in the VS Gallery

Mexedge Stylesheet Extension

imageThis is a beautiful extension that provides CSS document outline directly inside Solution Explorer. Not only does it look great, it also gives a very convenient overview over media queries, selectors and rule sets. This is a must-have for any web developer working with CSS.

Download: Mexedge in the VS Gallery

PHP Tools for Visual Studio

imageIn my live Channel 9 interview we talked briefly about this excellent extension for PHP development. This gives you PHP Intellisense, debugging, code navigation and a lot more inside Visual Studio. A must-have for PHP developers that want the awesome power of Visual Studio.

Website: http://www.devsense.com/products/php-tools/
Download: PHP Tools in the VS Gallery

Cobisi Routing Assistant

This is a great extension for visualizing your ASP.NET routing table and to find what URLs map to what routes. It makes it easier to diagnose routing issues and even provides some great editor tooling features as well.

Website: http://cobisi.com/routing-assistant
Download: Routing Assistant in the VS Gallery

CssCop – FxCop for Stylesheets

imageIf you’re getting serious with CSS, then this extension is going to help you out. It runs CssLint inside Visual Studio to give you error messages that makes it easy to fix any rule violations.

Download: CssCop in the VS Gallery

Node.js Tools for Visual Studio

nodejsNTVS is a free, open source plugin that turns Visual Studio into a Node.js IDE. And it does a superb job at that. This gives you the power of Visual Studio for any Node.js development.

Download: NTVS on CodePlex

Chutzpah Test Adapter

imageA great extension for JavaScript unit testing. Chutzpah supports Jasmine, QUnit and Mocha tests inside Visual Studio and works from both the command line as well as inside VS.

Download: Chutzpah in the VS Gallery

Lua Test Adapter

imageIf you’re using Lua for your JavaScript unit tests, then this extension will integrate it directly into the Test Explorer in Visual Studio. It makes it really easy to execute tests all at once every time you build the project.

Download: Lua Test Adapter in the VS Gallery

Did I forget any extensions? Let me know in the comments below.

46 Comments

Optimizing for website performance includes setting long expiration dates on our static resources, such s images, stylesheets and JavaScript files. Doing that tells the browser to cache our files so it doesn’t have to request them every time the user loads a page. This is one of the most important things to do when optimizing websites.

In ASP.NET on IIS7+ it’s really easy. Just add this chunk of XML to the web.config’s <system.webServer> element:

<staticcontent>
  <clientcache cachecontrolmode="UseMaxAge" cachecontrolmaxage="365.00:00:00" />
</staticcontent>

The above code tells the browsers to automatically cache all static resources for 365 days. That’s good and you should do this right now.

The issue becomes clear the first time you make a change to any static file. How is the browser going to know that you made a change, so it can download the latest version of the file? The answer is that it can’t. It will keep serving the same cached version of the file for the next 365 days regardless of any changes you are making to the files.

Fingerprinting

The good news is that it is fairly trivial to make a change to our code, that changes the URL pointing to the static files and thereby tricking the browser into believing it’s a brand new resource that needs to be downloaded.

Here’s a little class that I use on several websites, that adds a fingerprint, or timestamp, to the URL of the static file.

using System; 
using System.IO; 
using System.Web; 
using System.Web.Caching; 
using System.Web.Hosting;

public class Fingerprint 
{ 
  public static string Tag(string rootRelativePath) 
  { 
    if (HttpRuntime.Cache[rootRelativePath] == null) 
    { 
      string absolute = HostingEnvironment.MapPath("~" + rootRelativePath);

      DateTime date = File.GetLastWriteTime(absolute); 
      int index = rootRelativePath.LastIndexOf('/');

      string result = rootRelativePath.Insert(index, "/v-" + date.Ticks); 
      HttpRuntime.Cache.Insert(rootRelativePath, result, new CacheDependency(absolute)); 
    }

      return HttpRuntime.Cache[rootRelativePath] as string; 
  } 
}

All you need to change in order to use this class, is to modify the references to the static files.

Modify references

Here’s what it looks like in Razor for the stylesheet reference:

<link rel="stylesheet" href="@Fingerprint.Tag("/content/site.css")" />

…and in WebForms:

<link rel="stylesheet" href="<%=Fingerprint.Tag(" />content/site.css") %>" />

The result of using the FingerPrint.Tag method will in this case be:

<link rel="stylesheet" href="/content/v-634933238684083941/site.css" />

Since the URL now has a reference to a non-existing folder (v-634933238684083941), we need to make the web server pretend it exist. We do that with URL rewriting.

URL rewrite

By adding this snippet of XML to the web.config’s <system.webServer> section, we instruct IIS 7+ to intercept all URLs with a folder name containing “v=[numbers]” and rewrite the URL to the original file path.

<rewrite>
  <rules>
    <rule name="fingerprint">
      <match url="([\S]+)(/v-[0-9]+/)([\S]+)" />
      <action type="Rewrite" url="{R:1}/{R:3}" />
    </rule>
  </rules>
</rewrite>

You can use this technique for all your JavaScript and image files as well.

The beauty is, that every time you change one of the referenced static files, the fingerprint will change as well. This creates a brand new URL every time so the browsers will download the updated files.

FYI, you need to run the AppPool in Integrated Pipeline mode for the <system.webServer> section to have any effect.

10 Comments

What's the address of your website? www.domain.com or domain.com?

There are two camps on the subject of the www subdomain. One believe it should be enforced (www.yes-www.org) and the other (no-www.org) that it should be removed. They are both right.

What's important is that there is only a single canonical address to your website – with or without www.

The web.config makes it easy for us to either enforce or remove the www subdomain using URL rewrites. There are many examples online on how to do this, but they all share 2 fundamental flaws. The rules have a direct dependency to the domain name and they don't work with both HTTP and HTTPS.

So let's see if we can create generic URL rewrite rules that can be used on any website without modifications.

Your server needs to have the URL Rewrite module installed. Chances are that it does already. Azure Websites does and so does all of my other hosting providers.

Rewrite rules need to be placed inside the <rewrite> element in web.config:

<system.webServer>
  <rewrite>
    <rules>
      <!-- My rules -->
    </rules>
  </rewrite>
</system.webServer>

So here are 2 rules that works on all domains and on both HTTP and HTTPS.

Remove WWW

This rule redirects any incoming request to www.domain.com to domain.com while preserving the HTTP(S) protocol:

<rule name="Remove WWW" patternSyntax="Wildcard" stopProcessing="true">
  <match url="*" />
  <conditions>
    <add input="{CACHE_URL}" pattern="*://www.*" />
  </conditions>
  <action type="Redirect" url="{C:1}://{C:2}" redirectType="Permanent" />
</rule>

Enforce WWW

This rule redirects any incoming request to domain.com to www.domain.com while preserving the HTTP(S) protocol:

<rule name="Enforce WWW" stopProcessing="true">
  <match url=".*" />
  <conditions>
    <add input="{CACHE_URL}" pattern="^(.+)://(?!www)(.*)" />
  </conditions>
  <action type="Redirect" url="{C:1}://www.{C:2}" redirectType="Permanent" />
</rule>

So there you have it. It's easy once you now how.

For more info on the URL Rewrite Module, see the Configuration Reference.