27 April 2011

What is Web.Config And Machine.Config File?

What is Web.Config File?
It is an optional XML File which stores configuration details for a specific asp.net web application. 
Note:  When you modify the settings in the Web.Config file, you do not need to restart the Web service for the modifications to take effect..  By default, the Web.Config file applies to all the pages in the current directory and its subdirectories.
Extra:  You can use the <location> tag to lock configuration settings in the Web.Config file so that they cannot be overridden by a Web.Config file located below it. You can use the allowOverride attribute to lock configuration settings. This attribute is especially valuable if you are hosting untrusted applications on your server.

What is Machine.config File?
The Machine.Config file, which specifies the settings that are global to a particular machine. This file is located at the following path:
 \WINNT\Microsoft.NET\Framework\[Framework Version]\CONFIG\machine.config
As web.config file is used to configure one asp .net web application, same way Machine.config file is used to configure the application according to a particular machine. That is, configuration done in machine.config file is affected on any application that runs on a particular machine. Usually, this file is not altered and only web.config is used which configuring applications.
You can override settings in the Machine.Config file for all the applications in a particular Web site by placing a Web.Config file in the root directory of the Web site as follows:
\InetPub\wwwroot\Web.Config
  
What can be stored in Web.config file?
There are number of important settings that can be stored in the configuration file. Here are some of the most frequently used configurations, stored conveniently inside Web.config file..
1.      Database connections.
2.      Session States
3.      Error Handling (CustomError Page Settings.)
4.      Security (Authentication modes)

What is the best place to store Database connection string?
In Web.Config, you would add a key to the AppSettings Section:

<appSettings>
 <add key="MyDBConnection" value="data source=<ServerName>;Initial catalog =<DBName>;user id=<Username>;password=<Password>;" />
 </appSettings>

Example:
<add key="ConnectionString" value= "data source=localhost;Initial catalog=northwind;user id=sa;password=mypass" />
Then, in your ASP.Net application - just refer to it like this:
using System.Configuration;
string connectionString = (string )ConfigurationSettings.AppSettings["ConnectionString"];

Difference between Web.Config and Machine.Config File

Two types of configuration files supported by ASP.Net.
Configuration files are used to control and manage the behavior of a web application.

i) Machine.config
ii)Web.config

Difference between Machine.Config and Web.Config
Machine.Config:
i)  This is automatically installed when you install Visual Studio. Net.
ii) This is also called machine level configuration file.
iii)Only one machine.config file exists on a server.
iv) This file is at the highest level in the configuration hierarchy.

Web.Config:
i)  This is automatically created when you create an ASP.Net web application project.
ii) This is also called application level configuration file.
iii)This file inherits setting from the machine.config

13 April 2011

