What’s New in ASP.NET Web Forms in .NET 4.6

Posted by: Rion Williams , on 5/6/2015, in Category ASP.NET
Views: 42397
Abstract: ASP.NET Web Forms isn’t dying anytime soon. This article discusses Web Forms role within the new Microsoft development ecosystem and introduces some of the new features available within Web Forms.

With the release of the latest iteration of the .NET Framework edging closer and closer, the Microsoft development community has been buzzing about all of the new features, changes and improvements coming to MVC, but what about Web Forms and its future? Is it going the way of Classic ASP or Silverlight? Should current Web Forms developers be worried?

No, they shouldn’t.

Today, we will discuss Web Forms’ role within the new development ecosystem, introduce some of the latest features available within Web Forms applications and demonstrate that the future of Web Forms is still a bright one.

Framework Changes and the Role of Web Forms

With the release of .NET 5, the Microsoft development ecosystem is going to experience quite a bit of change. The latest version of the widely popular runtime framework was a complete re-write of .NET from the ground-up. This project was undertaken to accomplish various architectural goals (i.e. cross platform applications, increased modularity etc.), provide additional flexibility to its developers and ultimately provide the best possible technology for building modern web applications.

This article is published from the DotNetCurry .NET Magazine – A Free High Quality Digital Magazine for .NET professionals published once every two months. Subscribe to this eMagazine for Free and get access to hundreds of free .NET tutorials from experts

Many of these changes revolved around the familiar System.Web.dll, which is a core component of Web Forms and an integral part of web development within the .NET framework. The rewrite removed this dependency and introduced all kinds of new revolutionary features for more recent technologies like ASP.NET MVC, but it essentially removed the core component of Web Forms and left it with an uncertain future.

This scenario probably sounds a bit scary for Web Forms developers. Why would Microsoft seemingly abandon its most mature and widely used development technology? The answer is that they aren’t. While everyone has been discussing the new changes in .NET 5, Microsoft has also been hard at work developing .NET 4.6, another version of the framework to continue to support and improve Web Forms moving forward.

Note: It should be noted that all of the code and features discussed within this article was written using Preview builds of Visual Studio 2015, Windows 10 and the .NET Framework. As a result of this, syntax, features and functionality may change prior to the publication of this article or the release builds of any of the aforementioned products. Some of the new features might not “just work” at present, but they are expected to work within the final release.

ASP.NET Web Forms Improvements in .NET 4.6

There are several new features available for Web Forms within .NET 4.6 that will focus on improving performance, development time and efficiency within Web Forms applications. Some of the features that will be focused on within this article include:

  • HTTP2 Support
  • Roslyn Code DOM Compilers
  • Asynchronous Model Binding

Developers can take advantage of some of these features by downloading the latest version of Visual Studio 2015 (currently in RC), which comes packaged with the latest versions of both branches of the framework: .NET 4.6 and .NET 5.0.

HTTP2 Support to Improve Performance

HTTP is a protocol that has been around for quite a while and needless to say, the landscape of the web has changed significantly during that period. Web sites and applications are far more complex than they were in the 90s and the protocol that handles this information interchange needed a make-over to adapt to these changing demands. This is where HTTP2 comes in with a single goal in mind: to improve web site performance.

Based on Google’s SPDY protocol HTTP2 was designed with improving the performance and load times of sites by reducing latency as much as possible through header compression, leveraging server-based push technologies and parallel loading support for page elements over a single connection. The positive impact from these changes can be immediately seen when using a browser that supports the HTTP2 protocol and the benefits should keep both servers and end-users happy.

While reading about these benefits might sound nice, it’s much more favorable to actually see the impact that they can have on a web site or application. In the next section, we will walk through an example of using HTTP2 within a Web Forms application running on IIS in .NET 4.6.

Seeing HTTP2 in Action within Web Forms Applications

In order to take advantage of HTTP2, we will need to build an application that is capable of supporting it. Which means that the following dependencies will be required for this example:

  • Windows 10 Preview – At the time of writing, IIS only supports HTTP2 while running on Windows 10.
  • Visual Studio 2015 – Visual Studio 2015 is required for building .NET 4.6 applications.

Open Visual Studio 2015 and create a new Web Forms project through the following steps:

1. Open Visual Studio 2015 on a machine running Windows 10.

2. Create a new Web Forms project through the File > New Project dialog.

3. Ensure you are targeting .NET Framework 4.6 through the available dropdown in the New Project dialog.

4. Name and create your new ASP.NET Web Application project by choosing it from the list of available templates.

