Language

What's New in ASP.NET 4.5 and Visual Web Developer 11 Developer Preview

By Microsoft ASP.NET Team|

ASP.NET Core Runtime and Framework

Asynchronously Reading and Writing HTTP Requests and Responses

ASP.NET 4 introduced the ability to read an HTTP request entity as a stream using the HttpRequest.GetBufferlessInputStream method. This method provided streaming access to the request entity, but it executed synchronously, which tied up a thread for the duration of a request.

ASP.NET 4.5 supports the ability to read streams asynchronously on an HTTP request entity, and the ability to flush asynchronously. ASP.NET 4.5 also gives you the ability to double-buffer an HTTP request entity, which provides easier integration with downstream HTTP handlers such as .aspx page handlers and ASP.NET MVC controllers.

Improvements to HttpRequest handling

The Stream reference returned by ASP.NET 4.5 from HttpRequest.GetBufferlessInputStream supports both synchronous and asynchronous read methods. The Stream object returned from GetBufferlessInputStream now implements both the BeginRead and EndRead methods. The asynchronous Stream methods let you asynchronously read the request entity in chunks, while ASP.NET releases the current thread in between each iteration of an asynchronous read loop.

ASP.NET 4.5 has also added a new companion method for reading the request entity in a buffered way: HttpRequest.GetBufferedInputStream. This new overload works like GetBufferlessInputStream, supporting both synchronous and asynchronous reads. However, as it reads, GetBufferedInputStream also copies the entity bytes into ASP.NET's internal buffers so that downstream modules and handlers can still access the request entity. For example, if some upstream code in the pipeline has already read the request entity using GetBufferedInputStream, you can still use HttpRequest.Form or HttpRequest.Files. This lets you perform asynchronous processing on a request (for example, streaming a large file upload to a database), but still run .aspx pages and MVC ASP.NET controllers afterward.

Asynchronously flushing a response

Sending responses to an HTTP client can take considerable time when the client is far away or has a low-bandwidth connection. Normally ASP.NET buffers the response bytes as they are created by an application. ASP.NET then performs a single send operation of the accrued buffers at the very end of request processing.

If the buffered response is large (for example, streaming a large file to a client), you must periodically call HttpResponse.Flush to send buffered output to the client and keep memory usage under control. However, because Flush is a synchronous call, iteratively calling Flush still consumes a thread for the duration of potentially long-running requests.

ASP.NET 4.5 adds support for performing flushes asynchronously using the BeginFlush and EndFlush methods of the HttpResponse class. Using these methods, you can create asynchronous modules and asynchronous handlers that incrementally send data to a client without tying up operating-system threads. In between BeginFlush and EndFlush calls, ASP.NET releases the current thread. This substantially reduces the total number of active threads that are needed in order to support long-running HTTP downloads.

Support for await and Task-Based Asynchronous Modules and Handlers

The .NET Framework 4 introduced an asynchronous programming concept referred to as a task. Tasks are represented by the Task type and related types in the System.Threading.Tasks namespace. The .NET Framework 4.5 builds on this with compiler enhancements that make working with Task objects simple. In the .NET Framework 4.5, the compilers support two new keywords: await and async. The await keyword is syntactical shorthand for indicating that a piece of code should asynchronously wait on some other piece of code. The async keyword represents a hint that you can use to mark methods as task-based asynchronous methods.

The combination of await, async, and the Task object makes it much easier for you to write asynchronous code in .NET 4.5. ASP.NET 4.5 supports these simplifications with new APIs that let you write asynchronous HTTP modules and asynchronous HTTP handlers using the new compiler enhancements.

Asynchronous HTTP modules

Suppose that you want to perform asynchronous work within a method that returns a Task object. The following code example defines an asynchronous method that makes an asynchronous call to download the Microsoft home page. Notice the use of the async keyword in the method signature and the await call to DownloadStringTaskAsync.

private async
Task ScrapeHtmlPage(object caller, EventArgs e)
 {
    WebClient wc = new WebClient();
    var result = await wc.DownloadStringTaskAsync("http://www.microsoft.com");
    // Do something with the result
}

That's all you have to write — the .NET Framework will automatically handle unwinding the call stack while waiting for the download to complete, as well as automatically restoring the call stack after the download is done.

Now say that you want to use this asynchronous method in an asynchronous ASP.NET HTTP module. ASP.NET 4.5 includes a helper method (EventHandlerTaskAsyncHelper) and a new delegate type (TaskEventHandler) that you can use to easily integrate task-based asynchronous methods with the older asynchronous programming model exposed by the ASP.NET HTTP pipeline. This example shows how:

public void Init(HttpApplication context)
 {
   // Wrap the Task-based method so that it can be used with
   // the older async programming model.
   EventHandlerTaskAsyncHelper helper =
        new EventHandlerTaskAsyncHelper(ScrapeHtmlPage);
 
        // The helper object makes it easy to extract Begin/End methods out of
        // a method that returns a Task object. The ASP.NET pipeline calls the
        // Begin and End methods to start and complete calls on asynchronous
        // HTTP modules.
        context.AddOnPostAuthorizeRequestAsync(
            helper.BeginEventHandler, helper.EndEventHandler);
    }

Asynchronous HTTP handlers

The traditional approach to writing asynchronous handlers in ASP.NET is to implement the IHttpAsyncHandler interface. ASP.NET 4.5 introduces the HttpTaskAsyncHandler asynchronous base type that you can derive from, which makes it much easier to write asynchronous handlers.

The HttpTaskAsyncHandler type is abstract and requires you to override the ProcessRequestAsync method. Internally ASP.NET takes care of integrating the Task-based return signature of ProcessRequestAsync with the older asynchronous programming model used by the ASP.NET pipeline.

The following example shows how you can easily use Task and await as part of the implementation of an asynchronous HTTP handler:

public class MyAsyncHandler : HttpTaskAsyncHandler
{
    // ...
 
    // ASP.NET automatically takes care of integrating the Task based override
    // with the ASP.NET pipeline.
    public override async Task ProcessRequestAsync(HttpContext context)
    {
        WebClient wc = new WebClient();
        var result = 
            await wc.DownloadStringTaskAsync("http://www.microsoft.com");
        // Do something with the result
    }
}

New ASP.NET Request Validation Features

By default, ASP.NET performs request validation — it examines requests to look for markup or script in fields, headers, cookies, and so on. If any is detected, ASP.NET throws an exception. This acts as a first line of defense against potential cross-site scripting attacks.

ASP.NET 4.5 makes it easy to selectively read unvalidated request data. ASP.NET 4.5 also integrates the popular AntiXSS library (formerly an external library).

Developers have frequently asked for the ability to selectively turn off request validation for their applications. For example, if your application is forum software, you might want to allow users to submit HTML-formatted forum posts and comments, but still make sure that request validation is checking everything else.