difference between Server.MapPath("."), Server.MapPath("~"), Server.MapPath(@"\") and Server.MapPath("/")?

Server.MapPath specifies the relative or virtual path to map to a physical directory.
  • Server.MapPath(".") returns the current physical directory of the file (e.g. aspx) being executed
  • Server.MapPath("..") returns the parent directory
  • Server.MapPath("~") returns the physical path to the root of the application
  • Server.MapPath("/") returns the physical path to the root of the domain name (is not necessarily the same as the root of the application)
An example:
Let's say you pointed a web site application (http://www.example.com/) to
C:\Inetpub\wwwroot
and installed your shop application (sub web as virtual directory in IIS, marked as application) in
D:\WebApps\shop
For example, if you call Server.MapPath in following request:
http://www.example.com/shop/products/GetProduct.aspx?id=2342
then:
  • Server.MapPath(".") returns D:\WebApps\shop\products
  • Server.MapPath("..") returns D:\WebApps\shop
  • Server.MapPath("~") returns D:\WebApps\shop
  • Server.MapPath("/") returns C:\Inetpub\wwwroot
  • Server.MapPath("/shop") returns D:\WebApps\shop
If Path starts with either a forward (/) or backward slash (\), the MapPath method returns a path as if Path were a full, virtual path.
If Path doesn't start with a slash, the MapPath method returns a path relative to the directory of the request being processed.
Note: in C#, @ is the verbatim literal string operator meaning that the string should be used "as is" and not be processed for escape sequences.

18 March 2011

Temp table VS Table variable

Most of the SQL Developers/DBA would have come across a situation where they need to store the temporary result sets. This is where Temp tables and Table variables come into effect and helps in storing the data sets in a temporary location.


Temp table:

Consider the below sample temp table which holds the information about companies.
CREATE TABLE #Tmp
(
CompanyId Int,
Name varchar (50),
Location varchar (50)
)

  1. The temp table name always starts with # or ## and are created in the tempdb database. The # indicates that the temp table is a local temporary table i.e. table is accessible only by the particular connection of SQL Server which created it. The ## indicates that the temp table is a global temporary table i.e. the table is accessible from any connection. They are dropped automatically when the last session that uses them has completed.
  2. Since the local temporary table is accessible only by the connection which created it, this helps in minimizing the locks.
  3. We can create indexes, statistics in temp tables and hence performance can be improved.
  4. We cannot have foreign key constraints on temp tables.
  5. Causes recompilation within stored procedures.
  6. Only undo information is logged in tempdb and not the redo information.
  7. We can Rollback the transactions in temp table similar to a normal table but not in table variable.
  8. Temp tables can be used in nested stored procedures.
  9. The temp table names cannot exceed 116 characters whereas the permanent table can have 128 characters

The following example illustrates the transaction behavior in Temp tables:

--using temp tables where ROLLBACK happens
CREATE TABLE #Tmp
(
CompanyId Int,
Name varchar(20),
Location varchar(20)
)
GO
 
INSERT INTO #Tmp
VALUES (1,'Deepak','Chennai')
GO
 
BEGIN TRAN
UPDATE #Tmp
SET Location='CH'
WHERE CompanyId=1
ROLLBACK TRAN
 
SELECT * FROM #Tmp


Table variables:

The following the syntax for table variables:

DECLARE @Tmp TABLE
(
CompanyId Int,
Name varchar(20),
Location varchar(20)
)

  1. Table variables are local to a stored procedure and hence cannot be used in nested stored procedures
  2. We cannot create Nonclustered indexes in Table variables only Clustered index can be created by specifying them as constraints (Primary or Unique)                                                                                                                                                        DECLARE @Tmp TABLE (C1 int, C2 int, PRIMARY KEY (C1, C2))
  3. Table variables store the contents in memory but not always. Under extreme memory pressure, the pages belonging to table variables will be moved to tempdb
  4. We cannot Alter a table variable once its declared
  5. We cannot create statistics in table variables
  6. They cannot make use of multiple processors and hence Parallelism is not possible
  7. Transactions cannot be rollbacked in Table variable

The following example illustrates the transaction behavior in table variables:

--using table variables where ROLLBACK NEVER happens
DECLARE @Tmp TABLE
(
CompanyId Int,
Name varchar(20),
Location varchar(20)
)
INSERT INTO @Tmp
VALUES (1,'Deepak','Chennai')
 
BEGIN TRAN
UPDATE @Tmp
SET Location='CH'
WHERE CompanyId=1
ROLLBACK TRAN
 
SELECT * FROM @Tmp

I tried the following to check the performance perspective of table variables and temp tables. I could see that Temp tables are quite faster than table variables if we load numerous records. However with <10000 records being loaded, the table variables were much faster than temp tables.

I have a table named testmember with 1.5 million records.

--took 52 seconds to complete
SET STATISTICS TIME ON
DECLARE @Tmp TABLE
(
memberid          bigint,
name    nvarchar(100),
firstname           nvarchar(100),
emailaddress     nvarchar(100)
)
INSERT INTO @Tmp
SELECT memberid, name, firstname, emailaddress FROM testmember
WHERE memberid between 1 and 1000000
 
SELECT T.memberid, T.name, T.firstname, T.emailaddress
FROM @Tmp T INNER JOIN testmember M
ON T.memberid=M.memberid
where M.Memberid=1000
SET STATISTICS TIME OFF
 
--DBCC DROPCLEANBUFFERS
 
--took 45 seconds to complete
SET STATISTICS TIME ON
CREATE TABLE #Tmp
(
memberid          bigint,
name    nvarchar(100),
firstname           nvarchar(100),
emailaddress     nvarchar(100)
)
INSERT INTO #Tmp
SELECT memberid, name, firstname, emailaddress FROM testmember
WHERE memberid between 1 and 1000000
 
SELECT T.memberid, T.name, T.firstname, T.emailaddress
FROM #Tmp T INNER JOIN testmember M
ON T.memberid=M.memberid
where M.Memberid=1000
SET STATISTICS TIME OFF

Since we can create indexes, statistics etc there is still a scope for further improvement in performance in temp tables. In general there is no hard and fast rule, if there are <10K records we can opt for table variable else use temp tables but always test the query and then take a decision.

Limitations of Temp tables and Table variables:

  1. There will be high load on the disk where tempdb resides if temp tables are used frequently and to a large extent and we have to keep an eye on the tempdb growth to ensure that it doesn’t become full and consume disk space
  2. Table variables will perform poorly with large record set since index cannot be created other than primary key (Clustered Index)

17 March 2011

There is no source code available for the current location

I have a problem when i am started running windows application.  I copied that form one system to another, i got one as shown bellow. 
Debugging Error.
"There is no source code available for the current location. vs2005..."
Solution:-
Erase .pdb files that i have in my debug folder and it is working fine.
Reference Link:-
http://social.msdn.microsoft.com/Forums/en/csharpide/thread/5ee88200-cee8-44f4-a46a-774044c1ef38

Globalization using ASP.NET


Sometimes our application may need to cater content in different languages for different country users. Let us see in this article how to cater different contents based on the culture using Globalization in ASP.NET.

Globalization is the process of designing and developing a software product that function for multiple cultures. A web forms page have two culture values ,Culture and UICulture. Culture is used to determine culture dependent function such as Date, Currency. So it is used for date formatting ,number formatting. UICulture values is used to determine which language the resources should load that is which UIstring the resource should use. The two culture settings do not need to have same values. It may be different depending on the application.

Setting Culture and UICulture
 
1. Through Web.Config
<configuration>
<
system.web>
<
globalization fileEncoding="utf-8" requestEncoding="utf-8" responseEncoding="utf-8" culture="en-US" uiCulture="fr-FR"/>
</
system.web>
</
configuration>

2. In Code-inline (aspx) Page
<%@ Page UICulture="fr" Culture="en-US" ....%>

Now, suppose I want to change the current culture programmatically, I can use following code to set the new culture.

3. In Code-Behind (aspx.cs) Page

using System.Globalization;
using System.Threading;

protected void Page_Init(object sender, EventArgs e)

    {
        Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", false);
    }


Reference Links:-


http://msdn.microsoft.com/en-us/library/bb386581.aspx

07 March 2011

Error in File UNKNOWN.RPT: The request could not be submitted for background processing

I have a web application that uses Crystal Reports. It is working fine in one of our test server (Windows 2003). When we migrate this asp.net web apps to the production server, my Report Generate button that uses Crystal Reports did not work and got this following error.  The request could not be submitted for background processing".


Solution:-
I took the below steps to correct it:
  1. Right Click on C Drive
  2. Click on Security Tab
  3. Add "Network Services" to the list of users. Caution: Remember to remove it later.
  4. Browse to you application and crystal report should work now.
  5. Go back to your server and Remove the "Network Service" user from the security list. 
Hope this fixes the issue for all.

28 February 2011

Make sure the application for the file type (.aspx) is installed

After I created new WebSite in VS 2005 I'm getting this error

---------------------------Microsoft Visual Studio---------------------------
There is no editor available for 'C:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\WebSites\WebSiteUpload\Default.aspx'.
Make sure the application for the file type (.aspx) is installed.

---------------------------OK ---------------------------

Solution:
run from a Visual Studio Command Prompt, type "devenv.exe /setup" and then "devenv /resetskippkgs" (without the quotes)

22 February 2011

New features of ASP.NET 4

Introduction

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

1. Extensible Output Caching

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 new System.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.VelocityCacheProvider, 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).