5. Choose the Empty Project template and add the appropriate Web Forms references by clicking the Web Forms checkbox.

The next step will be to construct a very basic Web Forms page that consists of a collection of images. The actual content will not make much of a difference at all, we merely want to see how the requests differ between HTTP and HTTP2.

An example Web Form to demonstrate this might appear as follows:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="HTTP2Example.HTTP2Example" %>



    HTTP2 Support in .NET 4.6


    
        
        
        
        
        
        
    



Next, if you run the application within Visual Studio, you should be presented with it in your default browser as expected. We aren’t terribly concerned with the actual appearance of the page at this point, we are more interested in what is going on behind the scenes. To take a glimpse into this, we will take advantage of using the Developer Tools available within most modern browsers.

With the previously created Web Form open, press F12 within the browser to display the Developer Tools and select the Network tab that appears along the top, and refresh the page. You’ll see that initial request will be made with the browser parsing all of the HTML, and then the requests for the images will begin coming through:

http1-request

Figure 1: Requests loaded through HTTP

By examining the requests that were loaded through HTTP in Figure 1, you can see that the first set of images were loaded as expected, however any subsequent requests required previous requests to complete prior to beginning.

Most browsers can generally handle a small number of concurrent connections to a single domain at a given time, which can be fine for most scenarios. However, for a page that contains a large number of elements (or at least more than the number of maximum connections), the other elements will have to wait for an available connection before being loaded. The example above demonstrates that even while loading just eleven images, it took more than three seconds before the final image even began to download and would be far worse as the number of resources increased. Any delays because of this can often be perceived as slowness by the end-user, when in fact it is simply a limitation of the browser and protocol.

Note: In most browsers, HTTP2 will be supported by default and used if available. If you are running IIS and using Internet Explorer 11, it should be noted that HTTP2 is only supported over secure connections at present. In other browsers, you may need to explicitly enable it.

Let’s now see what type of benefits and improvements that switching the protocol over to HTTP2 yields for the exact same page. In order to take advantage of the protocol, we will need to change the protocol within the address bar from http to https and refresh the page, which should enable Internet Explorer to meet its requirements to use HTTP2 as follows:

http2-request

Figure 2: Requests being loaded through HTTP2

As you can see in Figure 2, the Developer Tools yield a significantly different shape for requests made using HTTP2. You can see that all of the requests were created and loaded in parallel, eliminating any delays from the perspective of the user.

As the HTTP2 request loads, we can see that the Developer Tools now displays a less staggered appearance and may indicate that the HTTP 2 protocol was used for each request. This indicates that all of the requested images were loaded in parallel as opposed to synchronously. Further examination will reveal that the final image began downloading in just 10 milliseconds, which is a significant improvement over HTTP and one that will certainly be noticed by end users.

The introduction of HTTP2 support with .NET 4.6 and IIS should yield significant performance benefits on both existing and future Web Forms applications with little to no changes on the part of the developer.

Leveraging New Language Features in Web Forms using the Roslyn Code DOM Compiler

The Roslyn compiler is arguably one of the cornerstones of a majority of the widespread changes and advances within the .NET ecosystem over the past few years and it’s a focal point for the upcoming changes within both .NET 4.6 and .NET 5.0. Roslyn began as an attempt to re-write the previously available compilers (and their related services) for both C# and Visual Basic actually using those respective languages. This would allow Roslyn to actually expose information regarding what was going on behind the scenes during the compilation process and even provide APIs to allow the developer to access this same data.

Exposure to these APIs has provided developers with the ability to generate and further optimize their existing code by receiving feedback from the compiler itself and allows for really cool features such as dynamic compilation, which opens all sorts of new doors for developing ASP.NET applications like the available Code DOM compilers.

In .NET 4.6, Web Forms applications will now use the Roslyn Code DOM compilers natively, which allows developers to write code and take advantage of many of the new available language features such as those found within C# 6.0 that might not otherwise be available using the previous compiler.

Compilation on the Fly within Web Forms in 4.6

Prior to .NET 4.6, Web Forms applications would use the framework-based Code DOM compilers to perform any compilation operations at runtime. This older compiler doesn’t currently understand how to use any of the newer language features available like Roslyn does, so you’ll be bombarded with errors if you attempt to use any of them without it.

Let’s take a look at a very basic ASP.NET Web Forms application that attempts to use a few of the following C# 6.0 features:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="RoslynCodeDOMExample.RoslynCodeDOMExample" %>



    Roslyn Code DOM Compiler Support in .NET 4.6


    