ASP.NET 4.5 introduces two features that make it easy for you to selectively work with unvalidated input: deferred request validation and access to unvalidated request data.

Deferred ("lazy") request validation

In ASP.NET 4.5, by default all request data is subject to request validation. However, you can configure the application to defer request validation until you actually access request data. (This is sometimes referred to as lazy request validation, based on terms like lazy loading for certain data scenarios.) You can configure the application to use deferred validation in the Web.config file by setting the requestValidationMode attribute to 4.5 in the httpRUntime element, as in the following example:

<httpRuntime requestValidationMode="4.5" ... />

When request validation mode is set to 4.5, request validation is triggered only for a specific request value and only when your code accesses that value. For example, if your code gets the value of Request.Form["forum_post"], request validation is invoked only for that element in the form collection. None of the other elements in the Form collection are validated. In previous versions of ASP.NET, request validation was triggered for the entire request collection when any element in the collection was accessed. The new behavior makes it easier for different application components to look at different pieces of request data without triggering request validation on other pieces.

Support for unvalidated requests

Deferred request validation alone doesn't solve the problem of selectively bypassing request validation. The call to Request.Form["forum_post"] still triggers request validation for that specific request value. However, you might want to access this field without triggering validation, because you want to allow markup in that field.

To allow this, ASP.NET 4.5 now supports unvalidated access to request data. ASP.NET 4.5 includes a new Unvalidated collection property in the HttpRequest class. This collection provides access to all of the common values of request data, like Form, QueryString, Cookies, and Url.

Using the forum example, to be able to read unvalidated request data, you first need to configure the application to use the new request validation mode:

<httpRuntime requestValidationMode="4.5" ... />

You can then use the HttpRequest.Unvalidated property to read the unvalidated form value:

var s = context.Request.Unvalidated.Form["forum_post"];

Security Note: Use unvalidated request data with care! ASP.NET 4.5 added the unvalidated request properties and collections to make it easier for you to tightly scope access to unvalidated request data. However, you must still perform custom parsing and validation on the raw request data to ensure that dangerous text is not rendered back to customers.

Anti-XSS Library

Due to the popularity of the Microsoft AntiXSS Library, ASP.NET 4.5 now incorporates core encoding routines from version 4.0 of that library.

The encoding routines are implemented by the AntiXssEncoder type in the new System.Web.Security.AntiXss namespace. You can use the AntiXssEncoder type directly by calling any of the static encoding methods that are implemented in the type. However, the easiest approach for using the new anti-XSS routines is to configure an ASP.NET application to use the AntiXssEncoder by default. To do this, add the following attribute to the Web.config file:

<httpRuntime ...
  encoderType="System.Web.Security.AntiXss.AntiXssEncoder, System.Web,
    Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

When the encoderType attribute is set to use the AntiXssEncoder type, all output encoding in ASP.NET automatically uses the new encoding routines.

These are the portions of the external AntiXSS library that have been incorporated into ASP.NET 4.5:

  • HtmlEncode, HtmlFormUrlEncode, and HtmlAttributeEncode
  • XmlAttributeEncode and XmlEncode
  • UrlEncode and UrlPathEncode (new)
  • CssEncode

Support for WebSockets Protocol

WebSockets protocol is a standards-based network protocol that defines how to establish secure, real-time bidirectional communications between a client and a server over HTTP. Microsoft has worked with both the IETF and W3C standards bodies to help define the protocol. The WebSockets protocol is supported by any client (not just browsers), with Microsoft investing substantial resources supporting WebSockets protocol on both client and mobile operating systems.

WebSockets protocol makes it much easier to create long-running data transfers between a client and a server. For example, writing a chat application is much easier because you can establish a real long-running connection between a client and a server. You do not have to resort to workarounds like periodic polling or HTTP long-polling to simulate the behavior of a socket.

ASP.NET 4.5 and IIS 8 include low-level WebSockets support, enabling ASP.NET developers to use managed APIs for asynchronously reading and writing both string and binary data on a WebSockets object. For ASP.NET 4.5, there is a new System.Web.WebSockets namespace that contains types for working with WebSockets protocol.

A browser client establishes a WebSockets connection by creating a DOM WebSocket object that points to a URL in an ASP.NET application, as in the following example:

socket = new WebSocket("ws://contoso.com/MyWebSocketApplication.ashx");

You can create WebSockets endpoints in ASP.NET using any kind of module or handler. In the previous example, an .ashx file was used, because .ashx files are a quick way to create a handler.

According to the WebSockets protocol, an ASP.NET application accepts a client's WebSockets request by indicating that the request should be upgraded from an HTTP GET request to a WebSockets request. Here's an example:

HttpContext.Current.AcceptWebSocketRequest(// WebSocket delegate goes here)

The AcceptWebSocketRequest method accepts a function delegate because ASP.NET unwinds the current HTTP request and then transfers control to the function delegate. Conceptually this approach is similar to how you use System.Threading.Thread, where you define a thread-start delegate in which background work is performed.

After ASP.NET and the upstream client have successfully completed a WebSockets handshake, ASP.NET calls your delegate and the WebSockets application starts running. The following code example shows a simple echo application that uses the built-in low-level WebSockets support in ASP.NET:

public async Task MyWebSocket(AspNetWebSocketContext context)
 {
    WebSocket socket = context.WebSocket;
    while (true)
    {
        ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);
 
        // Asynchronously wait for a message to arrive from a client
        WebSocketReceiveResult result =
            await socket.ReceiveAsync(buffer, CancellationToken.None);
 
        // If the socket is still open, echo the message back to the client
        if (socket.State == WebSocketState.Open)
        {
            string userMessage = Encoding.UTF8.GetString(buffer.Array, 0,
                result.Count);
            userMessage = "You sent: " + userMessage + " at " +
                DateTime.Now.ToLongTimeString();
            buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMessage));
 
            // Asynchronously send a message to the client
            await socket.SendAsync(buffer, WebSocketMessageType.Text,
                true, CancellationToken.None);
        }
        else { break; }
    }
}

The support in .NET 4.5 for the await keyword and asynchronous task-based operations is a natural fit for writing WebSockets applications. The code example shows that a WebSockets request runs completely asynchronously inside ASP.NET. The application waits asynchronously for a message to be sent from a client by calling await socket.ReceiveAsync. Similarly, you can send an asynchronous message to a client by calling await socket.SendAsync.

In the browser, an application receives WebSockets messages through an onmessage function. To send a message from a browser, you call the send method of the WebSocket DOM type, as shown in this example:

// Receive a string message from the server.
 socket.onmessage = function(msg)
 {
    document.getElementById("serverData").innerHTML = msg.data; 
 };
 