<%@ OutputCache Duration="60" VaryByParam="None" providerName="VelocityCache" %>

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).

public override string GetOutputCacheProviderName(HttpContext context)
{
    if (context.Request.Path.EndsWith("CacheWebForm.aspx"))
        return "VelocityCache";
    else
        return base.GetOutputCacheProviderName(context);
}

Listing 4

2. Permanently Redirecting a Page

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.

Problem: Traditionally, this is done using the Response.Redirect method to forward a request to the new URL. However, this method issues an HTTP 302 Found (temporary redirect) response, which results in an extra HTTP round trip when users attempt to access the old URLs.

Solution: ASP.NET 4 adds a new RedirectPermanent method that makes it easy to issue HTTP 301 Moved Permanently responses.

Implementation strategy: See an example in the Listing 5.

Response.RedirectPermanent("newlocation/page.aspx");

Listing 5

3. Shrinking Session State

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.

Implementation strategy: See an example in the Listing 6.

<sessionState
      mode="SQLServer" sqlConnectionString="data source=dbserver;Initial Catalog=aspnetstate" allowCustomSqlDatabase="true" compressionEnabled="true"/>

Listing 6

4. Setting Meta Tags

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.

Solution: ASP.NET 4 introduces the new properties MetaKeywords and MetaDescription to the Page class. The @Page directive contains the Keywords and Description attribute.