Example One: String Interpolation
<% // Define two example variables to concatenate using C# 6.0 String Interpolation var firstName = "Rion"; var lastName = "Williams"; // Attempt to use the C# 6.0 String Interpolation feature for formatting strings var output = $"{lastName}, {firstName}"; %> <%= output %>
Example Two: Exception Filters
<% // Define a variable that will be "caught" by in the Exception Filter var x = 42; try { // Define a null object object result = null; // Trigger a null reference exception var stringifiedResult = result.ToString(); } catch(NullReferenceException ex) if (x == 42){ // This will explicitly handle the exception Response.Write("The exception was handled in the Null Reference block as x was 42."); } catch(Exception ex) { // Otherwise fall through to this block and handle here Response.Write($"x was {x} and not 42, so it was handled in the generic catch block."); } %>
Example Three: nameof Expressions
<% // The nameof keyword can be used to help avoid the use of "magic strings" within your C# code by // resolving the appropriate type of a particular object as a string. var nameofExample = nameof(Request.Cookies); %> <%= nameofExample %>

If your application isn’t currently running on .NET 4.6 or it isn’t leveraging the Roslyn compiler through another route such as a NuGet package, your application should build, but then it will throw a compilation error when the newer language features are loaded:

codedom-compilation
Figure 3: Compilation errors will be thrown when new features aren’t recognized

On the other hand, if we use that same application and target .NET 4.6, we can see that it compiles just as it did previously, however when it hits the newer C# 6.0 features, it uses Roslyn to compile and handle this new code on the fly and process it as expected:

codedom-output
Figure 4: The Roslyn Code DOM compiler in action

Just when you thought your application would see the new language features that you are using and throw a compilation error, the Roslyn Code DOM compiler steps in and compiles these new features on the fly without issue.

While a feature like String Interpolation probably isn’t a game-changer, it is just one of the many new features introduced in C# 6.0. Since you now have access to all of these via the Code DOM compilers, try experimenting with some of the more practical ones like the null-conditional operator and exception filters.

It should be noted that you should be able to use the Microsoft.CodeDom.Providers.DotNetCompilerPlatform NuGet package available from within your application if you aren’t currently targeting .NET 4.6 or beyond to add this additional functionality in without committing to a new framework version.

Added Support for Asynchronous Model Binding

.NET 4.5 introduced the popular task-based async / await methods that have allowed developers to easily create asynchronous functionality within their applications. This same version of the framework also gave rise to model binding as well, which allows a variety of data-specific controls (e.g. GridViews, Repeaters, ListViews, etc.) to be populated by actual methods as opposed to data sources. Both of these changes provided developers with an improved flexibility about how they go about designing their applications and use them.

With the release of .NET 4.6, both of these concepts are expanded upon with the introduction of asynchronous model binding support. This added support allows you to decorate the various methods that govern your data sources with async and await calls, thereby creating a more asynchronous and efficient application.

Binding Data to Entity Framework Easily and Asynchronously

Although ADO.NET connections can still be seen in a wide range of applications, the rise of ORMs in recent years has made interacting with data much easier without being an SQL wizard. Entity Framework and Code First provide several built-in methods that allow developers to interact with their data asynchronously. For this reason, asynchronous model binding can be a helpful feature for developers working with Entity Framework as well as those that simply want to make their data transactions a bit more efficient.

Getting started with asynchronous model binding is quite easy and doesn’t demand too much work on your part for either new or existing applications. You’ll just need to ensure that the following things happen:

  • Ensure that your application is targeting .NET 4.6 or higher so that you can take advantage of this feature.
  • Set the Async directive set to “true” at the top of any of your pages that are targeting asynchronous methods.
  • Decorate any asynchronous methods with the appropriate async / await keywords (i.e. add async to the signature of the method and preface any asynchronous calls within it using await).

We can demonstrate this same functionality by constructing a single ASPX page that hooks into an imaginary data context and handles all of the necessary CRUD operations that you commonly find within an application in an asynchronous manner:

<%@ Page Language="C#" AutoEventWireup="true" Async="true" CodeBehind="Default.aspx.cs" Inherits="AsynchronousModelBindingExample.Default" %>



Asynchronous Model Binding Support in .NET 4.6


p.IsFunctioning) %>" runat="server">