// Send a string message from the browser.
 socket.send(document.getElementById("msgText"));

In the future, we might release updates to this functionality that abstract away some of the low-level coding that is required in this release for WebSockets applications.

Bundling and Minification

Bundling lets you combine individual JavaScript and CSS files into a bundle that can be treated like a single file. Minification condenses JavaScript and CSS files by removing whitespace and other characters that are not required. These features work with Web Forms, ASP.NET MVC, and Web Pages.

The bundling feature hooks into the ASP.NET routing mechanism and makes it possible to reference an entire folder instead of individual files. Suppose you have the following file structure.

You might want to bundle all .js files in the Scripts folder. To do that, you can now reference the folder and append /js to the path, as in this example:

You can do the same to bundle all the .css files in the Styles folder, but instead you append /css to the path:

When files are bundled, they are first sorted alphabetically (the way they are displayed in Solution Explorer). They are then organized so that known libraries and their custom extensions (such as jQuery, MooTools and Dojo) are loaded first. For example, the final order for the bundling of the Scripts folder as shown above will be:

  1. jquery-1.6.2.js
  2. jquery-ui.js
  3. jquery.tools.js
  4. a.js

CSS files are also sorted alphabetically and then reorganized so that reset.css and normalize.css come before any other file. The final sorting of the bundling of the Styles folder as shown above will be as follows:

  1. reset.css
  2. content.css
  3. forms.css
  4. globals.css
  5. menu.css
  6. styles.css

The sorting algorithm is customizable.

You can register your own bundles in the Global.asax file in order to specify which files go into each bundle and what the exact URL will be. The following code shows how:

The custom bundle can now be referenced as in this example:

You can even override the default CSS and JavaScript bundles in order to call custom post-processing routines for the bundled files. In the following example, the built-in minification transforms are replaced with custom MyJsTransform and MyCssTransform types. The types derive from the CSS and JavaScript minifier routines, respectively, and add custom functionality.

The bundling and minification feature is built with extensibility in mind, and every part of the process can be extended or replaced.

Performance Improvements for Web Hosting

The .NET Framework 4.5 and Windows 8 introduce features that can help you achieve a significant performance boost for web-server workloads. This includes a reduction (up to 35%) in both startup time and in the memory footprint of web hosting sites that use ASP.NET.

Key performance factors

Ideally, all websites should be active and in memory to assure quick response to the next request, whenever it comes. Factors that can affect site responsiveness include:

  • The time it takes for a site to restart after an app pool recycles. This is the time it takes to launch a web server process for the site when the site assemblies are no longer in memory. (The platform assemblies are still in memory, since they are used by other sites.) This situation is referred to as "cold site, warm framework startup" or just "cold site startup."
  • How much memory the site occupies. Terms for this are "per-site memory consumption" or "unshared working set."

The new performance improvements focus on both of these factors.

Requirements for New Performance Features

The requirements for the new features can be broken down into these categories:

  • Improvements that run on the .NET Framework 4.
  • Improvements that require the .NET Framework 4.5 but can run on any version of Windows.
  • Improvements that are available only with .NET Framework 4.5 running on Windows 8.

Performance increases with each level of improvement that you are able to enable.

Some of the .NET Framework 4.5 improvements take advantage of broader performance features that apply to other scenarios as well.

Sharing Common Assemblies

Requirement: .NET Framework 4 and Visual Studio 11 Developer Preview SDK

Different sites on a server often use the same helper assemblies (for example, assemblies from a starter kit or sample application). Each site has its own copy of these assemblies in its Bin directory. Even though the object code for the assemblies is identical, they're physically separate assemblies, so each assembly has to be read separately during cold site startup and kept separately in memory.

The new interning functionality solves this inefficiency and reduces both RAM requirements and load time. Interning lets Windows keep a single copy of each assembly in the file system, and individual assemblies in the site Bin folders are replaced with symbolic links to the single copy. If an individual site needs a distinct version of the assembly, the symbolic link is replaced by the new version of the assembly, and only that site is affected.

Sharing assemblies using symbolic links requires a new tool named aspnet_intern.exe, which lets you create and manage the store of interned assemblies. It is provided as a part of the Visual Studio 11 Developer Preview SDK. (However, it will work on a system that has only the .NET Framework 4 installed, assuming you have installed the latest update.)

To make sure all eligible assemblies have been interned, you run aspnet_intern.exe periodically (for example, once a week as a scheduled task). A typical use is as follows:

aspnet_intern -mode exec -sourcedir
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET
Files" -interndir C:\ASPNETCommonAssemblies

To see all options, run the tool with no arguments.

Using multi-Core JIT compilation for faster startup

Requirement: .NET Framework 4.5

For a cold site startup, not only do assemblies have to be read from disk, but the site must be JIT-compiled. For a complex site, this can add significant delays. A new general-purpose technique in the .NET Framework 4.5 reduces these delays by spreading JIT-compilation across available processor cores. It does this as much and as early as possible by using information gathered during previous launches of the site. This functionality implemented by the System.Runtime.ProfileOptimization.StartProfile method.

JIT-compiling using multiple cores is enabled by default in ASP.NET, so you do not need to do anything to take advantage of this feature. If you want to disable this feature, make the following setting in the Web.config file:

<configuration>
  <!-- ... -->
  <system.web>
    <compilation profileGuidedOptimizations="None"  />
  <!-- ... -->  

Tuning garbage collection to optimize for memory

Requirement: .NET Framework 4.5

Once a site is running, its use of the garbage-collector (GC) heap can be a significant factor in its memory consumption. Like any garbage collector, the .NET Framework GC makes tradeoffs between CPU time (frequency and significance of collections) and memory consumption (extra space that is used for new, freed, or free-able objects). For previous releases, we have provided guidance on how to configure the GC to achieve the right balance (for example, see ASP.NET 2.0/3.5 Shared Hosting Configuration).

For the .NET Framework 4.5, instead of multiple standalone settings, a workload-defined configuration setting is available that enables all of the previously recommended GC settings as well as new tuning that delivers additional performance for the per-site working set.

To enable GC memory tuning, add the following setting to the Windows\Microsoft.NET\Framework\v4.0.30319\aspnet.config file:

<configuration>
  <!-- ... -->
  <runtime>
    <performanceScenario value="HighDensityWebHosting"  />
  <!-- ... -->  