Implementation strategy: See an example in the Listing 7.

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="_01WebAppOutputCacheDemo._Default" Keywords="This is the default page" Description="This is the default page" %>

Listing 7

This configuration generates the following output as shown in the Listing 8.

<head id="Head1" runat="server"> 
  <title>Untitled Page</title> 
  <meta name="keywords" content="These, are, my, keywords" /> 
  <meta name="description" content="This is the description of my page" /> 
</head>

Listing 8

5. Better control of the ViewState

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.

Implementation strategy: See an example in the Listing 9.

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="_01WebAppOutputCacheDemo._Default" ViewStateMode="Disabled" %>

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:
    • RouteUrl, which provides a simple way to create a URL that corresponds to a route URL within an ASP.NET server control.
    • RouteValue, which provides a simple way to extract information from the RouteContext object.
  • The RouteParameter class, which makes it easier to pass data contained in a RouteContext object to a query for a data source control (similar to FormParameter).
Implementation strategy:

This is the main steps to add routing capabilities to your application.
  • 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
7. Setting Client IDs

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:

var btn = document.getElementById("<% =Button1.ClientID %>");

Listing 12

Or, the more elegant solution in jQuery as shown in the Listing 13.

var btn = $('<% =Button1.ClientID %>');

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:
  • AutoID. This is equivalent to the algorithm for generating ClientID property values that was used in earlier versions of ASP.NET.
  • Static. This specifies that the ClientID value will be the same as the ID without concatenating the IDs of parent naming containers. This can be useful in Web user controls. Because a Web user control can be located on different pages and in different container controls, it can be difficult to write client script for controls that use the AutoID algorithm because you cannot predict what the ID values will be.
  • Predictable. This option is primarily for use in data controls that use repeating templates. It concatenates the ID properties of the control's naming containers, but generated ClientID values do not contain strings like "ctlxxx". This setting works in conjunction with the ClientIDRowSuffix property of the control. You set the ClientIDRowSuffix property to the name of a data field, and the value of that field is used as the suffix for the generated ClientID value. Typically you would use the primary key of a data record as the ClientIDRowSuffix value.
  • Inherit. This setting is the default behavior for controls; it specifies that a control's ID generation is the same as its parent.
Implementation strategy:

An AutoID example (see Listing 14).

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <asp:Panel ID="PanelParent"  runat="server">         
        <asp:Panel ID="PanelChild" runat="server">         
            <asp:TextBox ID="txtEcho" runat="server" ClientIDMode="AutoID" />
        </asp:Panel>
    </asp:Panel>
</asp:Content>

Listing 14

And the output is shown in the Listing 15.

<div id="MainContent_PanelParent">          
   <div id="MainContent_PanelChild">          
     <input name="ctl00$MainContent$txtEcho" type="text" id="ctl00_MainContent_txtEcho" />  
  </div>
</div>

Listing 15

A Static example (see Listing 16).

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <asp:Panel ID="PanelParent"  runat="server">         
        <asp:Panel ID="PanelChild" runat="server">         
            <asp:TextBox ID="txtEcho" runat="server" ClientIDMode="Static" />
        </asp:Panel>
    </asp:Panel>
</asp:Content>

Listing 16

The output is shown in the Listing 17.

<div id="MainContent_PanelParent">          
  <div id="MainContent_PanelChild">          
    <input name="ctl00$MainContent$txtEcho" type="text" id="txtEcho" />   
   </div> 
</div>

Listing 17

A Predictable example (see Listing 18).

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <asp:Panel ID="PanelParent"  runat="server">         
        <asp:Panel ID="PanelChild" runat="server">         
            <asp:TextBox ID="txtEcho" runat="server" ClientIDMode="Predictable" />
        </asp:Panel>
    </asp:Panel>
</asp:Content>

Listing 18

And the output is shown in the Listing 19.

<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.DataVisualization.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).

<asp:Chart ID="Chart1" runat="server" />

Listing 21

First example.