There are a few things worth noting within this otherwise traditional GridView, especially if you are unfamiliar with the Model Binding that was introduced in .NET 4.5:

  • ItemType – This is a strongly-typed class that corresponds to the objects that will be used to populate the rows within the Grid.
  • Select, Update and Delete Methods – Each of these methods is going to point to a server-side method defined within the code-behind that is used to handle performing the respective operation (e.g. retrieving data, updating or deleting records).
  • Item within the ItemTemplate – The Item keyword can be used within Item templates to function as a strongly-typed object, similar to the iterator within a foreach loop through a collection.

We can take a look behind the scenes at the code-behind to see the asynchronous events that each of these various methods (e.g. Select, Update and Delete) correspond to and how they are built within an asynchronous environment:

using AsynchronousModelBindingExample.Models;
using System;
using System.Data.Entity;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web.UI.WebControls;

namespace AsynchronousModelBindingExample
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        public async Task GetWidgets()
        {
            // Create your data context to access your data (replace with your existing context
            // in your real-world application)
            using (var context = new ImaginaryContext())
            {
                // Build a query to pull your widgets (including the Parts related to each Widget)
                var query = context.Widgets.Include("Parts");
                // Return a SelectResult to bind the data to the GridView (using the asyncronous 
                // ToListAsync() method exposed by Entity Framework)
                return new SelectResult(query.Count(), await query.ToListAsync());
            }
        }

        public async Task UpdateWidget(Guid widgetId, CancellationToken token)
        {
            using (var context = new ImaginaryContext())
            {
                // Attempt to retrieve your current Widget through the context
                var widget = await context.Widgets.FirstAsync(w => w.WidgetID == widgetId);

                // Check if the requested Widget was found
                if (widget != null)
                {
                    // Update your Widget here, adding any custom logic as necessary
                    TryUpdateModel(widget);
                    // Ensure the model is valid, if so update and save the Widget
                    if (ModelState.IsValid)
                    {
                        await context.SaveChangesAsync();
                    }
                }
                // Otherwise, the widget was not found, display an error to the user
                ModelState.AddModelError("", $"The Widget with ID '{widgetId}' was not found");
            }
        }

        public async Task DeleteWidget(Guid widgetId, CancellationToken token)
        {
            using (var context = new ImaginaryContext())
            {
                // Attempt to retrieve your current Widget through the context
                var widget = await context.Widgets.FirstAsync(w => w.WidgetID == widgetId);

                // Check if the requested Widget was found
                if (widget != null)
                {
                    // Delete the requested Widget
                    context.Widgets.Remove(widget);
                    await context.SaveChangesAsync();
                }
                // Otherwise, the widget was not found, display an error to the user
                ModelState.AddModelError("", $"The Widget with ID '{widgetId}' was not found");
            }
        }
    }
}

That’s really it. After updating the return types for each of the methods to leverage Task objects and indicating which asynchronous methods should be awaited, everything should just work. The addition of these asynchronous features will allow developers to quickly and easily take advantage of the benefits that the async / await keywords provide with relatively little change to their applications.

Summary

The improvements that were introduced within this article should hopefully serve as a reminder that Web Forms is still an important component of the ASP.NET ecosystem and that Microsoft is dedicated to continuing to support and improve upon it. We can take one last glance to see exactly how each of them affected the Web Forms developer:

  • HTTP2 Protocol Support should aid in improving performance and reducing server latency for all Web Forms applications moving forward; a benefit that should be felt by both servers and end-users alike.
  • The Roslyn Code DOM Compiler will allow developers to take advantage of brand-new language features found in both C# and Visual Basic and easily integrate them into their applications on the fly.
  • Asynchronous Model Binding now provides Web Forms developers with the ability to easily take advantage of the benefits of Model Binding coupled with async / await support to build more efficient applications.

These recent enhancements, coupled with the entire 4.6 branch being dedicated to preserving it, should allow Web Forms developers to breathe a sigh of relief. Web Forms isn’t dying. While it may no longer have the spotlight shown upon it as it once did, it’s continuing to improve and it looks like it will still play an active part in .NET development for the foreseeable future.

Download the entire source code from GitHub at bit.ly/dncm18-aspwebforms

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Rion Williams is a Senior Software Developer and Microsoft MVP with a passion for building cool applications, helping fellow developers within the community and staying on the edge emerging development trends. If you want to see what he is up to, you can follow him Twitter as @rionmonster, visit his blog at rion.io or if it’s important enough, send him an e-mail (e-mail address left off as an exercise for the reader)


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Dana Ringrose on Friday, May 15, 2015 1:46 AM
Fantastic article RIon. I have been reading your forum posts from quite some time now and am thrilled to see you here as well.