4.0 New Features
4.0 New Features
4.0 New Features
In this article, I want to give an overview of the new features of ASP.NET that are
included in the .NET framework 4 and Visual Studio 2010. I will explain these new
features from the problem/solution strategy.
New features
Context: What is cache? A cache is a memory area where the output of operations is
stored in order to improve the performance. When we need this output again, we look
for in the cache unlike to execute the operations again.
Problem: This approach has a memory limitation. If your servers are experiencing heavy
traffic, then the memory consumed by the output caching can compete with memory
demands from other applications or components of your own application.
Solution: The extensible output caching enables you to configure one or more custom
output-cache providers for diverse persistence mechanisms such as hard drives (locally
or remotely), cloud storage and distributed cache engines as Velocity.
Implementation strategy: You can create a custom output-cache provider as a class that
derives from the newSystem.Web.Caching.OutputCacheProvider type. For example, let's
create a provider using AppFabric (Velocity) as shown in the Listing 1.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Caching;
using Microsoft.ApplicationServer.Caching;
namespace _01WebAppOutputCacheDemo.OutputCacheProviders
{
public class VelocityCacheProvider : OutputCacheProvider, IDisposable
{
private DataCache dataCache;
const String OutputCacheName = "OutputCache";
public VelocityCacheProvider()
{
DataCacheFactory factory = new DataCacheFactory();
this.dataCache = factory.GetCache(OutputCacheName);
}
public override object Add(string key, object entry, DateTime utcExpiry)
{
this.dataCache.Add(key, entry, utcExpiry - DateTime.UtcNow);
return entry;
}
public override object Get(string key)
{
return this.dataCache.Get(key);
}
public override void Remove(string key)
{
this.dataCache.Remove(key);
}
public override void Set(string key, object entry, DateTime utcExpiry)
{
throw new NotImplementedException();
}
public void Dispose()
{
this.dataCache = null;
}
}
}
Listing 1
You can then configure the provider in the Web.config file by using the new provider
subsection of the outputCache element (see Listing 2).
<caching>
<outputCache defaultProvider="AspNetInternalProvider">
<providers>
<add name="VelocityCache"type="_01WebAppOutputCacheDemo.OutputCacheProviders.V
elocityCacheProvider, 01WebAppOutputCacheDemo"/>
</providers>
</outputCache>
</caching>
Listing 2
Moreover, you can select different output-cache providers per control and per request.
The easiest way to choose a different output-cache provider for different Web user
controls is to do so declaratively by using the new providerName attribute in a control
directive (see Listing 3).
Listing 3
Instead of declaratively specifying the provider, you override the new
GetOuputCacheProviderName method in the Global.asax file to programmatically
specify which provider to use for a specific request (see Listing 4).
Listing 4
Context: It is common practice in Web applications to move pages and other content
around over time, which can lead to an accumulation of stale links in search engines.
Solution: ASP.NET 4 adds a new RedirectPermanent method that makes it easy to issue
HTTP 301 Moved Permanently responses.
Response.RedirectPermanent("newlocation/page.aspx");
Listing 5
Context: It is common practice in Web applications to store objects in the session state.
Problem: Depending on how much information a developer saves in session state, the
size of the serialized data can grow quite large.
Solution: ASP.NET 4 introduces a new compression option for both kinds of out-of-
process session-state providers. When the compressionEnabled configuration option
shown in the following example is set to true, ASP.NET will compress (and decompress)
serialized session state by using the .NET Framework
System.IO.Compression.GZipStream class.
<sessionState
mode="SQLServer" sqlConnectionString="data source=dbserver;Initial
Catalog=aspnetstate"allowCustomSqlDatabase="true" compressionEnabled="true"/>
Listing 6
Context: The Meta tags enable you including reference information about the Web
page (metadata) such as author, keywords, content, etc.
Problem: We need to dynamically include metadata in our page, for example, from a
relational data source for the search engine to give more relevance to our site. This is a
Search Engine Optimization (SEO) technique.
Listing 7
Problem: When we use the ViewState to store a great deal of data, this causes a
signficant performance degradation.
Solution: ASP.NET 4 introduces the new property ViewStateMode in the Web controls
that lets you disable view state by default and then enable it only for the controls that
require it in the page. This property may have three values: Enable, Disable, and Inherit.
You can also set the ViewStateMode at the page level.
Listing 9
6. Routing in ASP.NET 4
Context: To increase the traffic to our Web site, one of the most used SEO (search
engine opitimization) technique is the URL normalization in order to add semantic to
the URL, for example, a Web page that displays a list of products by category is
traditionally accessed by the URL http://website/products.aspx?categoryid=12, if we
need the URL to be descriptive, we have to transform it as
http://website/products/categoryid/12.
Problem: How can we configure our applications using Web Form pages to use URL not
bind to physical files in the server?
Solution: Although routing features comes with ASP.NET 3.5 SP1, ASP.NET 4 comes with
new additions to make it easier to use the routing mechanisms, including the following:
The PageRouteHandler class, which is a simple HTTP handler that you use when you
define routes. The class passes data to the page that the request is routed to.
The new properties HttpRequest.RequestContext and Page.RouteData (which is a
shortcut to HttpRequest.RequestContext.RouteData). These properties make it easier
to access information that is passed from the route.
The following new expression builders, which are defined in
System.Web.Compilation.RouteUrlExpressionBuilder and
System.Web.Compilation.RouteValueExpressionBuilder:
Implementation strategy:
Open the Global.asax file and add the following code to bind the
products/category/{id} url pattern with the physical page ProductsCategory.aspx
(see Listing 10).
Using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.Web.Routing;
namespace _02WebAppRoutingDemo
{
public class Global : System.Web.HttpApplication
{
// New code added
void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute("ProductsCategory", "products/category/{id}","~/ProductsCategory.aspx");
}
void Application_Start(object sender, EventArgs e)
{
// New code added
RegisterRoutes(RouteTable.Routes);
}
}
}
Listing 10
And finally, let's create the ProductsCategory.aspx file and add the code to get
category value and display in the page (see Listing 11).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace _02WebAppRoutingDemo
{
public partial class ProductsCategory : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string productCategoryId
= this.Page.RouteData.Values["id"]!=null?this.Page.RouteData.Values["id"].ToString():"No Product Category";
this.lblProductCategoryId.Text = productCategoryId;
}
}
}
Listing 11
Context: Everyday, we use Ajax and JavaScript libraries to build Rich Internet
Applications (RIA). The new ClientIDMode property addresses a long-standing issue in
ASP.NET, namely how controls create the id attribute for elements that they render.
Knowing the id attribute for rendered elements is important if your application includes
client script that references these elements.
Problem: Until ASP.NET 4, the algorithm for generating the id attribute from the
ClientID property has been to concatenate the naming container (if any) with the ID, and
in the case of repeated controls (as in data controls), to add a prefix and a sequential
number. While this has always guaranteed that the IDs of controls in the page are
unique, the algorithm has resulted in control IDs that were not predictable, and were
therefore difficult to reference in client script. This occurs specially when we're using
master pages.
A trick to get a reference to the HTML elements is shown in the Listing 12:
Listing 12
Or, the more elegant solution in jQuery as shown in the Listing 13.
Listing 13
Solution: ASP.NET 4 introduces new ClientIDMode property lets you specify more
precisely how the client ID is generated for controls. You can set the ClientIDMode
property for any control, including for the page. Possible settings are the following:
Implementation strategy:
Listing 14
<div id="MainContent_PanelParent">
<div id="MainContent_PanelChild">
Listing 15
Listing 16
<div id="MainContent_PanelParent">
<div id="MainContent_PanelChild">
<input name="ctl00$MainContent$txtEcho" type="text" id="txtEcho" />
</div>
</div>
Listing 17
Listing 18
<div id="MainContent_PanelParent">
<div id="MainContent_PanelChild">
<input name="ctl00$MainContent$txtEcho" type="text"
id="MainContent_txtEcho" />
</div>
</div>
Listing 19
8. Chart control
Problem: You need to visualize data in a comprehensible way in a Web application, for
example, a financial analysis report.
Solution: ASP.NET 4 introduces a new chart control with a set of features such as pie,
area, range, points, data distribution and Ajax support. At runtime, the control generates
an image (a .pgn file) that is referenced by the client-side.
Implementation strategy:
First step is to add a HTTP handler to your application in the web.config (see Listing 20).
<httpHandlers>
<add path="ChartImg.axd" verb="GET,HEAD,POST"type="System.Web.UI.DataVisualizati
on.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false" />
</httpHandlers>
Listing 20
Later, we add the Chart control to our page (see Listing 21).
Listing 21
First example.
Listing 22
The code-behind code for this page is shown in the Listing 23.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace _04WebAppCharting
{
public partial class _01SalesByDayOfWeek : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Random random = new Random();
string[] listDaysOfWeek = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
foreach (string dayOfWeek in listDaysOfWeek)
{
double totalSales = random.NextDouble() * 5000 + 1000;
this.chrSalesByDayOfWeek.Series[0].Points.AddXY(dayOfWeek, totalSales);
}
}
}
}
Listing 23
And the output report is shown in the Figure 1.
Figure 1
Let's add the data to the series statically (see Listing 24).
Listing 24
Figure 2
Context: Some ASP.NET sites (especially with ASP.NET MVC) rely heavily on using <%=
expression %> syntax (often called "code nuggets") to write some text to the response.
Problem: When you use code expressions, it is easy to forget to HTML-encode the text.
If the text comes from user input, it can leave pages open to an XSS (Cross Site
Scripting) attack.
Solution: ASP.NET 4 introduces the following new syntax for code expressions: <%:
expression %>.
This syntax uses HTML encoding by default when writing to the response. This new
expression effectively translates to the following: <%=
HttpUtility.HtmlEncode(expression) %>.
For those cases, ASP.NET 4 introduces a new interface, IHtmlString, along with a
concrete implementation, HtmlString. Instances of these types let you indicate that the
return value is already properly encoded (or otherwise examined) for displaying as
HTML, and that therefore the value should not be HTML-encoded again. For example,
the following should not be (and is not) HTML encoded: <%: new
HtmlString("<strong>HTML that is not encoded</strong>") %>.
Context: ASP.NET MVC 1.0 ships a great deal of HTML helpers used in the view
templates to generate the HTML output. For example, <%=
Html.TextBox("ProductName", Model.ProductName) %> where the first parameter is the
Name/ID of the HTML element and the second one is its value. This produces the
following output <input id="ProductName" name="ProductName" type="text"
value="Product1" />.
Problem: One of the features asked by the developers is to have strongly typed HTML
helpers that use lambda expressions to reference the model, and in this way, we can
detect compile-time errors and have a better IntelliSense support.
Html.TextBoxFor()
Html.TextAreaFor()
Html.DropDownListFor()
Html.CheckboxFor()
Html.RadioButtonFor()
Html.ListBoxFor()
Html.PasswordFor()
Html.HiddenFor()
Html.LabelFor()
Html.EditorFor()
Html.DisplayFor()
Html.DisplayTextFor()
Html.ValidationMessageFor()
Implementation strategy: An example is shown in the Listing 25.
Listing 25
Solution: ASP.NET MVC 2 includes a bunch of new features that make validating user
input and enforcing validation logic on models/viewmodels significantly easier. These
features are designed so that the validation logic is always enforced on the server, and
can optionally also be enforced on the client via JavaScript. ASP.NET MVC 2 is designed
to take advantages DataAnnotation validation support built-into the .NET Framework as
well as existing validation frameworks like Castle Validator or the EntLib Validation
Library.
Implementation strategy:
First step is to define the Contact entity in the Entities package. To enforce input
validation rules, we're going annotate the Contact entity with the validation rules to be
enforced whenever ASP.NET MVC engine performs binding operations within an
application. These annotations for validation are in the
System.ComponentModel.DataAnnotations assembly (see Listing 26).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace _05MvcAppValidationModel.Entities
{
public class Contact
{
[Required(ErrorMessage="FirstName field is required")]
[StringLength(50, ErrorMessage="FirstName must be under 50 characters")]
public string FirstName { get; set; }
[Required(ErrorMessage = "LastName field is required")]
[StringLength(50, ErrorMessage = "LastName must be under 50 characters")]
public string LastName { get; set; }
[Required(ErrorMessage = "Age field is required")]
[Range(0,120,ErrorMessage="Age must be between 0 and 120")]
public int Age { get; set; }
public string Email { get; set; }
}
}
Listing 26
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using _05MvcAppValidationModel.Entities;
namespace _05MvcAppValidationModel.Controllers
{
public class ContactManagerController : Controller
{
//
// GET: /ContactManager/
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult Create()
{
Contact newContact = new Contact();
return View(newContact);
}
[HttpPost]
public ActionResult Create(Contact contact)
{
if (ModelState.IsValid)
{
return Redirect("/");
}
return View(contact);
}
}
}
Listing 27
And right-click on the Create action method and select the Add View option from the
context menu (see Figure 3).
Figure 3
The Create view is generated with fields and validation necessary to create a contact
(see Listing 28).
Listing 28
And finally, let's run the application and enter invalid values in the Add Contact screen
and see the results (see Figure 4).
Figure 4
Listing 29
Conclusion
In this article, I've explained the new features of ASP.NET 4. Now, you can use the
features in your own solution.