The Web Form page is shown in the Listing 22.

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="01SalesByDayOfWeek.aspx.cs" Inherits="_04WebAppCharting._01SalesByDayOfWeek" %><%@ Register
    Assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <div>
       <h3>Sales Reports (By days of the week)</h3>
    </div>
    <div>
    <asp:Chart ID="chrSalesByDayOfWeek" runat="server" Width="500" Height="350">
        <Series>
            <asp:Series ChartType="Area" Palette="EarthTones" ChartArea="MainChartArea"></asp:Series>
        </Series>
        <ChartAreas>
          <asp:ChartArea Name="MainChartArea" Area3DStyle-Enable3D="true">
          </asp:ChartArea>
        </ChartAreas>
    </asp:Chart>
    </div>
</asp:Content>

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.

1.gif
Figure 1

Let's add the data to the series statically (see Listing 24).

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="02SalesByDayOfWeekStatic.aspx.cs" Inherits="_04WebAppCharting._02SalesByDayOfWeekStatic" %>
<%@ Register Assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <div>
       <h3>Sales Reports (By days of the week)</h3>
    </div>
    <div>
    <asp:Chart ID="chrSalesByDayOfWeek" runat="server" Width="500" Height="350">
        <Series>
            <asp:Series ChartType="Area" Palette="EarthTones" ChartArea="MainChartArea">
                <Points>
                    <asp:DataPoint AxisLabel="Sun" YValues="17" />
                    <asp:DataPoint AxisLabel="Mon" YValues="15" />
                    <asp:DataPoint AxisLabel="Tue" YValues="6" />
                    <asp:DataPoint AxisLabel="Wed" YValues="4" />
                    <asp:DataPoint AxisLabel="Thu" YValues="3" />
                    <asp:DataPoint AxisLabel="Fri" YValues="3" />
                    <asp:DataPoint AxisLabel="Sat" YValues="3" />
                </Points>
            </asp:Series>
        </Series>
        <ChartAreas>
          <asp:ChartArea Name="MainChartArea" Area3DStyle-Enable3D="true">
          </asp:ChartArea>
        </ChartAreas>
    </asp:Chart>
    </div>
</asp:Content>

Listing 24

And the report output is shown in the Figure 2.

2.gif
Figure 2

9. Html Encoded Code Expressions

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>") %>.

10. Html Encoded Code Expressions

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.

Solution: ASP.NET 4 introduces a set of strongly-typed HTML helpers following the naming convention Html.HelperNameFor(). The list is enumerated:
  • 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.

<%= Html.TextBoxFor(model=>model.ProductName) %>

Listing 25

11. Better validation model (ASP.NET MVC)

Problem: Validating user-input and enforcing business rules/logic is a core requirement of most web applications.

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

Let's illustrate this new feature with an example.

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

Next step is to add the ContactManagerController to handle the HTTP requests regarding the contacts (see Listing 27).

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).

3.gif
Figure 3

The Create view is generated with fields and validation necessary to create a contact (see Listing 28).

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<_05MvcAppValidationModel.Entities.Contact>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
          Add a contact
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Add a contact</h2>
    <% using (Html.BeginForm()) {%>
        <%: Html.ValidationSummary(true) %>
        <fieldset>
            <legend>Fields</legend>
            <div class="editor-label">
                <%: Html.LabelFor(model => model.FirstName) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(model => model.FirstName) %>
                <%: Html.ValidationMessageFor(model => model.FirstName) %>
            </div>
            <div class="editor-label">
                <%: Html.LabelFor(model => model.LastName) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(model => model.LastName) %>
                <%: Html.ValidationMessageFor(model => model.LastName) %>
            </div>
            <div class="editor-label">
                <%: Html.LabelFor(model => model.Age) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(model => model.Age) %>
                <%: Html.ValidationMessageFor(model => model.Age) %>
            </div>
            <div class="editor-label">
                <%: Html.LabelFor(model => model.Email) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(model => model.Email) %>
                <%: Html.ValidationMessageFor(model => model.Email) %>
            </div>
            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>
     <% } %>
    <div>
        <%: Html.ActionLink("Back to List", "Index") %>
    </div>
</asp:Content>

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).

4.gif
Figure 4

You can also enable client-side validation (see Listing 29).

    <h2>Add a contact</h2>
    <!-- BEGIN. This block is required for client-side validation -->
    <script src="../../Scripts/MicrosoftAjax.js" type="text/javascript"></script>
    <script src="../../Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>
    <% Html.EnableClientValidation(); %>
    <!-- END. This block is required for client-side validation -->