(If you're familiar with the previous guidance for changes to aspnet.config, note that this setting replaces the old settings — for example, there is no need to set gcServer, gcConcurrent, etc. You do not have to remove the old settings.)

Prefetching for web applications

Requirement: .NET Framework 4.5 running on Windows 8

For several releases, Windows has included a technology known as the prefetcher that reduces the disk-read cost of application startup. Because cold startup is a problem predominantly for client applications, this technology has not been included in Windows Server, which includes only components that are essential to a server. Prefetching is now available in the latest version of Windows Server, where it can optimize the launch of individual websites.

For Windows Server, the prefetcher is not enabled by default. To enable and configure the prefetcher for high-density web hosting, run the following set of commands at the command line:

sc config sysmain start=auto
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters" /v EnablePrefetcher /t REG_DWORD /d 2 /f
reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Prefetcher" /v MaxPrefetchFiles /t REG_DWORD /d 8192 /f
net start sysmain

Then, to integrate the prefetcher with ASP.NET applications, add the following to the Web.config file:

<configuration>
  <!-- ... -->
  <system.web>
    <compilation enablePrefetchOptimization="true" />
  <!-- ... -->  

ASP.NET Web Forms

Strongly Typed Data Controls

In ASP.NET 4.5, Web Forms includes some improvements for working with data. The first improvement is strongly typed data controls. In Web Forms controls in previous versions of ASP.NET, you use Eval and a data-binding expression to display a data-bound value:

<ul>
    <asp:Repeater runat="server" ID="customers">
        <ItemTemplate>
            <li>
                First Name: <%# Eval("FirstName") %><br />
                Last Name: <%# Eval("LastName") %><br />
            </li>
        </ItemTemplate>
    </asp:Repeater>
</ul>

For two-way data binding, you use Bind:

<asp:FormView runat="server" ID="editCustomer">
    <EditItemTemplate>
        <div>
            <asp:Label runat="server" AssociatedControlID="firstName">
                First Name:</asp:Label>
            <asp:TextBox ID="firstName" runat="server"
                Text='<%# Bind("FirstName") %>' />
        </div>
        <div>
            <asp:Label runat="server" AssociatedControlID="lastName">
                First Name:</asp:Label>
            <asp:TextBox ID="lastName" runat="server"
                Text='<%# Bind("LastName") %>' />
        </div>
        <asp:Button runat="server" CommandName="Update" />
    </EditItemTemplate>
</asp:FormView>

At run time, these calls use reflection to read the value of the specified member and then display the result in the HTML. This approach makes it easy to data bind against arbitrary, unshaped data.

However, data-binding expressions doesn't features like IntelliSense for these member names, support for navigation (like Go To Definition), or compile-time checking of these names.

To address this issue, ASP.NET 4.5 adds the ability to declare what type of data a control is bound to. You do this using the new ModelType property. When you set this property, two new typed variables are available in the scope of data-binding expressions: Item and BindItem. Because the variables are strongly typed, you get the full benefits of the Visual Studio development experience.

The following example shows how IntelliSense works for the Item member:

For two-way data-binding expressions, use the BindItem variable:

<asp:FormView runat="server" ID="editCustomer">
    <EditItemTemplate>
        <div>
            <asp:Label runat="server" AssociatedControlID="firstName">
                First Name:</asp:Label>
            <asp:TextBox ID="firstName" runat="server"
                Text='<%# BindItem.FirstName %>' />
        </div>
        <div>
            <asp:Label runat="server" AssociatedControlID="lastName">
                First Name:</asp:Label>
            <asp:TextBox ID="lastName" runat="server"
                Text='<%# BindItem.LastName %>' />
        </div>
        <asp:Button runat="server" CommandName="Update" />
    </EditItemTemplate>
</asp:FormView>

For example, if you make a mistake, Visual Studio can offer immediate feedback:

Most controls in the ASP.NET Web Forms framework that support data binding have been updated to support the ModelType property.

Model Binding

Model binding extends data binding in ASP.NET Web Forms controls to work with code-focused data access. It incorporates concepts from the ObjectDataSource control and from model binding in ASP.NET MVC.

Selecting data

To configure a data control to use model binding to select data, you set the control's SelectMethod property to the name of a method in the page's code. The data control calls the method at the appropriate time in the page life cycle and automatically binds the returned data. There's no need to explicitly call the DataBind method.

In the following example, the GridView control is configured to use a method named GetCategories:

<asp:GridView ID="categoriesGrid" runat="server"
    ModelType="WebApplication1.Model.Category"
    SelectMethod="GetCategories" AutoGenerateColumns="false">
    <Columns>
        <asp:BoundField DataField="CategoryID" HeaderText="ID" />
        <asp:BoundField DataField="CategoryName" HeaderText="Name" />
        <asp:BoundField DataField="Description" HeaderText="Description" />
        <asp:TemplateField HeaderText="# of Products">
            <ItemTemplate><%#Item.Products.Count %></ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

You create the GetCategories method in the page's code. For a simple select operation, the method needs no parameters and should return an IEnumerable or IQueryable object. If the new ModelType property is also set to enable strongly typed data-binding expressions, the generic versions of these interfaces should be returned — IEnumerable<T> or IQueryable<T>, with the T parameter matching the type of the ModelType property (for example, IQueryable<Category>).

The following example shows the actual GetCategories code. (This example uses the Entity Framework Code First model with the Northwind sample database). The code makes sure that the query returns details of the related products for each category by way of the Include method. (This ensures that the TemplateField element in the markup displays the count of products in each category without requiring an n+1 select.)

public IQueryable<Category>
GetCategories()
{
    var db = new Northwind();
    return db.Categories.Include(c => c.Products);
 }

When the page runs, the GridView control calls the GetCategories method automatically and renders the returned data using the configured fields:

Because the select method returns an IQueryable object, the GridView control can further manipulate the query before executing it. For example, the GridView control can add query expressions for sorting and paging to the returned IQueryable object before it is executed, so that those operations are performed by the underlying LINQ provider. In this case, Entity Framework will ensure those operations are performed in the database.

The following example shows the GridView control modified to allow sorting and paging:

<asp:GridView ID="categoriesGrid" runat="server"
    AutoGenerateColumns="false"
    AllowSorting="true" AllowPaging="true" PageSize="5"
    ModelType="WebApplication1.Model.Category" DataKeyNames="CategoryID"
    SelectMethod="GetCategories"
    UpdateMethod="UpdateCategory">
    <Columns>
        <asp:BoundField DataField="CategoryID" HeaderText="ID" 
            SortExpression="CategoryID" />
        <asp:BoundField DataField="CategoryName" HeaderText="Name" 
            SortExpression="CategoryName" />
        <asp:BoundField DataField="Description" HeaderText="Description" />
        <asp:TemplateField HeaderText="# of Products">
            <ItemTemplate><%# Item.Products.Count %></ItemTemplate>
        </asp:TemplateField>
    </Columns>
    <EmptyDataTemplate>No categories found with a product count of
       <%# minProductsCount.SelectedValue %></EmptyDataTemplate>
</asp:GridView>

Now when the page runs, the control can make sure that only the current page of data is displayed and that it's ordered by the selected column:

To filter the returned data, parameters have to be added to the select method. These parameters will be populated by the model binding at run time, and you can use them to alter the query before returning the data.

For example, assume that you want to let users filter products by entering a keyword in the query string. You can add a parameter to the method and update the code to use the parameter value:

public IQueryable<Product>
GetProducts(string keyword)
 {
    IQueryable<Product> query = _db.Products;
 
    if (!String.IsNullOrWhiteSpace(keyword))
    {
        query = query.Where(p => p.ProductName.Contains(keyword));
    }
 
    return query;
 }

This code includes a Where expression if a value is provided for keyword and then returns the query results.

Value providers

The previous example was not specific about where the value for the keyword parameter was coming from. To indicate this information, you can use a parameter attribute. For this example, you can use the QueryStringAttribute class that's in the System.Web.ModelBinding namespace:

public IQueryable<Product> GetProducts([QueryString]string keyword)
 {
    IQueryable<Product> query = _db.Products;
 
    if (!String.IsNullOrWhiteSpace(keyword))
    {
        query = query.Where(p => p.ProductName.Contains(keyword));
    }
 
    return query;
 }

This instructs model binding to try to bind a value from the query string to the keyword parameter at run time, which can involve performing type conversion. (Not in this case.) If a value cannot be provided and the type is non-nullable, an exception is thrown.

The sources of values for these methods are referred to as value providers, and the parameter attributes that indicate which value provider to use are referred to as value provider attributes. Web Forms will include value providers and corresponding attributes for all of the typical sources of user input in a Web Forms application, such as the query string, cookies, form values, controls, view state, session state, and profile properties. You can also write custom value providers.

By default, the parameter name is used as the key to find a value in the value provider collection. In the example, the code will look for a query-string value named "keyword" (for example, ~/default.aspx?keyword=chef). You can specify a custom key by passing it as an argument to the parameter attribute. For example, to use the value of the query-string variable named q, you could do this:

public IQueryable<Product> GetProducts([QueryString("q")]string keyword)
 {
    IQueryable<Product> query = _db.Products;
 
    if (!String.IsNullOrWhiteSpace(keyword))
    {
        query = query.Where(p => p.ProductName.Contains(keyword));
    }
 
    return query;
 }

If this method is in the page's code, users can filter the results by passing a keyword using the query string:

Model binding accomplishes many tasks that you would otherwise have to code by hand: reading the value, checking for a null value, attempting to convert it to the appropriate type, checking whether the conversion was successful, and finally, using the value in the query. Model binding results in far less code and in the ability to reuse the functionality throughout your application.

Filtering by values from a control

Suppose you want to extend the example to let the user choose a filter value from a drop-down list. Add the following drop-down list to the markup and configure it to get its data from another method using the SelectMethod property:

<asp:Label runat="server" AssociatedControlID="categories"
    Text="Select a category to show products for: " />
<asp:DropDownList runat="server" ID="categories"
    SelectMethod="GetCategories" AppendDataBoundItems="true"
    DataTextField="CategoryName" DataValueField="CategoryID"
    AutoPostBack="true">
  <asp:ListItem Value="" Text="- all -" />
</asp:DropDownList>

Typically you would also add an EmptyDataTemplate element to the GridView control so that the control will display a message if no matching products are found:

<asp:GridView ID="productsGrid" runat="server" DataKeyNames="ProductID"
    AllowPaging="true" AllowSorting="true" AutoGenerateColumns="false"
    SelectMethod="GetProducts" >
    <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="ID" />
        <asp:BoundField DataField="ProductName" HeaderText="Name"                  
             SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Unit Price"
             SortExpression="UnitPrice" />
        <asp:BoundField DataField="UnitsInStock" HeaderText="# in Stock"
             SortExpression="UnitsInStock" />
    </Columns>
    <EmptyDataTemplate>
         No products matching the filter criteria were found</EmptyDataTemplate>
</asp:GridView>

In the page code, add the new select method for the drop-down list:

public IQueryable<Category>
GetCategories()
{
    return _db.Categories;
 }

Finally, update the GetProducts select method to take a new parameter that contains the ID of the selected category from the drop-down list:

public IQueryable<Product> GetProducts(
    [QueryString("q")] string keyword,
    [Control("categories")] int? categoryId)
 {
    IQueryable<Product> query = _db.Products;
 
    if (!String.IsNullOrWhiteSpace(keyword))
    {
        query = query.Where(p => p.ProductName.Contains(keyword));
    }
 
    if (categoryId.HasValue && categoryId > 0)
    {
        query = query.Where(p => p.CategoryID == categoryId);
    }
 
    return query;
 }

Now when the page runs is rendered, users can select a category from the drop-down list, and the GridView control is automatically rebound to show the filtered data. This is possible because model binding tracks the values of parameters for select methods and detects whether any parameter value has changed after a postback. If so, model binding forces the associated data control to rebind to the data.

HTML Encoded Data-Binding Expressions

You can now HTML-encode the result of data-binding expressions. Add a colon (:) to the end of the <%# prefix that marks the data-binding expression:

<asp:TemplateField HeaderText="Name">
    <ItemTemplate><%#:Item.Products.Name %></ItemTemplate>
</asp:TemplateField>

Unobtrusive Validation

You can now configure the built-in validator controls to use unobtrusive JavaScript for client-side validation logic. This significantly reduces the amount of JavaScript rendered inline in the page markup and reduces the overall page size. You can configure unobtrusive JavaScript for validator controls in any of these ways:

  • Globally by adding the following setting to the <appSettings> element in the Web.config file:
    <add name="ValidationSettings:UnobtrusiveValidationMode" value="WebForms" />
  • Globally by setting the static System.Web.UI.ValidationSettings.UnobtrusiveValidationMode property to UnobtrusiveValidationMode.WebForms (typically in the Application_Start method in the Global.asax file).
  • Individually for a page by setting the new UnobtrusiveValidationMode property of the Page class to UnobtrusiveValidationMode.WebForms.

HTML5 Updates

Some improvements have been made to server controls to take advantage of new features of HTML5:

The TextMode property of the TextBox control has been updated to support the new HTML5 input types like email, datetime, and so on.

The FileUpload control now supports multiple file uploads from browsers that support this HTML5 feature.

Validator controls now support validating HTML5 input elements.

Support was added for runat="server" on new HTML5 elements that have attributes that represent a URL. As a result, you can use ASP.NET conventions in URL paths, like the ~ operator to represent the application root (for example, <video runat="server" src="~/myVideo.wmv" />).

The UpdatePanel control has been fixed to support posting HTML5 input fields.

ASP.NET MVC 4

ASP.NET MVC 4 Beta is not included with Visual Studio 11 Developer Preview. You can get the ASP.NET MVC 4 Beta release by using the Web Platform Installer. For more information, see the ASP.NET MVC 4 Release Notes.

ASP.NET Web Pages 2

ASP.NET Web Pages 2 Developer Preview is not included with the Visual Studio 11 Developer Preview.  Installation details will be available soon.  For more information, see the ASP.NET Web Pages 2 Release Notes.

This section describes new and enhanced features in ASP.NET Web Pages 2 Developer Preview.

New and Updated Site Templates

Web Pages 2 updates all the existing templates from Web Pages 1 so that they run on Web Pages 2.

The Starter Site template includes the following new capabilities:

  • Mobile-friendly page rendering that uses CSS styles to render pages for smaller displays.
  • Membership and authentication enhancements. You can use OAuth and OpenID providers to let users log into your site with their Google, Yahoo, Facebook, Windows Live, or Twitter accounts. 
  • A new Personal Site template. The site is easy for developers to customize and for end users to personalize. The home page of the site lets the user set up a blog, a Twitter page, and a photos page.

Improved Input Validation

Web Pages provides improved tools for validating user input. Some of the new options include:

  • Client-side validation, which lets you validate user input using JavaScript. This avoids round trips to the server for validation and improves the performance of your application.
  • New validation classes. Classes such as System.Web.WebPages.ValidationHelper and System.Web.WebPages.Validator enable you to specify validation rules with very little code.

To validate user input using these new features, you can use an approach like the following.

  1. Reference the required jQuery files. You can do this in a page or in a _Layout.cshtml page. The jQuery files can be local or on a remote site (including a CDN, as here).
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.2.js"></script>
    <script 
      src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.8.1/jquery.validate.min.js">
      </script>
    <script src="@Href("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>
  2. In the input form, include calls to display validation messages.
    <form method="post" action="">
     
    <!-- Display a summary message about any validation issues at top of form. -->
    @Html.ValidationSummary()
     
    <!-- The Validation.GetHtml("lastName") call adds validation attributes
         to the input element. -->
    <input type="text" name="lastName" value="@Request["lastName"]"  
        @Validation.GetHtml("lastName") />
     
    <!-- Display a field-specific message about validation -- for instance,
         if a required field is empty. -->
    @Html.ValidationMessage("lastName")
  3. Specify what fields in the form are required. For example, you can specify that an input field named lastName is required by using this code at the top of the page:
    Validation.Required("lastName");
  4. Specify what type of data must go in an input field. For example, to specify that a field named quantity should contain only numbers, use code like this:
    Validation.Add("quantity", Validator.Integer());
  5. Wrap your form-processing logic inside a call to your validation rules. You typically process form input in page postback code, and this is where you can check the result of validation:
    if(IsPost)
    {
        // Wrap the postback code with a validation check.
        if (Validation.IsValid()) {
           // Do form processing here.  Validation issues are flagged
           // automatically.
        }
    }

The following example uses validation logic similar to the code in the previous examples. Here, the user has not filled in a required field:

Resource Management

Web Pages 2 includes new resource management functions that make it easy to work with scripts when you have a complex site that includes layout pages, content pages, and other source files such as helper files. The resource manager coordinates among the source files to make sure that script files are referenced correctly and efficiently on the rendered page, regardless of where scripts are called from or how many times they are called. The resource manager also renders <script> tags in the right place on a page to avoid errors that can occur if scripts are called before rendering is complete.

For example, this can be very useful if you create a helper that other developers use in their web pages. Suppose that your helper must reference a script. Instead of requiring other developers to register a script on each page that contains the helper, you can register the script in the helper file itself. The resource manager will then make sure that the script is rendered correctly when the page runs.

To use resource management features, do this:

  1. In the code that needs to reference a script file, call the Scripts.Add method and pass it the path of the script. This registers the script.
  2. In a page that will reference the code that contains the script, add a call to Scripts.GetScriptTags, which renders the <script> tags. A good place to add this call is at the end of the <body> section of the _Layout.cshtml page, if your site uses a layout page. That way, all required scripts will be referenced when pages that depend on the layout page are rendered.

Enhanced Membership and Authentication

Web Pages 2 includes new authentication options that let visitors log into your site using their credentials from social networking sites such as Google, Yahoo, Facebook, Twitter, and Windows Live. After users log in, they can associate their logins with a single account on your website. New built-in providers for OAuth and OpenID authentication make it possible to add these features to your site with just a few lines of code. If you create a site based on the Starter Site template, most of this functionality is built in and all you have to do is add and uncomment a few lines of code.

The following illustration shows the Login page of the Starter Site template. Notice that users can log in with an existing account or with an external account.

To support login from Facebook, Twitter, or Windows Live accounts, create a site using the Starter Site template and then follow these steps.

  1. Go to the application developer website for Windows Live, Facebook, or Twitter, create an application, and then record the key and "consumer secret" values.
  2. In your site, edit the _AppStart.cshtml page and uncomment the code block for the provider you want to use. The following example shows the uncommented code block for the Facebook provider in _AppStart.cshtml:
    OAuthWebSecurity.RegisterOAuthClient(
        BuiltInOAuthClient.Facebook, consumerKey: "",
        // For FB, consumerKey is called AppID
        consumerSecret: "");
  3. Assign the key value from your application to the consumerKey parameter, and assign the secret value from your application to the consumerSecret parameter.
  4. Edit the ~/Account/Login.cshtml file and uncomment the <fieldset> element near the end of the file that wraps the input buttons for Facebook, Twitter, and Windows Live. This will enable users to see these input buttons on the Login page and submit their logins to those sites. The uncommented <fieldset> element looks like this:
    <fieldset>
        <legend>Log in using another service</legend>
        <input type="submit" name="provider" id="facebook"value="Facebook"
            title="Log in using your Facebook account." />
        <input type="submit" name="provider" id="twitter" value="Twitter"
            title="Log in using your Twitter account." />
        <input type="submit" name="provider" id="windowsLive"
            value="WindowsLive"
            title="Log in using your Windows Live account." />
    </fieldset>
  5. Edit the ~/Account/AssociateServiceAccount.cshtml file and uncomment the same <fieldset> element that you uncommented in the Login file. This lets users associate a login with an existing account on your website.

The following image shows the Facebook login page after you've done these steps and after a user has clicked the Facebook icon on the login page:

 

Side-by-side Execution

Web Pages 2 lets you run Web Pages 1 applications and Web Pages 2 applications on the same computer. Note the following:

  • By default, new websites based on the site templates run on Web Pages 2.
  • Existing Web Pages 1 websites continue to run on Web Pages 1.

To run a Web Pages 1 site as a Web Pages 2 site, you have these options:

  • Copy all the Web Pages 2 assemblies from the installation folder (for example, C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v2.0\Assemblies) to the bin folder of your website. This is the simplest approach and is recommended for most users.

    -or-

  • Update the web.config file of your website with an entry like the following one:
    <?xml version="1.0"?>
    <configuration>
        <appSettings>
            <add key="webPages:Version" value="2.0"/>
        </appSettings>
    </configuration>

Mobile Device Rendering

Increasingly, visitors view your sites using different devices and display sizes, often on mobile devices. Web Pages 2 adds features for rendering content on mobile (or other non-desktop) devices.

The System.Web.WebPages namespace contains the following classes that let you work with display modes: DefaultDisplayMode, DisplayInfo, and DisplayModes. You can use these classes directly and write code that renders the right output for specific devices. For example, you can write code in your web page code that responds differently based on what kind of device is making a request. You can also create custom display modes that are tailored to recognize specific devices.

Alternatively, you can create mobile-specific pages by using a file-naming pattern like this: FileName.Mobile.cshtml. For example, you can create two versions of a page, one named MyFile.cshtml and one named MyFile.Mobile.cshtml. At run time, when a mobile device requests MyFile.cshtml, Web Pages renders the content from MyFile.Mobile.cshtml. Otherwise, MyFile.cshtml is rendered.

The following two screen shots show a file named Page1.cshtml rendered in a desktop browser and in a mobile-browser simulator.

A desktop browser requests Page1.cshtml:

An Apple iPhone simulator requests Page1.cshtml, but Page1.Mobile.cshtml is rendered:

The Maps Helper

The Maps helper (that is, a new class named Microsoft.Web.Helpers.Maps) is included with the updated ASP.NET Web Helpers Library. You can use the Maps class to render maps on your website based on the Bing, Google, Yahoo, or MapQuest mapping engines.

To use the Maps class, you must first install the version 2 of the Web Helpers Library, which will be available soon through the Nuget package manager. 

The basic process for using the Maps class is to make a call to the mapping engine that you want to use. You pass parameters like a street address or map coordinates, a key value (if the map engine requires it), and optional parameters to configure the appearance of the rendered map.

The following example shows how to call the Google maps provider. In this case, the only required parameter is a street address; all other parameters are optional.

@Maps.GetGoogleHtml("One Microsoft Way, Redmond, WA 98052");

The other map provider calls work similarly (@Maps.GetBingHtml, @Maps.GetYahooHtml, @Maps.GetMapQuestHtml).

The following image shows a map rendered by a call to the Google maps engine:

Visual Web Developer 11 Developer Preview

This section provides information about improvements for web development in Visual Web Developer 11 Developer Preview and Visual Studio 11 Developer Preview.

HTML Editor

Smart Tasks

In Design view, complex properties of server controls often have associated dialog boxes and wizards to make it easy to set them. For example, to add a data source to a Repeater control or add columns to a GridView control.

However, this type of UI help for complex properties has not been available in Source view. Therefore, Visual Studio 11 introduces Smart Tasks for Source view. Smart Tasks are context-aware shortcuts for commonly used features in the C# and Visual Basic editors.

For ASP.NET Web Forms controls, Smart Tasks appear on server tags as a small glyph when the insertion point is inside the element:

The Smart Task expands when you click the glyph or press CTRL+. (dot), just as in the code editors. It then displays shortcuts that are similar to the Smart Tasks in Design view.

For example, the Smart Task in the previous illustration shows the GridView Tasks options. If you choose Edit Columns, the following dialog box is displayed:

Filling in the dialog box sets the same properties you can set in Design view. When you click OK, the markup for the control is updated with the new settings:

WAI-ARIA support

Writing accessible websites is becoming increasingly important. The WAI-ARIA accessibility standard defines how developers should write accessible websites. This standard is now fully supported in Visual Studio.

For example, the role attribute now has full IntelliSense:

The WAI-ARIA standard also introduces attributes that are prefixed with aria- that let you add semantics to an HTML5 document. Visual Studio also fully supports these aria- attributes:

New HTML5 snippets

To make it faster and easier to write commonly used HTML5 markup, Visual Studio includes a number of snippets. An example is the video snippet:

To invoke the snippet, press Tab,Tab when the element is selected in IntelliSense:

This produces a snippet that you can easily customize.

Extract to user control

In large web pages, it can be a good idea to move individual pieces into user controls. This form of refactoring can help increase the readability of the page and can simplify the page structure.

To make this easier, when you edit Web Forms pages in Source view, you can now select text in a page, right-click it, and then choose Extract to User Control:

IntelliSense for code nuggets in attributes

Visual Studio has always provided IntelliSense for server-side code nuggets in any page or control. Now Visual Studio includes IntelliSense for code nuggets in HTML attributes as well.

This makes it easier to create data-binding expressions:

Automatic renaming of matching tag when you rename an opening or closing tag

If you rename an HTML element (for example, you change a div tag to be a header tag), the corresponding opening or closing tag also changes in real time.

This helps avoid the error where you forget to change a closing tag or change the wrong one.

Event handler generation

Visual Studio now includes features in Source view to help you write event handlers and bind them manually. If you are editing an event name in Source view, IntelliSense displays <Create New Event>, which will create an event handler in the page's code that has the right signature:

By default, the event handler will use the control's ID for the name of the event-handling method:

The resulting event handler will look like this (in this case, in C#):

Smart indent

When you press Enter while inside an empty HTML element, the editor will put the insertion point in the right place:

If you press Enter in this location, the closing tag is moved down and indented to match the opening tag. The insertion point is also indented:

Auto-reduce statement completion

The IntelliSense list in Visual Studio now filters based on what you type so that it displays only relevant options:

IntelliSense also filters based on the title case of the individual words in the IntelliSense list. For example, if you type "dl", both dl and asp:DataList are displayed:

This feature makes it faster to get statement completion for known elements.

JavaScript Editor

The JavaScript editor in Visual Studio 11 Developer Preview is completely new and it greatly improves the experience of working with JavaScript in Visual Studio.

Code outlining

Outlining regions are now automatically created for all functions, allowing you to collapse parts of the file that aren't pertinent to your current focus.

Brace matching

When you put the insertion point on an opening or closing brace, the editor highlights the matching one.

Go to Definition

The Go to Definition command lets you jump to the source for a function or variable.

ECMAScript5 support

The editor supports the new syntax and APIs in ECMAScript5, the latest version of the standard that describes the JavaScript language.

DOM IntelliSense

IntelliSense for DOM APIs has been improved, with support for many new HTML5 APIs including querySelector, DOM Storage, cross-document messaging, and canvas. DOM IntelliSense is now driven by a single simple JavaScript file, rather than by a native type library definition. This makes it easy to extend or replace.

VSDOC signature overloads

Detailed IntelliSense comments can now be declared for separate overloads of JavaScript functions by using the new <signature> element, as shown in this example:

function GetOrSet(key, value)
{
    /// <signature>
    ///     <summary>Gets the value</summary>
    ///     <param name="key" type="String">The key to get the value for</param>
    ///     <returns type="String" />
    /// </signature>
    /// <signature>
    ///     <summary>Sets the value</summary>
    ///     <param name="key" type="String">The key to set the value for</param>
    ///     <param name="value" type="String">The value to set</param>
    ///     <returns type="MyLib"/>
    /// </signature>

    if (value) {
        values[key] = value;
        return this;
    } else {
        return values[key];
    }
}

Implicit references

You can now add JavaScript files to a central list that will be implicitly included in the list of files that any given JavaScript file or block references, meaning you'll get IntelliSense for its contents. For example, you can add jQuery files to the central list of files, and you'll get IntelliSense for jQuery functions in any JavaScript block of file, whether you've referenced it explicitly (using /// <reference />) or not.

CSS Editor

Auto-reduce statement completion

The IntelliSense list for CSS now filters based on the CSS properties and values supported by the selected schema.

IntelliSense also supports title case searches:

Hierarchical indentation

The CSS editor uses indentation to display hierarchical rules, which gives you an overview of how the cascading rules are logically organized. In the following example, the #list a selector is a cascading child of list and is therefore indented.

The following example shows a more complex inheritance:

The indentation of a rule is determined by its parent rules. Hierarchical indentation is enabled by default, but you can disable it the Options dialog box (Tools, Options from the menu bar):

CSS hacks support

Analysis of hundreds of real-world CSS files shows that CSS hacks are very common, and now Visual Studio supports the most widely used ones. This support includes IntelliSense and validation of the star (*) and underscore (_) property hacks:

Typical selector hacks are also supported so that hierarchical indentation is maintained even when they are applied. A typical selector hack used to target Internet Explorer 7 is to prepend a selector with *:first-child + html. Using that rule will maintain the hierarchical indentation:

Vendor specific schemas (-moz-, -webkit)

CSS3 introduces many properties that have been implemented by different browsers at different times. This has forced developers to code for specific browsers by using vendor-specific syntax.

Commenting and uncommenting support

You can now comment and uncomment CSS rules using the same shortcuts that you use in the code editor (Ctrl+K,C to comment and Ctrl+K,U to uncomment).

Color picker

In previous versions of Visual Studio, IntelliSense for color-related attributes consisted of a drop-down list of named color values. That list has been replaced by a full-featured color picker.

When you enter a color value, the color picker is displayed automatically and presents a list of previously used colors followed by a default color palette. You can select a color using the mouse or the keyboard.

The list can be expanded into a complete color picker. The picker lets you control the alpha channel by automatically converting any color into RGBA when you move the opacity slider:

Snippets

Snippets in the CSS editor make it easier and faster to create cross-browser styles. Many CSS3 properties that require browser-specific settings have now been rolled into snippets.

CSS snippets support advanced scenarios (like CSS3 media queries) by typing the at-symbol which, will show the IntelliSense list.

When you select @media value and press Tab, the CSS editor inserts the following snippet:

As with snippets for code, you can create your own CSS snippets.

Custom regions

Named code regions, which are already available in the code editor, are now available for CSS editing. This lets you easily group related style blocks.

When a region is collapsed it displays the name of the region:

Page Inspector

Page Inspector is a tool that renders a web page (HTML, Web Forms, ASP.NET MVC, or Web Pages) directly within the Visual Studio IDE and lets you examine both the source code and the resulting output. For ASP.NET pages, Page Inspector lets you determine which server-side code has produced the HTML markup that is rendered to the browser.

Page Inspector is not included with Visual Studio 11 Developer Preview. To get Page Inspector Developer Preview, install it using Web Platform Installer. For more information, see Page Inspector v1 Developer Preview Release Notes.

Publishing

Publish profiles

In Visual Studio 2010, publishing information for Web application projects is not stored in version control and is not designed for sharing with others. In Visual Studio 11 Developer Preview, the format of the publish profile has been changed. It has been made a team artifact, and it is now easy to leverage from builds based on MSBuild. Build configuration information is in the Publish dialog box so that you can easily switch build configurations before publishing.

Publish profiles are stored in the PublishProfiles folder. The location of the folder depends on what programming language you are using:

  • C#: Properties\PublishProfiles
  • Visual Basic: My Project\PublishProfiles

Each profile is an MSBuild file. During publishing, this file is imported into the project's MSBuild file. In Visual Studio 2010, if you want to make changes to the publish or package process, you have to put your customizations in a file named ProjectName.wpp.targets. This is still supported, but you can now put your customizations in the publish profile itself. That way, the customizations will be used only for that profile.

You can now also leverage publish profiles from MSBuild. To do so, use the following command when you build the project:

msbuild.exe project.csproj /t:WebPublish /p:PublishProfile=ProfileName

The project.csproj value is the path of the project, and ProfileName is the name of the profile to publish. Alternatively, instead of passing the profile name for the PublishProfile property, you can pass in the full path to the publish profile.

ASP.NET precompilation and merge

For Web application projects, Visual Studio 11 Developer Preview adds an option on the Package/Publish Web properties page that lets you precompile and merge your site's content when you publish or package the project. To see these options, right-click the project in Solution Explorer, choose Properties, and then choose the Package/Publish Web property page. The following illustration shows the Precompile this application before publishing option.

When this option is selected, Visual Studio precompiles the application whenever you publish or package the web application. If you want to control how the site is precompiled or how assemblies are merged, click the Advanced button to configure those options.

IIS Express

The default web server for testing web projects in Visual Studio is now IIS Express. The Visual Studio Development Server is still an option for local web server during development, but IIS Express is now the recommended server. The experience of using IIS Express in Visual Studio 11 Developer Preview is very similar to using it in Visual Studio 2010 SP1.

Disclaimer

This is a preliminary document and may be changed substantially prior to final commercial release of the software described herein.

The information contained in this document represents the current view of Microsoft Corporation on the issues discussed as of the date of publication. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of publication.

This White Paper is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS DOCUMENT.

Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation.

Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.

Unless otherwise noted, the example companies, organizations, products, domain names, e-mail addresses, logos, people, places and events depicted herein are fictitious, and no association with any real company, organization, product, domain name, email address, logo, person, place or event is intended or should be inferred.

© 2011 Microsoft Corporation. All rights reserved.

Microsoft and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.

The names of actual companies and products mentioned herein may be the trademarks of their respective owners.

Author Information

Microsoft ASP.NET Team

Microsoft ASP.NET Team – ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.