Go Top
advertise here!!!

Library || READ MORE || DOWNLOAD PDF || QUESTION ANSWERS || HOME

  • BASIC ASP.NET ↓

    Basic ASP.NET

    Introduction

    Welcome to this ASP.NET tutorial. According to Microsoft, "ASP.NET is a technology for building powerful, dynamic Web applications and is part of the .NET Framework". This tutorial will teach you ASP.NET from scratch, and no knowledge of any kind of serverside scripting is required. Basic HTML and CSS knowledge is preferable. Having worked with Classic ASP or PHP won't give you much of an advantage, since ASP.NET is a whole new way of doing things.

    .NET is language independent, which means you can use any .NET supported language to make .NET applications. The most common languages for writing ASP.NET applications are C# and VB.NET. While VB.NET is directly based VB (Visual Basic), C# was introduced together with the .NET framework, and is therefore a some what new language. Some people call C# "the .NET language", but according to Microsoft, you can do all the same things, no matter if you're using C# or VB.NET. The 2 languages are not that different, and if you have used one of them, you will have no problems at all learning the other. In this tutorial we will use C#.

    One of the main differences between ASP.NET and Classic ASP/PHP is the fact that ASP.NET is compiled, while Classic ASP is always interpreted. PHP can be compiled by using commercial products, but usually it's interpreted as well. A noted difference between php & asp.net is that, php web applications can be hosted in linux as well as windows servers, while asp.net websites can only be hosted in windows servers.

    This tutorial will use the free Visual Studio Express 2012 IDE from Microsoft. Despite what some people think, ASP.NET can be used without an IDE. It would be perfectly possible to write ASP.NET code in Notepad, and use the commandline compiler included with the .NET framework. Some people might actually prefer this "back to basics" way of doing things, but I believe that ASP.NET is best programmed with a decent IDE. You can use an IDE from another vendor, and you will still be able to follow most of this tutorial. We will use Visual Studio Express 2012 for Web since it's free, quick to install and easy to use. Besides, using a good IDE will make a lot of things faster in the long run.

    Now, you can read more about Visual Studio for Web on this page: http://www.microsoft.com/visualstudio/eng/products/visual-studio-express-for-web and download it from this page: http://www.microsoft.com/visualstudio/eng/downloads#d-express-web. The initial download is very small, because the installation is based on which components you already have and which will have to be downloaded. Just execute the file, and you will be guided through the installation. Once installed, start up the application, and proceed to the next chapter.

    First Website

    With MS Visual Studio installed, we're ready to create our first ASP.NET website. In VS, this is very easy. Open the File menu and select "New Web Site". You will be presented with the following dialog:

    You need to select "ASP.NET Web Site", if it's not already selected. You should also name your new site. This is done by entering a name in the Location box. This text box is probably already filled for you, with the last part being something like "Website1". You can choose to accept this, as well as the location of the project, or you can enter a new one, like I did. I have created a folder, "My Websites", and within this folder, I would like to create the new project with the name of "FirstWebSite". For now, this is less important, but later on you might wish to gather all your projects in a specific folder.

    This tutorial will focus on the C# language. Once again, no knowledge of this is required, so if you already know another .NET language, you will get to learn some C# with this tutorial as well. Select C# in the Language dropdown. Now, click the Ok button to create this new website.

    VS will create a very basic website for you, consisting only of a Default.aspx file (and it's partner, the Default.aspx.cs file) and an App_Data folder. I will explain this later, but for now, just accept the fact that they are there. We will only use the Default.aspx for this first example. Move on to the next chapter, for the obligatory "Hello, world!" example.

    Hello World!

    In almost every programming tutorial you will find the classic "Hello, world!" example, and who am I to break such a fine tradition? Let me show you how you can say hello to the world from ASP.NET. Open the Default.aspx (if it's not already opened) by doubleclicking it in the Solution Explorer. It already contains a bunch of HTML markup, as well as some stuff you probably won't recognize, like the Page directive in the top, or the runat attribute on the form tag. This will all be explained later, but for now, we want to see some working code.

    First of all, we will add a Label control to the page. A Label control is some what simple, since it's just used to hold a piece of text. Add the following piece of HTML-looking code somewhere between the set of

    tags:

    Secondly, add this script block somewhere on the page, preferably below the Page directive in the top:

    <%
        HelloWorldLabel.Text = "Hello, world!";
    %>

    If you haven't worked with ASP.NET before, I'm sure there's a bunch of things that you're wondering about now, but as I said, this is all about seeing some results right now. To see the page in action, use Debug -> Start Without Debugging, or simply press F6. Visual Studio will now compile your project, and launch the page you're working on in your default browser. The page will simply have a piece of text which says "Hello, world!" - congratulations, you have just created your first ASP.NET website! Here is the complete listing:

    <%
        HelloWorldLabel.Text = "Hello, world!";
    %>
    
    
    
        Untitled Page
    
    
        
        
    CodeBehind

    While our first example was fine, we unfortunately broke one of the coding principles of ASP.NET: To separate markup and code. As you noticed, we added a scripting block (using <% %>), where we wrote a line of C# code to use the label. While this is just fine for a small and simple example like this, we would soon get a real mess with a bunch of C# code within an even bigger amount of HTML code. If you throw in some JavaScript and some CSS as well, it will soon become very chaotic to edit. That's why MS introduced CodeBehind, a technique which allows you to completely separate markup (HTML, CSS etc.) and code (C#, VB.NET etc.). So let's remove the script block (from <% to %>) and save the file.

    As we talked about earlier, VS added a file called Default.aspx.cs. If you can't see it in the Solution Explorer, then click the little plus sign left of the Default.aspx file. Open this file. Now, if you haven't worked with .NET or another non-web programming language before, it might look a bit scary at this point. It looks nothing like HTML. However, I will try to explain the different parts of the content, and soon you will hopefully see that CodeBehind is a great tool to get a better overview of your work. Here is a complete listing of the file as it looks right now:

    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    
    public partial class _Default : System.Web.UI.Page 
    {
        protected void Page_Load(object sender, EventArgs e)
        {
    
        }
    }

    For now, the top part is rather irrelevant to us. It's a list of namespaces being included with the using keyword, for usage in the file. Since this is an ASP.NET tutorial and not a dedicated C# tutorial, I won't explain this in depth. Next, we have the class. Classes are a part of the concept of Object Oriented programming, which has become very popular, especially with languages like Java and C#. OO is a very complex subject, which also won't be explained within this tutorial.

    The name of this class is "_Default", and the : (colon) tells us that this class inherits from the Page class in the System.Web.UI namespace. This means that our page can already do a bunch of things, without any programming, because it inherits methods and properties from another class. All ASP.NET pages inherits from the Page class, or another class which inherits from the Page class.

    The only method within this class is the Page_Load, which is called everytime the page is loaded. Let's use that to our advantage, and set the ext from this method. We can use the exact same line of code as before, but of course without the script block tags. Add the line of code between the { and } characters:

    HelloWorldLabel.Text = "Hello, world!";

    That's it. Run the project (F6), and have a look. The page looks exactly like before, but we have just used CodeBehind for the first time. But this example is starting to get a bit old, so in the next chapter, we will look into something a bit more interesting.

    Events

    ASP.NET is an event-driven way of making web applications. With PHP and Classic ASP, you have one file, which is executed line after line, from start to end. However, ASP.NET is very different. Here we have events, which are either activated by the user in one way or another. In the previous example, we used the Page_Load method. Actually, this is an event, which the Page class calls when the page is loaded. We will use the same technique in the next example, where we will add a couple of controls to our simple hello world example. To make it a bit more interesting, we will change the "world" word with something defined by the user. Have a look at this codelisting, where we add two new controls: A Button control and a TextBox control.

                               <form id="form1" runat="server">
    <div>
        <asp:Label runat="server" id="HelloWorldLabel"></asp:Label>
        <br /><br />
        <asp:TextBox runat="server" id="TextInput" /> 
        <asp:Button runat="server" id="GreetButton" text="Say Hello!" />
    </div>
    </form>

    As you can see, we now have the 2 new controls added, but they really can't do much at the moment. You can run the example if you wish to check this out for your self - if you click the button, the page is simply reloaded. Let's change that, and let's start by doing it the easy way. VS comes with a WYSIWYG editor, and while I hardly ever use it my self, it does make some things easier, like creating events.

    So, click the Design button in the bottom of VS. Now you will see a visual representation of our page. We wish to add a Click event to the button, and this is very simply - just doubleclick the GreetButton, and you will be taken to the CodeBehind file of our page. As you can see, a fine new method has been added, called GreetButton_Click. If you have a look at the Default.aspx file (you need to go from Design view to Source view), you will see that an attribute has been added to our Button control, telling which method to call when the button is clicked. All this work done with a simple doubleclick.

    Now lets add some code to our new event. We wish to use the text from the TextBox, on our good old Label with the "Hello, world!" text. This is also very simple, and all it requires is a single line of code:

    HelloWorldLabel.Text = "Hello, " + TextInput.Text;

    Run the project again (F6), and you will see the our old page with a couple of new controls. The "Hello, world!" text is still there, because we set it in the Page_Load event. Now try entering a name in the textbox, and press the button. Voila, the text is changed, and we have just used our first control event. Notice how we can add code which is not necessarily called unless the user performs a specific task. This is different from the good old Classic ASP/PHP approach, but you will soon get used to it, and you will probably also come to like it a lot!

    Okay, the onclick event from last chapter was easy, but let's try creating all the code required to use an event from scratch. We will also add yet a new control, to make things more interesting - the DropDownList, which allows the user to select an item from a list. Add the folowing code snippet somewhere in the Default.aspx file:

                                <asp:DropDownList runat="server" id="GreetList" autopostback="true">
        <asp:ListItem value="no one">No one</asp:ListItem>
        <asp:ListItem value="world">World</asp:ListItem>
        <asp:ListItem value="universe">Universe</asp:ListItem>
    </asp:DropDownList>>

    This thing works just like a normal HTML SELECT element, which is of course what it's translated into upon rendering. The only attribute that would seem new to a person with basic HTML experience, is the autopostback. You will learn more about postbacks in one of the next chapters, but for now, just know that it makes the control contact the server eachtime an item is selected by the user. We will use this to our benefit now, by adding an event:

    protected void GreetList_SelectedIndexChanged(object sender, EventArgs e)
    {
        HelloWorldLabel.Text = "Hello, " + GreetList.SelectedValue;
    }

    We are using the onselectedindexchanged event, and assigning a method from CodeBehind which does not yet exist. You are free to choose the name of the method, but using a convention with the name of the control, an underscore, and then the name of the event, helps you keep track of it all. We better go create the event, so change to the Default.aspx.cs file, and add the following method:

    protected void GreetList_SelectedIndexChanged(object sender, EventArgs e)
    {
        HelloWorldLabel.Text = "Hello, " + GreetList.SelectedValue;
    }

    Once again, we make this extremely simple. We use the SelectedValue property of our dropdown list, which holds the text from the value property of the selected item. Try running the site, and select an item from the dropdown list. Pretty neat, huh? All commen controls come with a bunch of usefull events, which you can subscribe to like this.

  • USER-CONTROLS ↓

    UserControls

    Introduction

    A UserControl is a separate, reusable part of a page. You can put a piece of a page in a UserControl, and then reuse it from a different location. The name, UserControl, might seem a bit fancy, but actually, it's just like a regular page, with an optional CodeBehind file. A notable difference is that UserControls can be included on multiple pages, while a page can't. UserControls are used much like regular server controls, and they can be added to a page declaratively, just like server controls can.

    A big advantage of the UserControl is that it can be cached, using the OutputCache functionality described in a previous chapter, so instead of caching an entire page, you may cache only the UserControl, so that the rest of the page is still re-loaded on each request.

    An example where a UserControl could come in handy, is a control for showing information about a certain user on a community website. In the next couple of chapters, we will create a UserControl from scratch, make it fit to our purpose, and then use it on a page.

    Creating a UserControl

    Okay, so we will be building a UserControl for displaying information about a community user. First of all, let's add a UserControl to our project. In your Visual Studio, you should be able to right click on your project and select Add new item.. A dialog will pop up, and you should select the Web User Control from the list of possible things to add. Let's call our UserControl UserInfoBoxControl, with the filename of UserInfoBoxControl.ascx. Make sure that you have checked the checkbox which places code in a separate file, the so-called CodeBehind file.

    You should now have a UserInfoBoxControl.ascx and a UserInfoBoxControl.ascx.cs in your project. The first is where we put our markup, and the second is our CodeBehind file. Now, if UserInfoBoxControl.ascx is not already open and selected, do so now. You will see only one line of code, the UserControl declaration. As mentioned, this control will be displaying information about a user, so let's get started adding some markup to do so:

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="UserInfoBoxControl.ascx.cs" Inherits="UserInfoBoxControl" %>
    <b>Information about <%= this.UserName %></b>
    <br /><br />
    <%= this.UserName %> is <%= this.UserAge %> years old and lives in <%= this.UserCountry %>

    As you can see, it's all very basic. We have a declaration, some standard tags, some text, and then we have some sort of variables. Now, where do they come from? Well, right now, they come from nowhere, since we haven't declared them yet. We better do that right away. Open the CodeBehind file for the UserControl, that is, the one which ends on .cs.

    As you can see, it looks just like a CodeBehind file for a regular page, except that it inherits from UserControl instead of from Page. We will declare the tree properties used in our markup, and base them on three corresponding fields.

    private string userName;
    private int userAge;
    private string userCountry;
    
    public string UserName
    {
        get { return userName; }
        set { userName = value; }
    }
    
    public int UserAge
    {
        get { return userAge; }
        set { userAge = value; }
    }
    
    public string UserCountry
    {
        get { return userCountry; }
        set { userCountry = value; }
    }

    It's all very simple and works just like a regular class. You can even add methods, if you feel like it! Our UserControl is actually done now, but as you may have already experienced, we can't use it yet. A UserControl can't be displayed directly in the browser - it has to be included on a page. We will do that in the next chapter.



    Using a UserControl

    In the previous chapter we created a UserControl, and now we will try using it for the first time. Pick a page in your project, or simply create a new one for the purpose, and open it. The first thing we have to do, is declare our UserControl. It can be done either in each page where it's used, or globally in the web.config file. There is no performance difference, but when declaring UserControls in the web.config file, the controls have to reside in a different directory than the page(s) using it.

    For now, let's just declare it within the page. Add the following line below the standard page declaration:

    <%@ Register TagPrefix="My" TagName="UserInfoBoxControl" Src="~/UserInfoBoxControl.ascx" %>
    
    Make sure that the src value matches the path to your UserControl file. Now you may use the UserControl in your page, like any other control. For instance, like this:
    <My:UserInfoBoxControl runat="server" ID="MyUserInfoBoxControl" />
    
    If you look at the page now, you will see our UserControl in action, although the information will be a bit... limited. We will have to set a value for the properties we defined, for things to get just a bit more interestingly. Fortunately, it's very easy:
    <My:UserInfoBoxControl runat="server" ID="MyUserInfoBoxControl" UserName="John Doe" UserAge="45" UserCountry="Australia" />
    
    You see, every public or protected member can be accessed declaretively, allowing easy access to them when we use our control. However, with this specific UserControl, chances are that you will be receiving the information from an external resource, like a database, and then populating the UserControl from there. This usually involves the CodeBehind of the page, so how can we do that? Pretty simple, actually. In the CodeBehind of the page, try something like this:
    protected void Page_Load(object sender, EventArgs e)
    {
        // These values can come from anywhere, but right now, we just hardcode them
        MyUserInfoBoxControl.UserName = "Jane Doe";
        MyUserInfoBoxControl.UserAge = 33;
        MyUserInfoBoxControl.UserCountry = "Germany";
    }
    

    Loading dynamically

    Sometimes you may wish to add UserControls to your page dynamically instead of declaring them. It's actually quite simple too. You need an existing control where you can add the UserControl to, for instance a Panel. If there's no logical control on your page to add it to, you may create one for the purpose - the PlaceHolder control is for situations just like that.


    Events in UserControls
    In a previous chapter, we looked at defining properties for our UserControl, but events can be declared and used as well! This allows you to encapsulate even more functionality inside your controls, and then let your page respond to certain events, triggered by the control, if necessary.

    For this chapter, we will create a new and very simple UserControl, to illustrate how to create events. It won't have a real life purpose, but is only meant to show you how to use events in a UserControl. If you don't know how to create and use a UserControl, then please go back a few chapters. This one will focus on the event part.

    First, we create a new, simple EventUserControl, with this code in it:
    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="EventUserControl.ascx.cs" Inherits="EventUserControl" %>
    Page title: 
    <asp:TextBox runat="server" ID="txtPageTitle" />
    <asp:Button runat="server" ID="btnUpdatePageTitle" OnClick="btnUpdatePageTitle_Click" Text="Update" />
    
    All just text and server controls that we know. In the CodeBehind, it looks a bit like this:
    public partial class EventUserControl : System.Web.UI.UserControl
    {
        private string pageTitle;
        public event EventHandler PageTitleUpdated;
    
        protected void btnUpdatePageTitle_Click(object sender, EventArgs e)
        {
            this.pageTitle = txtPageTitle.Text;
            if(PageTitleUpdated != null)
                PageTitleUpdated(this, EventArgs.Empty);
        }
    
        public string PageTitle
        {
            get { return pageTitle; }
        }
    }
    
    We have defined a pageTitle container variable and a property for it. Then we have a new thing, an event. As you can see, it's defined much like any other kind of field, but it is a bit different. The theory about is explained in the C# tutorial, so we won't get into that here.

    In the Click event of our button, we set the pageTitle field. Then we check if PageTitleUpdated, our event, is null. If it's not, it means that we have subscribed to this event somewhere, and in that case, we send a notification by calling the PageTitleUpdated as a method. As parameters, we send this (a reference to the UserControl it self) as the sender, and an empty EventArgs parameter. This will make sure that all subscribers are notified that the pageTitle has just been updated. Now, in our page, I've declared our UserControl like this:
    <%@ Register TagPrefix="My" TagName="EventUserControl" Src="~/EventUserControl.ascx" %>
    
    And inserted it like this:
    <My:EventUserControl runat="server" ID="MyEventUserControl" OnPageTitleUpdated="MyEventUserControl_PageTitleUpdated" />
    
    As you can see, we have defined an event handler for the PageTitleUpdated event like if it was any other server control. In the CodeBehind of our page, we define the simple event handler for the UserControl event like this:
    protected void MyEventUserControl_PageTitleUpdated(object sender, EventArgs e)
    {
        this.Title = MyEventUserControl.PageTitle;
    }
    
    It's that simple! Now obviously, updating the page title could have been done directly from our UserControl, so it's just to provide a simple example on how to use events, but as you will likely learn later on, this technic will come in handy in lots of situations.
  • VALIDATION ↓

    Validation

    Validation Introduction
    Ever since the first dynamic website was created, form validation has been an important subject. Getting user input through the system requires much attention, and with previous serverside scripting languages, there were no standard way of dealing with form validation. For that reason, clientside scripting has been used in many cases, but as you probably know, clientside scripting is not bulletproof - it can easily be bypassed or simply turned off. With ASP.NET, webdevelopers were finally given a good, standard set of tools for validating forms. The validation controls of ASP.NET is based on both clientside and serverside technology, which brings the best from both worlds, to make sure that validating a form is as easy as ever.

    ASP.NET 2.0, which is the latest version as I write this, comes with several different validation controls for different purposes. In the following chapters, we will show examples of each of them. They all work in different ways, but essentially they do the same - they make sure that a form field has been properly filled by the user.

    RequiredFieldValidator
    The RequiredFieldValidator is actually very simple, and yet very useful. You can use it to make sure that the user has entered something in a TextBox control. Let's give it a try, and add a RequiredFieldValidator to our page. We will also add a TextBox to validate, as well as a button to submit the form with.
    <form id="form1" runat="server">
        Your name:<br />
        <asp:TextBox runat="server" id="txtName" />
        <asp:RequiredFieldValidator runat="server" id="reqName" controltovalidate="txtName" errormessage="Please enter your name!" />
        <br /><br />
        <asp:Button runat="server" id="btnSubmitForm" text="Ok" />
    </form>
    
    Actually, that's all we need to test the most basic part of the RequiredFieldValidator. I'm sure that all the attributes of the controls makes sense by now, so I won't go into details about them. Try running the website and click the button. You should see something like this:

    Validation example

    If your browser supports JavaScript, which most modern browers do, then you will notice that the page is not being posted back to the server - the validation is performed clientside! This is one of the really cool things about ASP.NET validators. Validation is only performed serverside if necessary! To see how it feels, you can add enableclientscript="false" to the RequiredFieldValidator and try again. Now you will see the browser posting back to the server, but the result will be the same - the validator still works!

    Right now, the button does nothing, besides posting back if the page is valid. We will change this by adding an onclick event to it:
    <asp:Button runat="server" id="btnSubmitForm" text="Ok" onclick="btnSubmitForm_Click" />
    
    In the CodeBehind file, we add the following event handler:
    protected void btnSubmitForm_Click(object sender, EventArgs e)
    {
        if(Page.IsValid)
        {
            btnSubmitForm.Text = "My form is valid!";
        }
    }
    


    As you will notice, we check whether or not the page is valid, before we do anything. This is very important, since this code WILL be reached if the clientside validation is not used, for some reason. Once it comes to serverside validation, it's your job to make sure that no sensitive code is executed unless you want it to. As you see, it's very simple - just check the Page.IsValid parameter, and you're good to go. Try to run the website again, and notice how the text of the button is changed if you submit a valid form.

    CompareValidator
    The CompareValidator might not be the most commonly used validator of the bunch, but it's still useful in some cases. It can compare two values, for instance the values of two controls. In the next example, I will show you a small example of how it can be used.
    Small number:<br />
    <asp:TextBox runat="server" id="txtSmallNumber" /><br /><br />
    Big number:<br />
    <asp:TextBox runat="server" id="txtBigNumber" /><br />
    <asp:CompareValidator runat="server" id="cmpNumbers" controltovalidate="txtSmallNumber" controltocompare="txtBigNumber" operator="LessThan" type="Integer" errormessage="The first number should be smaller than the second number!" /><br />
    
    As you see, we only use one validator to validate the two fields. It might seem a bit overwhelming, but it's actually quite simple. Like with the RequiredFieldValidator, we use the controltovalidate attribute to specify which control to validate. In addition to that, we specify a control to compare. The operator attribute specifies which method to use when comparing. In this case, we use the LessThan operator, because we wish for the first control to have the smallest value. We set the type to integer, because we want to compare integers. Dates, strings and other value types can be compared as well.

    Now, try running the website, and test the two new fields. Here is what happens if you don't fill out the form correctly:

    The CompareValidator in action

    If you switch the numbers, you will see another cool thing about the ASP.NET validators and clientside scripting: Validation is also performed upon exiting the fields. If you don't want this, you can turn off clientside scripting with the enableclientscript attribute. You can also compare a field to a static value. To do this, remove the controltocompare attribute, and add the valuetocompare attribute.

    However, as you may have noticed, the content of the two textboxes is not checked before comparing it. For instance, it would be possible to enter nothing, or enter a piece of text instead of a number. You should always consider this when using the CompareValidator. You can protect against empty fields with the RequiredFieldValidator, and you can protect against wrong values like text with for instance a RegularExpressionValidator, which we will show you how to use a bit later.

    If the clientside validation is not working, the invalid form will be catched by our piece of code in the CodeBehind file, as shown with the RequiredFieldValidator. This is important.

    RangeValidator
    The RangeValidator does exactly what the name implies; it makes sure that the user input is within a specified range. You can use it to validate both numbers, strings and dates, which can make it useful in a bunch of cases. Since we validated numbers the last time, we will try with a date this time.
    Date:<br />
    <asp:TextBox runat="server" id="txtDate" />
    <asp:RangeValidator runat="server" id="rngDate" controltovalidate="txtDate" type="Date" minimumvalue="01-01-2006" maximumvalue="31-12-2006" errormessage="Please enter a valid date within 2006!" />
    <br /><br />
    
    The date format might seem a bit weird to you if you're not from Europe, where we use dd-mm-yy. You can just change it if it doesn't fit the date format on the machine you're working on. Now, try running the website, and enter a date in our new TextBox. It's only valid if the date is within 2006, and a cool sideeffect is that the date is also checked for validity. Have a look at this screenshot, which shows us that the validator reacts to an impossible date as well:

    The RangeValidator in action

    And once again, if the clientside validation is not working, it will be catched in our CodeBehind, as shown with the RequiredFieldValidator. If you missed this part, then be sure to check out the first chapters!

    RegularExpressionValidator
    The RegularExpressionValidator is a bit more difficult to write about, because it requires knowledge of Regular Expressions to really use it. However, RegularExpressionValidator is one of the most useful validators, because it can be used to check the validity of any kind of string. If you don't feel like learning Regular Expressions, but still feel like using this validator, have a look around the Internet. You can find many pre-made expressions out there, which can be very useful to you. Here is an example where we require a 4 digit number - nothing else is acceptable:
    4 digit number:<br />
    <asp:TextBox runat="server" id="txtNumber" />
    <asp:RegularExpressionValidator runat="server" id="rexNumber" controltovalidate="txtNumber" validationexpression="^[0-9]{4}$" errormessage="Please enter a 4 digit number!" />
    <br /><br />
    
    The only new attribute we use, is the validationexpression. This attribute simply holds the Regular Expression which should be used to validate the field. Since Regular Expressions are beyond the scope of this tutorial, I won't try to explain it, other than it simply tells the validator that a value of 4 digitgs is acceptable, and nothing else. You can use the RegularExpressionValidator for almost everything, for instance validating an e-mail or an URL.

    Try switching to Design view and select the RegularExpressionValidator on your page. Now have a look in the Properties tab of Visual Studio. The ValidationExpression attribute has a button next to it, and if you click it, you will gain access to some default expressions, delivered by the ASP.NET team, for various purposes. Just select one of them, to use in your validator.

    CustomValidator
    If none of the other validators can help you, the CustomValidator usually can. It doesn't come with a predefined way of working; you write the code for validating your self. This is of course very powerful, since the possibilities are basically endless. A common way of using the CustomValidator is when you need to make a database lookup to see if the value is valid. Since this tutorial hasn't treated database access yet, we will do a simpler example, but hopefully you will see that you can do just about everything with the CustomValidator. The control allows you to validate both clientside and serverside, where the serverside approach is probably the most powerful. Of course, doing serverside validation requires a postback to validate, but in most cases, that's not really a problem.

    In this example, we will simply check the length of the string in the TextBox. This is a very basic and that useful example, only made to show you how you may use the CustomValidator.
    Custom text:<br />
    <asp:TextBox runat="server" id="txtCustom" />
    <asp:CustomValidator runat="server" id="cusCustom" controltovalidate="txtCustom" onservervalidate="cusCustom_ServerValidate" errormessage="The text must be exactly 8 characters long!" />
    <br /><br />
    
    As you can see, it's pretty simple. The only unknown property is the onservervalidate event. It's used to reference a method from CodeBehind which will handle the validation. Switch to our CodeBehind file and add the following method:
    protected void cusCustom_ServerValidate(object sender, ServerValidateEventArgs e)
    {
        if(e.Value.Length == 8)
            e.IsValid = true;
        else
            e.IsValid = false;
    }
    
    This is very simple. The validator basically works by setting the e.IsValid boolean value to either true or false. Here we check the e.Value, which is the string of the control being validated, for it's length. If it's exactly 8 characters long, we return true, otherwise we return false.

    The validators all share a couple of attributes, which can be very useful in some cases.

    ValidationGroup

    This attribute was introduced with ASP.NET 2.0, and makes it possible to divide your form elements into groups. Usually, a validator control is always triggered on a postback, which could sometimes lead to problems. For instance, if you have a contact form and a search field on the same page, the validation of the contact form could be triggered by the Search button, preventing the user from searching before filling out the contact form. You can assign a name in the validationgroup property, for both the validators and the button(s) that you wish to be able to trigger the validation. The value of the attribute can be a number or a name, like validationgroup="contact_form".

    SetFocusOnError (true|false)

    This attribute was also introduced with ASP.NET 2.0, and it does exactly what the name implies. Set SetFocusOnError to true on one or several of your validators, to give focus to the first invalid field when the form is validated.

    Display (Dynamic|None|Static)

    This attribute decides how the validator is rendered to your page. The default value is Static, which makes the validator take up the required place whether it's visible (active) or not. You can test this by placing a piece of text directly behind a validator and load the page. If you have not set the Display attribute, or if you have set it to Static, you will see that the text is moved. However, if you set it to Dynamic, the validator will only take up any space if the validation fails and the validator is activated. This can be convenient in some cases, where you need the space the validator can take up otherwise. If you set it to None, the error message will never be shown.
  • CACHING ↓

    Introduction

    One of the really cool features of ASP.NET is the caching. With other technologies, caching usually requires some extra software or at least complicated code, but with ASP.NET 2.0, it's easier than ever before. You can use two different kinds of caching - output caching and standard caching. The first one is the easiest, so let's start with that. In the following chapters we will use various forms of the OutputCache directive, as well as the ASP.NET Cache object. Read on.

    advertise here!!!
    OutputCache
    In this chapter, we will take a look at the OutputCache directive, which is by far the easiest way of caching content with ASP.NET. As you will see in our example, it doesn’t even require any code – only some minor changes to the markup of the page, and you’re good to go. In the next chapter, we will look into more ways of using the OuputCachce directive.

    Here is a very simple example of a page which will show us the difference between a cached page and a non-cached page. Try creating a new project, and change the Default.aspx page to contain the following markup:
    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Caching</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <%= DateTime.Now.ToString() %>
        </form>
    </body>
    </html>
    
    This is all standard stuff, except the line with the DateTime. It simply outputs the current date and time to the page. Try running the project and reload the page a couple of times. As you will see, the time is refreshed on each reload. Now, add the following line as line number 2 to our example:
    <%@ OutputCache duration="10" varybyparam="None" %>
    
    Run our project again, and reload the page a number of times. As you will see, the time is only refreshed every 10 seconds. Adding caching to your page is as simple as that! Now, the duration parameter is pretty obvious - it tells the page how many seconds to cache the content. Each time the page is requested, ASP.NET checks if the page is in the cache, and if it is, whether or not it has expired. It's served from the cache if it isn't expired - if it is, the page is removed from the cache and the page is generated from scratch and then placed in the cache.

    The varybyparam is a required parameter of the OutputCache directive. It specifies a list of parameters which the the cache should be varied by. For instance, if you set it to "p", the cache is now depending on the value of the parameter p. Try changing our example to something like this:
    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
    <%@ OutputCache duration="10" varybyparam="p" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Caching</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <%= DateTime.Now.ToString() %><br />
            <a href="?p=1">1</a><br />
            <a href="?p=2">2</a><br />
            <a href="?p=3">3</a><br />
        </form>
    </body>
    </html>
    
    Now, run our example again, and try clicking the links. They each now have their own timestamp, based on when you first accessed the page. The cache is depending on the value of the p parameter! You can specify multiple parameters by seperating them with a semicolon.


    More Example Caching

    In the last chapter, we looked at using the OutputCache directive to cache our page very simply. In this chapter, we will look into other ways of using the OutputCache. We used varybyparam in the previous example, but you can vary your cache by other factors as well. Here is a brief list and some examples.

    OutputCache - varybyparam

    Please see the previous chapter for more information on the varybyparam parameter.

    OutputCache - varybycontrol

    The varybycontrol does exactly what it says - it varies the cache depending on the value of the specified control. For instance, you can have a dropdownlist with a set of selections, and base the content of the page based on the selected item. In that case, it will make sense to vary by the value of this control, since the content of the page changes according to it. Here is an example of using the varybycontrol parameter:
    <%@ OutputCache duration="10" varybyparam="none" varybycontrol="NameOfControl" %>
    

    OutputCache - varybycustom

    This is probably the least easy way of using the OutputCache system, but on the other hand, probably the most flexible. It allows you to handle the variations your self, by setting a custom string, which ASP.NET will vary the output by. To test this, you need to add a global.asax file to your project, if you don't already have one. Right click on your project in the Solution Explorer, and select Add new item. Now select the "Global Application Class" and click Ok. In the Global.asax file, you need to override the GetVaryByCustomString like this:
    public override string GetVaryByCustomString(HttpContext context, string custom)
    {
        if(custom == "Browser")
        {
            return context.Request.Browser.Browser;
        }
        return String.Empty;
    }
    
    In this case, our caching will be varied based on which browser the user accesses the page with. The markup part should be written like this:
    <%@ OutputCache duration="120" varybyparam="None" varybycustom="Browser" %>
    Try accessing the page from different browsers. You will see that the output now depends on which browser you use. The Browser object comes with a bunch of useful information about the client browser - for instance you could vary by whether or not the browser supports CSS, JavaScript or something else.

    OutputCache - varybyheader

    This one allows you to vary the content based on one or more of the headers that browser send. Here is an example:
    <%@ OutputCache duration="120" varybyparam="None" varybyheader="Accept-Language" %>
    
    This will vary cache based on the Accept-Language header, which tells the server which languages the user accepts and prefers.


    Substitution
    With ASP.NET version 1.0 and 1.1, there was no way to control which parts of a page would be cached, and more importantly: Which parts would be generated on each request no matter what. That meant that whenever you needed just a small part of the page to refreshed on each request, the OutputCache directive could not be used. This has changed with ASP.NET 2.0, where we may use the <asp:Substitution> tag to make areas exist outside the cached content. Have a look at the following example:
    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
    <%@ OutputCache duration="120" varybyparam="None" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Caching</title>
    </head>
    <body>
        <form id="form1" runat="server">
            Cached datestamp:<br />
            <%= DateTime.Now.ToString() %><br /><br />
            Fresh datestamp:<br />
            <asp:Substitution runat="server" id="UnCachedArea" methodname="GetFreshDateTime" />
        </form>
    </body>
    </html> 
    
    The Substitution tag takes an attribute called methodname, which holds the name of a method which should return the string to output. Once the page is loaded, no matter if it's returned from the cache or freshly generated, this method will be called, and the Substitution control will be filled with the returned string. Here is the CodeBehind, where you will see our GetFreshDateTime method:
    using System;
    using System.Data;
    using System.Web;
    
    public partial class _Default : System.Web.UI.Page 
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }
    
        protected static string GetFreshDateTime(HttpContext context)
        {
            return DateTime.Now.ToString();
        }
    }
    
    Since the GetFreshDateTime method needs to be called by the Substitution control, it needs to "look" a certain way - it has to take the HttpContext as a parameter, it has to return a string, and it has to be static. Now, the HttpContext allows you to access all kinds of information about the request etc. to use for returning the proper value. For now, we simply return the current datetime. Run the example, and see how the first datestamp is cached, while the second is reloaded each time. It's as simple as that!


    Caching objects
    While the OutputCache directive is easy to use and work with, it allows you only to cache the entire page, or an entire UserControl. While this is just fine for some situations, there will be times where caching an object will be much smarter. While the following example might seem a bit silly, it does show how the Cache object can be used to store for instance an ArrayList with custom objects in it. Create a new project, or use an existing page and change the CodeBehind Page_Load method to something like this (this example doesn't require you to modify the markup part):
    protected void Page_Load(object sender, EventArgs e)
    {
        ArrayList datestamps;
        if(Cache["datestamps"] == null)
        {
            datestamps = new ArrayList();
            datestamps.Add(DateTime.Now);
            datestamps.Add(DateTime.Now);
            datestamps.Add(DateTime.Now);
    
            Cache.Add("datestamps", datestamps, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(0, 0, 60), System.Web.Caching.CacheItemPriority.Default, null);
        }
        else
            datestamps = (ArrayList)Cache["datestamps"];
    
        foreach(DateTime dt in datestamps)
            Response.Write(dt.ToString() + "<br />");
    }
    
    Try running this example and reloading the page. 3 instances of the current date is placed in an ArrayList, and the list is then cached using the Cache object. On each page load, the Cache is checked to see if it contains our ArrayList, using a name we have provided. If it's not, the list is generated, filled and cached. If the ArrayList is already in the cache, we pull it out and cast it to the correct type (everything is stored as object types). No matter where we get the list from, we iterate through it and output each value.

    Most of it should be pretty straight forward, except for the line where we add the list to the Cache. The Add method takes a bunch of parameters, and I will try to explain all of them.

    First of all, the key we wish to store our object by, in this case we simply call it "datestamps". The key is used to get the object back from the Cache.

    Next parameter is the object we wish to cache, so that goes without explaining.

    Next up is the CacheDependency parameter. It can be used to tell ASP.NET that the cached item depends on other items, allowing ASP.NET to invalidate the cache if one of these items changes.

    The following two parameters tells ASP.NET how and when the item should expire in the cache. The first one specifies an absolute expiration, meaning that the item will expire at a certain time of day. This is usually not what you want, so we set it to NoAbsoluteExpiration. Next we can specify a sliding expiration, which means that the item will expire after a certain amount of time, based on when the item is placed in the cache. The TimeSpan class is used, and we specify that it should expire after 0 hours, 0 minutes and 60 seconds. A priority can be set for the item in the cache. This is used when ASP.NET is removing items from the cache - items with a lower priority are removed first.

    The last parameter allows us to specify a callback function for the item, which will be called once the item is removed from the cache, in case you need that. We simply specify a null value.

    So, as you can see, storing items by using the Cache object is really easy. Of course, we don't really earn any performance in this example, but only the imagination is the limit here. One of the most common practices are storing objects retrieved from a database in the cache, so save resources on the database machine and allow for faster loading pages.
  • STATE ↓

    Cookies
    Cookies are small pieces of text, stored on the client's computer to be used only by the website setting the cookies. This allows webapplications to save information for the user, and then re-use it on each page if needed. Here is an example where we save a users choice of background color:
    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Cookies</title>
    </head>
    <body runat="server" id="BodyTag">
        <form id="form1" runat="server">
        <asp:DropDownList runat="server" id="ColorSelector" autopostback="true" onselectedindexchanged="ColorSelector_IndexChanged">
            <asp:ListItem value="White" selected="True">Select color...</asp:ListItem>
            <asp:ListItem value="Red">Red</asp:ListItem>
            <asp:ListItem value="Green">Green</asp:ListItem>
            <asp:ListItem value="Blue">Blue</asp:ListItem>
        </asp:DropDownList>
        </form>
    </body>
    </html>
    
    The page simply contains a DropDownList control, which automatically posts back each time a new item is selected. It has 3 different colors, besides the default one, which is simply white. Once a new item is selected, the ColorSelector_IndexChanged method is fired, from our CodeBehind file:
    using System;
    using System.Data;
    using System.Web;
    
    public partial class _Default : System.Web.UI.Page 
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if(Request.Cookies["BackgroundColor"] != null)
            {
                ColorSelector.SelectedValue = Request.Cookies["BackgroundColor"].Value;
                BodyTag.Style["background-color"] = ColorSelector.SelectedValue;
            }
        }
    
        protected void ColorSelector_IndexChanged(object sender, EventArgs e)
        {
            BodyTag.Style["background-color"] = ColorSelector.SelectedValue;
            HttpCookie cookie = new HttpCookie("BackgroundColor");
            cookie.Value = ColorSelector.SelectedValue;
            cookie.Expires = DateTime.Now.AddHours(1);
            Response.SetCookie(cookie);
        }
    }
    
    Okay, two different parts to be explained here. First, the Page_Load method, which is called on each page request. Here we check for a cookie to tell us which background color should be used. If we find it, we set the value of our dropdown list to reflect this, as well as the background color of the page, simply by accessing the style attribute of the body tag.

    Then we have the ColorSelector_IndexChanged method, which is called each time the user selects a new color. Here we set the background color of the page, and then we create a cookie, to hold the value for us. We allow it to expire after one hour, and then we set it by calling the SetCookie method on the Response object.

    Try running the example, and set a color. Now close the browser, and start it up again. You will see that the choice of color is saved, and it will remain saved for an hour. However, nothing prevents you from saving the choice for much longer. Simply add a bigger value to the expiry date, or set an absolute value for it.


    Sessions
    Sessions can be used to store even complex data for the user just like cookies. Actually, sessions will use cookies to store the data, unless you explicitly tell it not to. Sessions can be used easily in ASP.NET with the Session object. We will re-use the cookie example, and use sessions instead. Keep in mind though, that sessions will expire after a certain amount of minutes, as configured in the web.config file. Markup code:
    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Sessions</title>
    </head>
    <body runat="server" id="BodyTag">
        <form id="form1" runat="server">
        <asp:DropDownList runat="server" id="ColorSelector" autopostback="true" onselectedindexchanged="ColorSelector_IndexChanged">
            <asp:ListItem value="White" selected="True">Select color...</asp:ListItem>
            <asp:ListItem value="Red">Red</asp:ListItem>
            <asp:ListItem value="Green">Green</asp:ListItem>
            <asp:ListItem value="Blue">Blue</asp:ListItem>
        </asp:DropDownList>
        </form>
    </body>
    </html>
    
    And here is the CodeBehind:
    using System;
    using System.Data;
    using System.Web;
    
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if(Session["BackgroundColor"] != null)
            {
                ColorSelector.SelectedValue = Session["BackgroundColor"].ToString();
                BodyTag.Style["background-color"] = ColorSelector.SelectedValue;
            }
        }
    
        protected void ColorSelector_IndexChanged(object sender, EventArgs e)
        {
            BodyTag.Style["background-color"] = ColorSelector.SelectedValue;
            Session["BackgroundColor"] = ColorSelector.SelectedValue;
        }
    }
    
    As you can see, the example doesn't need a lot of changes to use sessions instead of cookies. Please notice that session values are tied to an instance of your browser. If you close down the browser, the saved value(s) will usually be "lost".

    Also, if the webserver recycles the aspnet_wp.exe process, sessions are lost, since they are saved in memory as well. This can be avoided by saving session states on a separate StateServer or by saving to a SQL server, but that's beyond the scope of this article.


    ViewState
    Another approach to saving data for the user, is the ViewState. As described elsewhere in this tutorial, the ViewState allows ASP.NET to repopulate form fields on each postback to the server, making sure that a form is not automatically cleared when the user hits the submit button. All this happens automatically, unless you turn it off, but you can actually use the ViewState for your own purposes as well. Please keep in mind though, that while cookies and sessions can be accessed from all your pages on your website, ViewState values are not carried between pages. Here is a simple example of using the ViewState to carry values between postbacks:
    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>ViewState</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <asp:TextBox runat="server" id="NameField" />
            <asp:Button runat="server" id="SubmitForm" onclick="SubmitForm_Click" text="Submit & set name" />
            <asp:Button runat="server" id="RefreshPage" text="Just submit" />
            <br /><br />
            Name retrieved from ViewState: <asp:Label runat="server" id="NameLabel" />
        </form> 
    </body>
    </html>
    
    And the CodeBehind:
    using System;
    using System.Data;
    using System.Web;
    
    public partial class _Default : System.Web.UI.Page 
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if(ViewState["NameOfUser"] != null)
                NameLabel.Text = ViewState["NameOfUser"].ToString();
            else
                NameLabel.Text = "Not set yet...";
        }
    
        protected void SubmitForm_Click(object sender, EventArgs e)
        {
            ViewState["NameOfUser"] = NameField.Text;
            NameLabel.Text = NameField.Text;
        }
    }
    
    Try running the project, enter your name in the textbox and press the first button. The name will be saved in the ViewState and set to the Label as well. No magic here at all. Now press the second button. This one does nothing at all actually, it just posts back to the server.

    As you will notice, the NameLabel still contains the name, but so does the textbox. The first thing is because of us, while the textbox is maintained by ASP.NET it self. Try deleting the value and pressing the second button again. You will see that the textbox is now cleared, but our name label keeps the name, because the value we saved to the ViewState is still there!

    ViewState is pretty good for storing simple values for use in the form, but if you wish to save more complex data, and keep them from page to page, you should look into using cookies or sessions, as described in the previous chapters.
  • MISC ↓

    Sending e-mails
    Sending e-mails with ASP.NET is pretty straight forward. The .NET framework comes with an entire namespace for handling e-mails, the System.Net.Mail namespace. In the following examples, we will use two classes from this namespace: The MailMessage class, for the actual e-mail, and the SmtpClient class, for sending the e-mail.

    As you may be aware, mails are sent through an SMTP server, and to send mails with the .NET framework, you will need access to an SMTP server. If you're testing things locally, the company that supplies your with Internet access, will usually have an SMTP server that you can use, and if you wish to use one of these examples on your actual website, the company that hosts your website will usually have an SMTP server that you can use. Go through the support pages to find the actual address - it's usually something along the lines of smtp.your-isp.com or mail.your-isp.com.

    Once you have an accessible SMTP server, we're ready to send our very first e-mail. For the first example, all you need is an empty page, with the following code in the CodeBehind:

    protected void Page_Load(object sender, EventArgs e)
    {
        try
        {
            MailMessage mailMessage = new MailMessage();
            mailMessage.To.Add("your.own@mail-address.com");
            mailMessage.From = new MailAddress("another@mail-address.com");
            mailMessage.Subject = "ASP.NET e-mail test";
            mailMessage.Body = "Hello world,\n\nThis is an ASP.NET test e-mail!";
            SmtpClient smtpClient = new SmtpClient("smtp.your-isp.com");
            smtpClient.Send(mailMessage);
            Response.Write("E-mail sent!");
        }
        catch(Exception ex)
        {
            Response.Write("Could not send the e-mail - error: " + ex.Message);
        }
    }
    

    That's actually all you need to send an e-mail. We create a new MailMessage instance, add a new receiver, set the "From" address and the subject, and then we write a simple test message for the body of the e-mail. After that, we create a new instance of the SmtpClient, with the host address of the SMTP server that you may use as a parameter, and then we use the SmtpClient instance to shoot the e-mail out into cyberspace. The entire thing is surrounded by a try..catch block, just in case something goes wrong.

    This was just a very basic example, but there are a lot of other options. Here is a short list with interesting ideas:

    You can attach one or several files, simply by adding them to the Attachments collection. In this example, we attach a file called "image.jpg", located in the root of the ASP.NET website:
    mailMessage.Attachments.Add(new Attachment(Server.MapPath("~/image.jpg")));
    
    You can send to more than one person at the same time, simply by adding another e-mail address to the "To" collection, like this:
    mailMessage.To.Add("your.own@mail-address.com");
    mailMessage.To.Add("another@mail-address.com");
    
    You can set a name for the sender - otherwise, only the e-mail address will be shown in the "From" column of the receivers e-mail client. For instance, like this:
    mailMessage.From = new MailAddress("me@mail-address.com", "My Name");
    
    You can send HTML e-mails, instead of the default plaintext mails, to use more complicated layouts. Here is a simple example:
    mailMessage.IsBodyHtml = true;
    mailMessage.Body = "Hello <b>world!</b>";
    
    You can use the CC and BCC fields, just like in regular e-mail messages, like this:
    mailMessage.CC.Add("me@mail-address.com");
    mailMessage.Bcc.Add("me2@mail-address.com");
    
    You can set the priority of an e-mail, like this:
    mailMessage.Priority = MailPriority.High;
    



    Controls

    FileUpload control
    With ASP.NET, accepting file uploads from users has become extremely easy. With the FileUpload control, it can be done with a small amount of code lines, as you will see in the following example. However, please notice that there are security concerns to to consider when accepting files from users! Here is the markup required:
    <form id="form1" runat="server">
        <asp:FileUpload id="FileUploadControl" runat="server" />
        <asp:Button runat="server" id="UploadButton" text="Upload" onclick="UploadButton_Click" />
        <br /><br />
        <asp:Label runat="server" id="StatusLabel" text="Upload status: " />
    </form>
    
    And here is the CodeBehind code required to handle the upload:
    protected void UploadButton_Click(object sender, EventArgs e)
    {
        if(FileUploadControl.HasFile)
        {
            try
            {
                string filename = Path.GetFileName(FileUploadControl.FileName);
                FileUploadControl.SaveAs(Server.MapPath("~/") + filename);
                StatusLabel.Text = "Upload status: File uploaded!";
            }
            catch(Exception ex)
            {
                StatusLabel.Text = "Upload status: The file could not be uploaded. The following error occured: " + ex.Message;
            }
        }
    }
    
    As you can see, it's all relatively simple. Once the UploadButton is clicked, we check to see if a file has been specified in the upload control. If it has, we use the FileUpload controls SaveAs method to save the file. We use the root of our project (we use the MapPath method to get this) as well as the name part of the path which the user specified. If everything goes okay, we notify the user by setting the Text property of the StatusLabel - if not, an exception will be thrown, and we notify the user as well.

    This example will get the job done, but as you can see, nothing is checked. The user can upload any kind of file, and the size of the file is only limited by the server configuration. A more robust example could look like this:
    protected void UploadButton_Click(object sender, EventArgs e)
    {
        if(FileUploadControl.HasFile)
        {
            try
            {
                if(FileUploadControl.PostedFile.ContentType == "image/jpeg")
                {
                    if(FileUploadControl.PostedFile.ContentLength < 102400)
                    {
                        string filename = Path.GetFileName(FileUploadControl.FileName);
                        FileUploadControl.SaveAs(Server.MapPath("~/") + filename);
                        StatusLabel.Text = "Upload status: File uploaded!";
                    }
                    else
                        StatusLabel.Text = "Upload status: The file has to be less than 100 kb!";
                }
                else
                    StatusLabel.Text = "Upload status: Only JPEG files are accepted!";
            }
            catch(Exception ex)
            {
                StatusLabel.Text = "Upload status: The file could not be uploaded. The following error occured: " + ex.Message;
            }
        }
    }
    
    Here we use the two properties, ContentLength and ContentType, to do some basic checking of the file which the user is trying to upload. The status messages should clearly indicate what they are all about, and you can change them to fit your needs.
  • AD ROTATOR ↓

    The AdRotator control randomly selects banner graphics from a list, which is specified in an external XML schedule file. This external XML schedule file is called the advertisement file.

    The AdRotator control allows you to specify the advertisement file and the type of window that the link should follow in the AdvertisementFile and the Target property respectively.

    The basic syntax of adding an AdRotator is as follows:

    <asp:AdRotator  runat = "server" AdvertisementFile = "adfile.xml"  Target =  "_blank" />
    

    Before going into the details of the AdRotator control and its properties, let us look into the construction of the advertisement file.

    The Advertisement File

    The advertisement file is an XML file, which contains the information about the advertisements to be displayed.

    Extensible Markup Language (XML) is a W3C standard for text document markup. It is a text-based markup language that enables you to store data in a structured format by using meaningful tags. The term 'extensible' implies that you can extend your ability to describe a document by defining meaningful tags for the application.

    XML is not a language in itself, like HTML, but a set of rules for creating new markup languages. It is a meta-markup language. It allows developers to create custom tag sets for special uses. It structures, stores, and transports the information.

    Following is an example of XML file:

    <BOOK>
       <NAME> Learn XML </NAME>
       <AUTHOR> Samuel Peterson </AUTHOR>
       <PUBLISHER> NSS Publications </PUBLISHER>
       <PRICE> $30.00</PRICE>
    </BOOK>
    

    Like all XML files, the advertisement file needs to be a structured text file with well-defined tags delineating the data. There are the following standard XML elements that are commonly used in the advertisement file:

    Element Description
    Advertisements Encloses the advertisement file.
    Ad Delineates separate ad.
    ImageUrl The path of image that will be displayed.
    NavigateUrl The link that will be followed when the user clicks the ad.
    AlternateText The text that will be displayed instead of the picture if it cannot be displayed.
    Keyword Keyword identifying a group of advertisements. This is used for filtering.
    Impressions The number indicating how often an advertisement will appear.
    Height Height of the image to be displayed.
    Width Width of the image to be displayed.

    Apart from these tags, customs tags with custom attributes could also be included. The following code illustrates an advertisement file ads.xml:

    <Advertisements>
       <Ad>
          <ImageUrl>rose1.jpg</ImageUrl>
          <NavigateUrl>http://www.1800flowers.com</NavigateUrl>
          <AlternateText>
             Order flowers, roses, gifts and more
          </AlternateText>
          <Impressions>20</Impressions>
          <Keyword>flowers</Keyword>
       </Ad>
    
       <Ad>
          <ImageUrl>rose2.jpg</ImageUrl>
          <NavigateUrl>http://www.babybouquets.com.au</NavigateUrl>
          <AlternateText>Order roses and flowers</AlternateText>
          <Impressions>20</Impressions>
          <Keyword>gifts</Keyword>
       </Ad>
    
       <Ad>
          <ImageUrl>rose3.jpg</ImageUrl>
          <NavigateUrl>http://www.flowers2moscow.com</NavigateUrl>
          <AlternateText>Send flowers to Russia</AlternateText>
          <Impressions>20</Impressions>
          <Keyword>russia</Keyword>
       </Ad>
    
       <Ad>
          <ImageUrl>rose4.jpg</ImageUrl>
          <NavigateUrl>http://www.edibleblooms.com</NavigateUrl>
          <AlternateText>Edible Blooms</AlternateText>
          <Impressions>20</Impressions>
          <Keyword>gifts</Keyword>
       </Ad>
    </Advertisements>
    

    Properties and Events of the AdRotator Class

    The AdRotator class is derived from the WebControl class and inherits its properties. Apart from those, the AdRotator class has the following properties:

    Properties Description
    AdvertisementFile The path to the advertisement file.
    AlternateTextFeild The element name of the field where alternate text is provided. The default value is AlternateText.
    DataMember The name of the specific list of data to be bound when advertisement file is not used.
    DataSource Control from where it would retrieve data.
    DataSourceID Id of the control from where it would retrieve data.
    Font Specifies the font properties associated with the advertisement banner control.
    ImageUrlField The element name of the field where the URL for the image is provided. The default value is ImageUrl.
    KeywordFilter For displaying the keyword based ads only.
    NavigateUrlField The element name of the field where the URL to navigate to is provided. The default value is NavigateUrl.
    Target The browser window or frame that displays the content of the page linked.
    UniqueID Obtains the unique, hierarchically qualified identifier for the AdRotator control.

    Following are the important events of the AdRotator class:

    Events Description
    AdCreated It is raised once per round trip to the server after creation of the control, but before the page is rendered
    DataBinding Occurs when the server control binds to a data source.
    DataBound Occurs after the server control binds to a data source.
    Disposed Occurs when a server control is released from memory, which is the last stage of the server control lifecycle when an ASP.NET page is requested
    Init Occurs when the server control is initialized, which is the first step in its lifecycle.
    Load Occurs when the server control is loaded into the Page object.
    PreRender Occurs after the Control object is loaded but prior to rendering.
    Unload Occurs when the server control is unloaded from memory.

    Working with AdRotator Control

    Create a new web page and place an AdRotator control on it.

    <form id="form1" runat="server">
       <div>
          <asp:AdRotator ID="AdRotator1" runat="server" AdvertisementFile  ="~/ads.xml" onadcreated="AdRotator1_AdCreated" />
       </div>
    </form>
    

    The ads.xml file and the image files should be located in the root directory of the web site.

    Try to execute the above application and observe that each time the page is reloaded, the ad is changed.


  • CALENDER ↓

    The calendar control is a functionally rich web control, which provides the following capabilities:

    • Displaying one month at a time
    • Selecting a day, a week or a month
    • Selecting a range of days
    • Moving from month to month
    • Controlling the display of the days programmatically

    The basic syntax of a calendar control is:

    <asp:Calender ID = "Calendar1" runat = "server">
    </asp:Calender>
    

    Properties and Events of the Calendar Control

    The calendar control has many properties and events, using which you can customize the actions and display of the control. The following table provides some important properties of the Calendar control:

    Properties Description
    Caption Gets or sets the caption for the calendar control.
    CaptionAlign Gets or sets the alignment for the caption.
    CellPadding Gets or sets the number of spaces between the data and the cell border.
    CellSpacing Gets or sets the space between cells.
    DayHeaderStyle Gets the style properties for the section that displays the day of the week.
    DayNameFormat Gets or sets format of days of the week.
    DayStyle Gets the style properties for the days in the displayed month.
    FirstDayOfWeek Gets or sets the day of week to display in the first column.
    NextMonthText Gets or sets the text for next month navigation control. The default value is >.
    NextPrevFormat Gets or sets the format of the next and previous month navigation control.
    OtherMonthDayStyle Gets the style properties for the days on the Calendar control that are not in the displayed month.
    PrevMonthText Gets or sets the text for previous month navigation control. The default value is <.
    SelectedDate Gets or sets the selected date.
    SelectedDates Gets a collection of DateTime objects representing the selected dates.
    SelectedDayStyle Gets the style properties for the selected dates.
    SelectionMode Gets or sets the selection mode that specifies whether the user can select a single day, a week or an entire month.
    SelectMonthText Gets or sets the text for the month selection element in the selector column.
    SelectorStyle Gets the style properties for the week and month selector column.
    SelectWeekText Gets or sets the text displayed for the week selection element in the selector column.
    ShowDayHeader Gets or sets the value indicating whether the heading for the days of the week is displayed.
    ShowGridLines Gets or sets the value indicating whether the gridlines would be shown.
    ShowNextPrevMonth Gets or sets a value indicating whether next and previous month navigation elements are shown in the title section.
    ShowTitle Gets or sets a value indicating whether the title section is displayed.
    TitleFormat Gets or sets the format for the title section.
    Titlestyle Get the style properties of the title heading for the Calendar control.
    TodayDayStyle Gets the style properties for today's date on the Calendar control.
    TodaysDate Gets or sets the value for today's date.
    UseAccessibleHeader Gets or sets a value that indicates whether to render the table header <th> HTML element for the day headers instead of the table data <td> HTML element.
    VisibleDate Gets or sets the date that specifies the month to display.
    WeekendDayStyle Gets the style properties for the weekend dates on the Calendar control.

    The Calendar control has the following three most important events that allow the developers to program the calendar control. They are:

    Events Description
    SelectionChanged It is raised when a day, a week or an entire month is selected.
    DayRender It is raised when each data cell of the calendar control is rendered.
    VisibleMonthChanged It is raised when user changes a month.

    Working with the Calendar Control

    Putting a bare-bone calendar control without any code behind file provides a workable calendar to a site, which shows the months and days of the year. It also allows navigation to next and previous months.

    Calendar

    Calendar controls allow the users to select a single day, a week, or an entire month. This is done by using the SelectionMode property. This property has the following values:

    Properties Description
    Day To select a single day.
    DayWeek To select a single day or an entire week.
    DayWeekMonth To select a single day, a week, or an entire month.
    None Nothing can be selected.

    The syntax for selecting days:

    <asp:Calender ID = "Calendar1" runat = "server" SelectionMode="DayWeekMonth">
    </asp:Calender>
    

    When the selection mode is set to the value DayWeekMonth, an extra column with the > symbol appears for selecting the week, and a >> symbol appears to the left of the days name for selecting the month.

    Calendar2

    Example

    The following example demonstrates selecting a date and displays the date in a label:

    The content file code is as follows:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="calendardemo._Default" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
    
       <head runat="server">
          <title>
             Untitled Page
          </title>
       </head>
       
       <body>
          <form id="form1" runat="server">
          
             <div>
                <h3> Your Birthday:</h3>
                <asp:Calendar ID="Calendar1" runat="server  SelectionMode="DayWeekMonth" onselectionchanged="Calendar1_SelectionChanged">
                </asp:Calendar>
             </div>
             
             <p>Todays date is: 
                <asp:Label ID="lblday" runat="server"></asp:Label>
             </p>
             
             <p>Your Birday is: 
                <asp:Label ID="lblbday" runat="server"></asp:Label>
             </p>
             
          </form>
       </body>
    </html>
    

    The event handler for the event SelectionChanged:

    protected void Calendar1_SelectionChanged(object sender, EventArgs e)
    {
       lblday.Text = Calendar1.TodaysDate.ToShortDateString();
       lblbday.Text = Calendar1.SelectedDate.ToShortDateString();
    }
    

    When the file is run, it should produce the following output:

    Calendar3


    MULTYVIEW CALENDER

    MultiView and View controls allow you to divide the content of a page into different groups, displaying only one group at a time. Each View control manages one group of content and all the View controls are held together in a MultiView control.

    The MultiView control is responsible for displaying one View control at a time. The View displayed is called the active view.

    The syntax of MultiView control is:

    <asp:MultView ID= "MultiView1" runat= "server">
    </asp:MultiView>
    

    The syntax of View control is:

    <asp:View ID= "View1" runat= "server">
    </asp:View>
    

    However, the View control cannot exist on its own. It would render error if you try to use it stand-alone. It is always used with a Multiview control as:

    <asp:MultView ID= "MultiView1" runat= "server">
       <asp:View ID= "View1" runat= "server"> </asp:View>
    </asp:MultiView>
    

    Properties of View and MultiView Controls

    Both View and MultiView controls are derived from Control class and inherit all its properties, methods, and events. The most important property of the View control is Visible property of type Boolean, which sets the visibility of a view.

    The MultiView control has the following important properties:

    Properties Description
    Views Collection of View controls within the MultiView.
    ActiveViewIndex A zero based index that denotes the active view. If no view is active, then the index is -1.

    The CommandName attribute of the button control associated with the navigation of the MultiView control are associated with some related field of the MultiView control.

    For example, if a button control with CommandName value as NextView is associated with the navigation of the multiview, it automatically navigates to the next view when the button is clicked.

    The following table shows the default command names of the above properties:

    Properties Description
    NextViewCommandName NextView
    PreviousViewCommandName PrevView
    SwitchViewByIDCommandName SwitchViewByID
    SwitchViewByIndexCommandName SwitchViewByIndex

    The important methods of the multiview control are:

    Methods Description
    SetActiveview Sets the active view
    GetActiveview Retrieves the active view

    Every time a view is changed, the page is posted back to the server and a number of events are raised. Some important events are:

    Events Description
    ActiveViewChanged Raised when a view is changed
    Activate Raised by the active view
    Deactivate Raised by the inactive view

    Apart from the above mentioned properties, methods and events, multiview control inherits the members of the control and object class.

    Example

    The example page has three views. Each view has two button for navigating through the views.

    The content file code is as follows:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="multiviewdemo._Default" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
    
       <head runat="server">
          <title>
             Untitled Page
          </title>
       </head>
       
       <body>
          <form id="form1" runat="server">
          
             <div>
                <h2>MultiView and View Controls</h2>
                
                <asp:DropDownList ID="DropDownList1" runat="server" onselectedindexchanged="DropDownList1_SelectedIndexChanged">
                </asp:DropDownList>
                
                <hr />
                
                <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="2"  onactiveviewchanged="MultiView1_ActiveViewChanged" >
                   <asp:View ID="View1" runat="server">
                      <h3>This is view 1</h3>
                      <br />
                      <asp:Button CommandName="NextView" ID="btnnext1" runat="server" Text = "Go To Next" />
                      <asp:Button CommandArgument="View3" CommandName="SwitchViewByID" ID="btnlast" runat="server" Text  ="Go To Last" />
                   </asp:View> 
    					
                   <asp:View ID="View2" runat="server">
                      <h3>This is view 2</h3>
                      <asp:Button CommandName="NextView" ID="btnnext2" runat="server" Text = "Go To Next" />
                      <asp:Button CommandName="PrevView" ID="btnprevious2" runat="server" Text = "Go To Previous View" />
                   </asp:View> 
    
                   <asp:View ID="View3" runat="server">
                      <h3> This is view 3</h3>
                      <br />
                      <asp:Calendar ID="Calender1" runat="server"></asp:Calendar>
                      <br />
                      <asp:Button  CommandArgument="0" CommandName="SwitchViewByIndex" ID="btnfirst"   runat="server" Text = "Go To Next" />
                      <asp:Button CommandName="PrevView" ID="btnprevious" runat="server" Text = "Go To Previous View" />
                   </asp:View> 
                   
                </asp:MultiView>
             </div>
             
          </form>
       </body>
    </html>
    

    Observe the following:

    The MultiView.ActiveViewIndex determines which view will be shown. This is the only view rendered on the page. The default value for the ActiveViewIndex is -1, when no view is shown. Since the ActiveViewIndex is defined as 2 in the example, it shows the third view, when executed.

    MultiView
  • PANEL CONTROL ↓

    The Panel control works as a container for other controls on the page. It controls the appearance and visibility of the controls it contains. It also allows generating controls programmatically.

    The basic syntax of panel control is as follows:

    <asp:Panel ID= "Panel1"  runat = "server">
    </asp:Panel>
    

    The Panel control is derived from the WebControl class. Hence it inherits all the properties, methods and events of the same. It does not have any method or event of its own. However it has the following properties of its own:

    Properties Description
    BackImageUrl URL of the background image of the panel.
    DefaultButton Gets or sets the identifier for the default button that is contained in the Panel control.
    Direction Text direction in the panel.
    GroupingText Allows grouping of text as a field.
    HorizontalAlign Horizontal alignment of the content in the panel.
    ScrollBars Specifies visibility and location of scrollbars within the panel.
    Wrap Allows text wrapping.

    Working with the Panel Control

    Let us start with a simple scrollable panel of specific height and width and a border style. The ScrollBars property is set to both the scrollbars, hence both the scrollbars are rendered.

    The source file has the following code for the panel tag:

    <asp:Panel ID="Panel1" runat="server" BorderColor="#990000" BorderStyle="Solid" 
       Borderstyle="width:1px" Height="116px" ScrollBars="Both" style="width:278px">
       
       This is a scrollable panel.
       <br />
       <br />
    
       <asp:Button ID="btnpanel" runat="server" Text="Button" style="width:82px" />
    </asp:Panel>
    

    The panel is rendered as follows:

    Panel

    Example

    The following example demonstrates dynamic content generation. The user provides the number of label controls and textboxes to be generated on the panel. The controls are generated programmatically.

    Change the properties of the panel using the properties window. When you select a control on the design view, the properties window displays the properties of that particular control and allows you to make changes without typing.

    Panel2

    The source file for the example is as follows:

    <form id="form1" runat="server">
       <div>
          <asp:Panel ID="pnldynamic" runat="server" BorderColor="#990000" 
             BorderStyle="Solid" Borderstyle="width:1px" Height="150px"  ScrollBars="Auto" style="width:60%" BackColor="#CCCCFF"  Font-Names="Courier" HorizontalAlign="Center">
         
             This panel shows dynamic control generation:
             <br />
             <br />
          </asp:Panel>
       </div>
    
       <table style="width: 51%;">
          <tr>
             <td class="style2">No of Labels:</td>
             <td class="style1">
                <asp:DropDownList ID="ddllabels" runat="server">
                   <asp:ListItem>0</asp:ListItem>
                   <asp:ListItem>1</asp:ListItem>
                   <asp:ListItem>2</asp:ListItem>
                   <asp:ListItem>3</asp:ListItem>
                   <asp:ListItem>4</asp:ListItem>
                </asp:DropDownList>
             </td>
          </tr>
    
          <tr>
             <td class="style2"> </td>
             <td class="style1"> </td>
          </tr>
    
          <tr>
             <td class="style2">No of Text Boxes :</td>
             <td class="style1">
                <asp:DropDownList ID="ddltextbox" runat="server">
                   <asp:ListItem>0</asp:ListItem>
                   <asp:ListItem Value="1"></asp:ListItem>
                   <asp:ListItem>2</asp:ListItem>
                   <asp:ListItem>3</asp:ListItem>
                   <asp:ListItem Value="4"></asp:ListItem>
                </asp:DropDownList>
             </td>
          </tr>
    
          <tr>
             <td class="style2"> </td>
             <td class="style1"> </td>
          </tr>
    
          <tr>
             <td class="style2">
                <asp:CheckBox ID="chkvisible" runat="server" 
                   Text="Make the Panel Visible" />
             </td>
    
             <td class="style1">
                <asp:Button ID="btnrefresh" runat="server" Text="Refresh Panel" 
                   style="width:129px" />
             </td>
          </tr>
       </table>
    </form>
    

    The code behind the Page_Load event is responsible for generating the controls dynamically:

    public partial class _Default : System.Web.UI.Page
    {
       protected void Page_Load(object sender, EventArgs e)
       {
          //make the panel visible
          pnldynamic.Visible = chkvisible.Checked;
    
          //generating the lable controls:
          int n = Int32.Parse(ddllabels.SelectedItem.Value);
          for (int i = 1; i <= n; i++)
          {
             Label lbl = new Label();
             lbl.Text = "Label" + (i).ToString();
             pnldynamic.Controls.Add(lbl);
             pnldynamic.Controls.Add(new LiteralControl("<br />"));
          }
          
          //generating the text box controls:
    
          int m = Int32.Parse(ddltextbox.SelectedItem.Value);
          for (int i = 1; i <= m; i++)
          {
             TextBox txt = new TextBox();
             txt.Text = "Text Box" + (i).ToString();
             pnldynamic.Controls.Add(txt);
             pnldynamic.Controls.Add(new LiteralControl("<br />"));
          }
       }
    }
    

    When executed, the panel is rendered as:

    Panel3
  • AJAX ↓

    AJAX stands for Asynchronous JavaScript and XML. This is a cross platform technology which speeds up response time. The AJAX server controls add script to the page which is executed and processed by the browser.

    However like other ASP.NET server controls, these AJAX server controls also can have methods and event handlers associated with them, which are processed on the server side.

    The control toolbox in the Visual Studio IDE contains a group of controls called the 'AJAX Extensions'

    AJAX Extensions

    The ScriptManager Control

    The ScriptManager control is the most important control and must be present on the page for other controls to work.

    It has the basic syntax:

    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    

    If you create an 'Ajax Enabled site' or add an 'AJAX Web Form' from the 'Add Item' dialog box, the web form automatically contains the script manager control. The ScriptManager control takes care of the client-side script for all the server side controls.

    The UpdatePanel Control

    The UpdatePanel control is a container control and derives from the Control class. It acts as a container for the child controls within it and does not have its own interface. When a control inside it triggers a post back, the UpdatePanel intervenes to initiate the post asynchronously and update just that portion of the page.

    For example, if a button control is inside the update panel and it is clicked, only the controls within the update panel will be affected, the controls on the other parts of the page will not be affected. This is called the partial post back or the asynchronous post back.

    Example

    Add an AJAX web form in your application. It contains the script manager control by default. Insert an update panel. Place a button control along with a label control within the update panel control. Place another set of button and label outside the panel.

    The design view looks as follows:

    ScriptManager

    The source file is as follows:

    <form id="form1" runat="server">
       <div>
          <asp:ScriptManager ID="ScriptManager1" runat="server" />
       </div>
       
       <asp:UpdatePanel ID="UpdatePanel1" runat="server">
          <ContentTemplate>
             <asp:Button ID="btnpartial" runat="server" onclick="btnpartial_Click" Text="Partial PostBack"/>
             <br />
             <br />
             <asp:Label ID="lblpartial" runat="server"></asp:Label>
          </ContentTemplate>
       </asp:UpdatePanel>
       
       <p> </p>
       <p>Outside the Update Panel</p>
       <p>
          <asp:Button ID="btntotal" runat="server" onclick="btntotal_Click" Text="Total PostBack" />
       </p>
       
       <asp:Label ID="lbltotal" runat="server"></asp:Label>
    </form>
    

    Both the button controls have same code for the event handler:

    string time = DateTime.Now.ToLongTimeString();
    lblpartial.Text = "Showing time from panel" + time;
    lbltotal.Text = "Showing time from outside" + time;
    

    Observe that when the page is executed, if the total post back button is clicked, it updates time in both the labels but if the partial post back button is clicked, it only updates the label within the update panel.

    update panel

    A page can contain multiple update panels with each panel containing other controls like a grid and displaying different part of data.

    When a total post back occurs, the update panel content is updated by default. This default mode could be changed by changing the UpdateMode property of the control. Let us look at other properties of the update panel.

    Properties of the UpdatePanel Control

    The following table shows the properties of the update panel control:

    Properties Description
    ChildrenAsTriggers This property indicates whether the post backs are coming from the child controls, which cause the update panel to refresh.
    ContentTemplate It is the content template and defines what appears in the update panel when it is rendered.
    ContentTemplateContainer Retrieves the dynamically created template container object and used for adding child controls programmatically.
    IsInPartialRendering Indicates whether the panel is being updated as part of the partial post back.
    RenderMode Shows the render modes. The available modes are Block and Inline.
    UpdateMode Gets or sets the rendering mode by determining some conditions.
    Triggers Defines the collection trigger objects each corresponding to an event causing the panel to refresh automatically.

    Methods of the UpdatePanel Control

    The following table shows the methods of the update panel control:

    Methods Description
    CreateContentTemplateContainer Creates a Control object that acts as a container for child controls that define the UpdatePanel control's content.
    CreateControlCollection Returns the collection of all controls that are contained in the UpdatePanel control.
    Initialize Initializes the UpdatePanel control trigger collection if partial-page rendering is enabled.
    Update Causes an update of the content of an UpdatePanel control.

    The behavior of the update panel depends upon the values of the UpdateMode property and ChildrenAsTriggers property.

    UpdateMode ChildrenAsTriggers Effect
    Always False Illegal parameters.
    Always True UpdatePanel refreshes if whole page refreshes or a child control on it posts back.
    Conditional False UpdatePanel refreshes if whole page refreshes or a triggering control outside it initiates a refresh.
    Conditional True UpdatePanel refreshes if whole page refreshes or a child control on it posts back or a triggering control outside it initiates a refresh.

    The UpdateProgress Control

    The UpdateProgress control provides a sort of feedback on the browser while one or more update panel controls are being updated. For example, while a user logs in or waits for server response while performing some database oriented job.

    It provides a visual acknowledgement like "Loading page...", indicating the work is in progress.

    The syntax for the UpdateProgress control is:

    <asp:UpdateProgress ID="UpdateProgress1" runat="server" DynamicLayout="true" AssociatedUpdatePanelID="UpdatePanel1" >
    
       <ProgressTemplate>
          Loading...
       </ProgressTemplate>
       
    </asp:UpdateProgress>
    

    The above snippet shows a simple message within the ProgressTemplate tag. However, it could be an image or other relevant controls. The UpdateProgress control displays for every asynchronous postback unless it is assigned to a single update panel using the AssociatedUpdatePanelID property.

    Properties of the UpdateProgress Control

    The following table shows the properties of the update progress control:

    Properties Description
    AssociatedUpdatePanelID Gets and sets the ID of the update panel with which this control is associated.
    Attributes Gets or sets the cascading style sheet (CSS) attributes of the UpdateProgress control.
    DisplayAfter Gets and sets the time in milliseconds after which the progress template is displayed. The default is 500.
    DynamicLayout Indicates whether the progress template is dynamically rendered.
    ProgressTemplate Indicates the template displayed during an asynchronous post back which takes more time than the DisplayAfter time.

    Methods of the UpdateProgress Control

    The following table shows the methods of the update progress control:

    Methods Description
    GetScriptDescriptors Returns a list of components, behaviors, and client controls that are required for the UpdateProgress control's client functionality.
    GetScriptReferences Returns a list of client script library dependencies for the UpdateProgress control.

    The Timer Control

    The timer control is used to initiate the post back automatically. This could be done in two ways:

    (1) Setting the Triggers property of the UpdatePanel control:

    <Triggers> 
       <asp:AsyncPostBackTrigger ControlID="btnpanel2" EventName="Click" />
    </Triggers>
    

    (2) Placing a timer control directly inside the UpdatePanel to act as a child control trigger. A single timer can be the trigger for multiple UpdatePanels.

    <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">
    
       <ContentTemplate>
          <asp:Timer ID="Timer1" runat="server" Interval="1000">
             </asp:Timer>
             
          <asp:Label ID="Label1" runat="server" Height="101px" style="width:304px" >
             </asp:Label>
       </ContentTemplate>
       
    </asp:UpdatePanel>
    

  • DATA SOURCES ↓

    A data source control interacts with the data-bound controls and hides the complex data binding processes. These are the tools that provide data to the data bound controls and support execution of operations like insertions, deletions, sorting, and updates.

    Each data source control wraps a particular data provider-relational databases, XML documents, or custom classes and helps in:

    • Managing connection
    • Selecting data
    • Managing presentation aspects like paging, caching, etc.
    • Manipulating data

    There are many data source controls available in ASP.NET for accessing data from SQL Server, from ODBC or OLE DB servers, from XML files, and from business objects.

    Based on type of data, these controls could be divided into two categories:

    • Hierarchical data source controls
    • Table-based data source controls

    The data source controls used for hierarchical data are:

    • XMLDataSource - It allows binding to XML files and strings with or without schema information.

    • SiteMapDataSource - It allows binding to a provider that supplies site map information.

    The data source controls used for tabular data are:

    Data source controls Description
    SqlDataSource It represents a connection to an ADO.NET data provider that returns SQL data, including data sources accessible via OLEDB and QDBC.
    ObjectDataSource It allows binding to a custom .Net business object that returns data.
    LinqdataSource It allows binding to the results of a Linq-to-SQL query (supported by ASP.NET 3.5 only).
    AccessDataSource It represents connection to a Microsoft Access database.

    Data Source Views

    Data source views are objects of the DataSourceView class. Which represent a customized view of data for different data operations such as sorting, filtering, etc.

    The DataSourceView class serves as the base class for all data source view classes, which define the capabilities of data source controls.

    The following table provides the properties of the DataSourceView class:

    Properties Description
    CanDelete Indicates whether deletion is allowed on the underlying data source.
    CanInsert Indicates whether insertion is allowed on the underlying data source.
    CanPage Indicates whether paging is allowed on the underlying data source.
    CanRetrieveTotalRowCount Indicates whether total row count information is available.
    CanSort Indicates whether the data could be sorted.
    CanUpdate Indicates whether updates are allowed on the underlying data source.
    Events Gets a list of event-handler delegates for the data source view.
    Name Name of the view.

    The following table provides the methods of the DataSourceView class:

    Methods Description
    CanExecute Determines whether the specified command can be executed.
    ExecuteCommand Executes the specific command.
    ExecuteDelete Performs a delete operation on the list of data that the DataSourceView object represents.
    ExecuteInsert Performs an insert operation on the list of data that the DataSourceView object represents.
    ExecuteSelect Gets a list of data from the underlying data storage.
    ExecuteUpdate Performs an update operation on the list of data that the DataSourceView object represents.
    Delete Performs a delete operation on the data associated with the view.
    Insert Performs an insert operation on the data associated with the view.
    Select Returns the queried data.
    Update Performs an update operation on the data associated with the view.
    OnDataSourceViewChanged Raises the DataSourceViewChanged event.
    RaiseUnsupportedCapabilitiesError Called by the RaiseUnsupportedCapabilitiesError method to compare the capabilities requested for an ExecuteSelect operation against those that the view supports.

    The SqlDataSource Control

    The SqlDataSource control represents a connection to a relational database such as SQL Server or Oracle database, or data accessible through OLEDB or Open Database Connectivity (ODBC). Connection to data is made through two important properties ConnectionString and ProviderName.

    The following code snippet provides the basic syntax of the control:

    <asp:SqlDataSource runat="server" ID="MySqlSource"
       ProviderName='<%$ ConnectionStrings:LocalNWind.ProviderName  %>'
       ConnectionString='<%$ ConnectionStrings:LocalNWind %>'
       SelectionCommand= "SELECT * FROM EMPLOYEES" />
    
    <asp:GridView ID="GridView1" runat="server" DataSourceID="MySqlSource" />
    

    Configuring various data operations on the underlying data depends upon the various properties (property groups) of the data source control.

    The following table provides the related sets of properties of the SqlDataSource control, which provides the programming interface of the control:

    Property Group Description

    DeleteCommand,

    DeleteParameters,

    DeleteCommandType

    Gets or sets the SQL statement, parameters, and type for deleting rows in the underlying data.

    FilterExpression,

    FilterParameters

    Gets or sets the data filtering string and parameters.

    InsertCommand,

    InsertParameters,

    InsertCommandType

    Gets or sets the SQL statement, parameters, and type for inserting rows in the underlying database.

    SelectCommand,

    SelectParameters,

    SelectCommandType

    Gets or sets the SQL statement, parameters, and type for retrieving rows from the underlying database.
    SortParameterName Gets or sets the name of an input parameter that the command's stored procedure will use to sort data.

    UpdateCommand,

    UpdateParameters,

    UpdateCommandType

    Gets or sets the SQL statement, parameters, and type for updating rows in the underlying data store.

    The following code snippet shows a data source control enabled for data manipulation:

    <asp:SqlDataSource runat="server" ID= "MySqlSource"
       ProviderName='<%$ ConnectionStrings:LocalNWind.ProviderName  %>'
       ConnectionString=' <%$ ConnectionStrings:LocalNWind %>'
       SelectCommand= "SELECT * FROM EMPLOYEES"
       UpdateCommand= "UPDATE EMPLOYEES SET LASTNAME=@lame"
       DeleteCommand= "DELETE FROM EMPLOYEES WHERE EMPLOYEEID=@eid"
       FilterExpression= "EMPLOYEEID > 10">
       .....
       .....
    </asp:SqlDataSource>
    

    The ObjectDataSource Control

    The ObjectDataSource Control enables user-defined classes to associate the output of their methods to data bound controls. The programming interface of this class is almost same as the SqlDataSource control.

    Following are two important aspects of binding business objects:

    • The bindable class should have a default constructor, it should be stateless, and have methods that can be mapped to select, update, insert, and delete semantics.

    • The object must update one item at a time, batch operations are not supported.

    Let us go directly to an example to work with this control. The student class is the class to be used with an object data source. This class has three properties: a student id, name, and city. It has a default constructor and a GetStudents method for retrieving data.

    The student class:

    public class Student
    {
       public int StudentID { get; set; }
       public string Name { get; set; }
       public string City { get; set; }
       
       public Student()
       { }
       
       public DataSet GetStudents()
       {
          DataSet ds = new DataSet();
          DataTable dt = new DataTable("Students");
          
          dt.Columns.Add("StudentID", typeof(System.Int32));
          dt.Columns.Add("StudentName", typeof(System.String));
          dt.Columns.Add("StudentCity", typeof(System.String));
          dt.Rows.Add(new object[] { 1, "M. H. Kabir", "Calcutta" });
          dt.Rows.Add(new object[] { 2, "Ayan J. Sarkar", "Calcutta" });
          ds.Tables.Add(dt);
          
          return ds;
       }
    }
    

    Take the following steps to bind the object with an object data source and retrieve data:

    • Create a new web site.

    • Add a class (Students.cs) to it by right clicking the project from the Solution Explorer, adding a class template, and placing the above code in it.

    • Build the solution so that the application can use the reference to the class.

    • Place an object data source control in the web form.

    • Configure the data source by selecting the object.

    selecting the object
    • Select a data method(s) for different operations on data. In this example, there is only one method.

    Select a data method
    • Place a data bound control such as grid view on the page and select the object data source as its underlying data source.

    Data Bound Control
    • At this stage, the design view should look like the following:

    Object Data Source
    • Run the project, it retrieves the hard coded tuples from the students class.

    Object Data Result

    The AccessDataSource Control

    The AccessDataSource control represents a connection to an Access database. It is based on the SqlDataSource control and provides simpler programming interface. The following code snippet provides the basic syntax for the data source:

    <asp:AccessDataSource ID="AccessDataSource1 runat="server" 
       DataFile="~/App_Data/ASPDotNetStepByStep.mdb" SelectCommand="SELECT * FROM  [DotNetReferences]">
    </asp:AccessDataSource>
    

    The AccessDataSource control opens the database in read-only mode. However, it can also be used for performing insert, update, or delete operations. This is done using the ADO.NET commands and parameter collection.

    Updates are problematic for Access databases from within an ASP.NET application because an Access database is a plain file and the default account of the ASP.NET application might not have the permission to write to the database file.


  • DATA BINDING ↓

    Every ASP.NET web form control inherits the DataBind method from its parent Control class, which gives it an inherent capability to bind data to at least one of its properties. This is known as simple data binding or inline data binding.

    Simple data binding involves attaching any collection (item collection) which implements the IEnumerable interface, or the DataSet and DataTable classes to the DataSource property of the control.

    On the other hand, some controls can bind records, lists, or columns of data into their structure through a DataSource control. These controls derive from the BaseDataBoundControl class. This is called declarative data binding.

    The data source controls help the data-bound controls implement functionalities such as, sorting, paging, and editing data collections.

    The BaseDataBoundControl is an abstract class, which is inherited by two more abstract classes:

    • DataBoundControl
    • HierarchicalDataBoundControl

    The abstract class DataBoundControl is again inherited by two more abstract classes:

    • ListControl
    • CompositeDataBoundControl

    The controls capable of simple data binding are derived from the ListControl abstract class and these controls are:

    • BulletedList
    • CheckBoxList
    • DropDownList
    • ListBox
    • RadioButtonList

    The controls capable of declarative data binding (a more complex data binding) are derived from the abstract class CompositeDataBoundControl. These controls are:

    • DetailsView
    • FormView
    • GridView
    • RecordList

    Simple Data Binding

    Simple data binding involves the read-only selection lists. These controls can bind to an array list or fields from a database. Selection lists takes two values from the database or the data source; one value is displayed by the list and the other is considered as the value corresponding to the display.

    Let us take up a small example to understand the concept. Create a web site with a bulleted list and a SqlDataSource control on it. Configure the data source control to retrieve two values from your database (we use the same DotNetReferences table as in the previous chapter).

    Choosing a data source for the bulleted list control involves:

    • Selecting the data source control
    • Selecting a field to display, which is called the data field
    • Selecting a field for the value
    Choose Data Source

    When the application is executed, check that the entire title column is bound to the bulleted list and displayed.

    Choose Data Source2

    Declarative Data Binding

    We have already used declarative data binding in the previous tutorial using GridView control. The other composite data bound controls capable of displaying and manipulating data in a tabular manner are the DetailsView, FormView, and RecordList control.

    In the next tutorial, we will look into the technology for handling database, i.e, ADO.NET.

    However, the data binding involves the following objects:

    • A dataset that stores the data retrieved from the database.

    • The data provider, which retrieves data from the database by using a command over a connection.

    • The data adapter that issues the select statement stored in the command object; it is also capable of update the data in a database by issuing Insert, Delete, and Update statements.

    Relation between the data binding objects:

    Declarative Data Binding

    Example

    Let us take the following steps:

    Step (1) : Create a new website. Add a class named booklist by right clicking on the solution name in the Solution Explorer and choosing the item 'Class' from the 'Add Item' dialog box. Name it as booklist.cs.

    using System;
    using System.Data;
    using System.Configuration;
    using System.Linq;
    
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    
    using System.Xml.Linq;
    
    namespace databinding
    {
       public class booklist
       {
          protected String bookname;
          protected String authorname;
          public booklist(String bname, String aname)
          {
             this.bookname = bname;
             this.authorname = aname;
    
          }
          
          public String Book
          {
             get
             {
                return this.bookname;
             }
             set
             {
                this.bookname = value;
             }
          }
          
          public String Author
          {
             get
             {
                return this.authorname;
             }
             set
             {
                this.authorname = value;
             }
          }
       }
    }
    

    Step (2) : Add four list controls on the page a list box control, a radio button list, a check box list, and a drop down list and four labels along with these list controls. The page should look like this in design view:

    List box control

    The source file should look as the following:

    <form id="form1" runat="server">
       <div>
       
          <table style="width: 559px">
             <tr>
                <td style="width: 228px; height: 157px;">
                   <asp:ListBox ID="ListBox1" runat="server" AutoPostBack="True" 
                      OnSelectedIndexChanged="ListBox1_SelectedIndexChanged">
                   </asp:ListBox>
                </td>
    
                <td style="height: 157px">
                   <asp:DropDownList ID="DropDownList1" runat="server" 
                      AutoPostBack="True" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
                   </asp:DropDownList>
                </td>             
             </tr>
    
             <tr>
                <td style="width: 228px; height: 40px;">
                   <asp:Label ID="lbllistbox" runat="server"></asp:Label>
                </td>
    
                <td style="height: 40px">
                   <asp:Label ID="lbldrpdown" runat="server">
                   </asp:Label>
                </td>
             </tr>
    
             <tr>
                <td style="width: 228px; height: 21px">
                </td>
    
                <td style="height: 21px">
                </td>              
             </tr>
    
             <tr>
                <td style="width: 228px; height: 21px">
                   <asp:RadioButtonList ID="RadioButtonList1" runat="server"
                      AutoPostBack="True"  OnSelectedIndexChanged="RadioButtonList1_SelectedIndexChanged">
                   </asp:RadioButtonList>
                </td>
    
                <td style="height: 21px">
                   <asp:CheckBoxList ID="CheckBoxList1" runat="server" 
                      AutoPostBack="True" OnSelectedIndexChanged="CheckBoxList1_SelectedIndexChanged">
                   </asp:CheckBoxList>
                </td>                
             </tr>
    
             <tr>
                <td style="width: 228px; height: 21px">
                   <asp:Label ID="lblrdlist" runat="server">
                   </asp:Label>
                </td>
    
                <td style="height: 21px">
                   <asp:Label ID="lblchklist" runat="server">
                   </asp:Label>
                </td>           
             </tr>
          </table>      
          
       </div>
    </form>
    

    Step (3) : Finally, write the following code behind routines of the application:

    public partial class _Default : System.Web.UI.Page
    {
       protected void Page_Load(object sender, EventArgs e)
       {
          IList bklist = createbooklist();
          
          if (!this.IsPostBack)
          {
             this.ListBox1.DataSource = bklist;
             this.ListBox1.DataTextField = "Book";
             this.ListBox1.DataValueField = "Author";
             
             this.DropDownList1.DataSource = bklist;
             this.DropDownList1.DataTextField = "Book";
             this.DropDownList1.DataValueField = "Author";
             
             this.RadioButtonList1.DataSource = bklist;
             this.RadioButtonList1.DataTextField = "Book";
             this.RadioButtonList1.DataValueField = "Author";
             
             this.CheckBoxList1.DataSource = bklist;
             this.CheckBoxList1.DataTextField = "Book";
             this.CheckBoxList1.DataValueField = "Author";
             
             this.DataBind();
          }
       }
       
       protected IList createbooklist()
       {
          ArrayList allbooks = new ArrayList();
          booklist bl;
          
          bl = new booklist("UNIX CONCEPTS", "SUMITABHA DAS");
          allbooks.Add(bl);
          
          bl = new booklist("PROGRAMMING IN C", "RICHI KERNIGHAN");
          allbooks.Add(bl);
          
          bl = new booklist("DATA STRUCTURE", "TANENBAUM");
          allbooks.Add(bl);
          
          bl = new booklist("NETWORKING CONCEPTS", "FOROUZAN");
          allbooks.Add(bl);
          
          bl = new booklist("PROGRAMMING IN C++", "B. STROUSTROUP");
          allbooks.Add(bl);
          
          bl = new booklist("ADVANCED JAVA", "SUMITABHA DAS");
          allbooks.Add(bl);
          
          return allbooks;
       }
       
       protected void ListBox1_SelectedIndexChanged(object sender, EventArgs e)
       {
          this.lbllistbox.Text = this.ListBox1.SelectedValue;
       }
       
       protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
       {
          this.lbldrpdown.Text = this.DropDownList1.SelectedValue;
       }
       
       protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e)
       {
          this.lblrdlist.Text = this.RadioButtonList1.SelectedValue;
       }
       
       protected void CheckBoxList1_SelectedIndexChanged(object sender, EventArgs e)
       {
          this.lblchklist.Text = this.CheckBoxList1.SelectedValue;
       }
    }
    

    Observe the following:

    • The booklist class has two properties: bookname and authorname.

    • The createbooklist method is a user defined method that creates an array of booklist objects named allbooks.

    • The Page_Load event handler ensures that a list of books is created. The list is of IList type, which implements the IEnumerable interface and capable of being bound to the list controls. The page load event handler binds the IList object 'bklist' with the list controls. The bookname property is to be displayed and the authorname property is considered as the value.

    • When the page is run, if the user selects a book, its name is selected and displayed by the list controls whereas the corresponding labels display the author name, which is the corresponding value for the selected index of the list control.

    Data Binding Results
  • WEB SERVICES ↓

    p>A web service is a web-based functionality accessed using the protocols of the web to be used by the web applications. There are three aspects of web service development:

    • Creating the web service
    • Creating a proxy
    • Consuming the web service

    Creating a Web Service

    A web service is a web application which is basically a class consisting of methods that could be used by other applications. It also follows a code-behind architecture such as the ASP.NET web pages, although it does not have a user interface.

    To understand the concept let us create a web service to provide stock price information. The clients can query about the name and price of a stock based on the stock symbol. To keep this example simple, the values are hardcoded in a two-dimensional array. This web service has three methods:

    • A default HelloWorld method
    • A GetName Method
    • A GetPrice Method

    Take the following steps to create the web service:

    Step (1) : Select File -> New -> Web Site in Visual Studio, and then select ASP.NET Web Service.

    Step (2) : A web service file called Service.asmx and its code behind file, Service.cs is created in the App_Code directory of the project.

    Step (3) : Change the names of the files to StockService.asmx and StockService.cs.

    Step (4) : The .asmx file has simply a WebService directive on it:

    <%@ WebService Language="C#" CodeBehind="~/App_Code/StockService.cs" Class="StockService" %>
    

    Step (5) : Open the StockService.cs file, the code generated in it is the basic Hello World service. The default web service code behind file looks like the following:

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Data;
    using System.Linq;
    
    using System.Web;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    
    using System.Xml.Linq;
    
    namespace StockService
    {
       // <summary>
       // Summary description for Service1
       // <summary>
       
       [WebService(Namespace = "http://tempuri.org/")]
       [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
       [ToolboxItem(false)]
       
       // To allow this Web Service to be called from script, 
       // using ASP.NET AJAX, uncomment the following line. 
       // [System.Web.Script.Services.ScriptService]
       
       public class Service1 : System.Web.Services.WebService
       {
          [WebMethod]
          
          public string HelloWorld()
          {
             return "Hello World";
          }
       }
    }
    

    Step (6) : Change the code behind file to add the two dimensional array of strings for stock symbol, name and price and two web methods for getting the stock information.

    using System;
    using System.Linq;
    
    using System.Web;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    
    using System.Xml.Linq;
    
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    
    // To allow this Web Service to be called from script, 
    // using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    
    public class StockService : System.Web.Services.WebService
    {
       public StockService () {
          //Uncomment the following if using designed components 
          //InitializeComponent(); 
       }
       
       string[,] stocks =
       {
          {"RELIND", "Reliance Industries", "1060.15"},
          {"ICICI", "ICICI Bank", "911.55"},
          {"JSW", "JSW Steel", "1201.25"},
          {"WIPRO", "Wipro Limited", "1194.65"},
          {"SATYAM", "Satyam Computers", "91.10"}
       };
    
       [WebMethod]
       public string HelloWorld() {
          return "Hello World";
       }
       
       [WebMethod]
       public double GetPrice(string symbol)
       { 
          //it takes the symbol as parameter and returns price
          for (int i = 0; i < stocks.GetLength(0); i++)
          {
             if (String.Compare(symbol, stocks[i, 0], true) == 0)
             return Convert.ToDouble(stocks[i, 2]);
          }
          
          return 0;
       }
       
       [WebMethod]
       public string GetName(string symbol)
       {
          // It takes the symbol as parameter and 
          // returns name of the stock
          for (int i = 0; i < stocks.GetLength(0); i++)
          {
             if (String.Compare(symbol, stocks[i, 0], true) == 0)
             return stocks[i, 1];
          }
          
          return "Stock Not Found";
       }
    }
    

    Step (7) : Running the web service application gives a web service test page, which allows testing the service methods.

    Stock Service

    Step (8) : Click on a method name, and check whether it runs properly.

    Get Name

    Step (9) : For testing the GetName method, provide one of the stock symbols, which are hard coded, it returns the name of the stock

    the name of the stock

    Consuming the Web Service

    For using the web service, create a web site under the same solution. This could be done by right clicking on the Solution name in the Solution Explorer. The web page calling the web service should have a label control to display the returned results and two button controls one for post back and another for calling the service.

    The content file for the web application is as follows:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="wsclient._Default" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
    
       <head runat="server">
          <title>
             Untitled Page
          </title>
       </head>
       
       <body>
       
          <form id="form1" runat="server">
             <div>
             
                <h3>Using the Stock Service</h3>
                
                <br /> <br />
                
                <asp:Label ID="lblmessage" runat="server"></asp:Label>
                
                <br /> <br />
                
                <asp:Button ID="btnpostback" runat="server" onclick="Button1_Click" Text="Post Back" style="width:132px" />
                   
                <asp:Button ID="btnservice" runat="server" onclick="btnservice_Click"  Text="Get Stock" style="width:99px" />
                
             </div>
          </form>
          
       </body>
    </html>
    

    The code behind file for the web application is as follows:

    using System;
    using System.Collections;
    using System.Configuration;
    using System.Data;
    using System.Linq;
    
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    
    using System.Xml.Linq;
    
    //this is the proxy
    using localhost;
    
    namespace wsclient
    {
       public partial class _Default : System.Web.UI.Page
       {
          protected void Page_Load(object sender, EventArgs e)
          {
             if (!IsPostBack)
             {
                lblmessage.Text = "First Loading Time: " +  DateTime.Now.ToLongTimeString
             }
             else
             {
                lblmessage.Text = "PostBack at: " + DateTime.Now.ToLongTimeString();
             }
          }
          
          protected void btnservice_Click(object sender, EventArgs e)
          {
             StockService proxy = new StockService();
             lblmessage.Text = String.Format("Current SATYAM Price:{0}",
             proxy.GetPrice("SATYAM").ToString());
          }
       }
    }
    

    Creating the Proxy

    A proxy is a stand-in for the web service codes. Before using the web service, a proxy must be created. The proxy is registered with the client application. Then the client application makes the calls to the web service as it were using a local method.

    The proxy takes the calls, wraps it in proper format and sends it as a SOAP request to the server. SOAP stands for Simple Object Access Protocol. This protocol is used for exchanging web service data.

    When the server returns the SOAP package to the client, the proxy decodes everything and presents it to the client application.

    Before calling the web service using the btnservice_Click, a web reference should be added to the application. This creates a proxy class transparently, which is used by the btnservice_Click event.

    protected void btnservice_Click(object sender, EventArgs e)
    {
       StockService proxy = new StockService();
       lblmessage.Text = String.Format("Current SATYAM Price: {0}", 
       proxy.GetPrice("SATYAM").ToString());
    }
    

    Take the following steps for creating the proxy:

    Step (1) : Right click on the web application entry in the Solution Explorer and click on 'Add Web Reference'.

    Add Web Reference

    Step (2) : Select 'Web Services in this solution'. It returns the StockService reference.

    Select Web Services

    Step (3) : Clicking on the service opens the test web page. By default the proxy created is called 'localhost', you can rename it. Click on 'Add Reference' to add the proxy to the client application.

    Stock Service 2

    Include the proxy in the code behind file by adding:

     using localhost;
    

  • MULTI THREADING ↓

    A thread is defined as the execution path of a program. Each thread defines a unique flow of control. If your application involves complicated and time consuming operations such as database access or some intense I/O operations, then it is often helpful to set different execution paths or threads, with each thread performing a particular job.

    Threads are lightweight processes. One common example of use of thread is implementation of concurrent programming by modern operating systems. Use of threads saves wastage of CPU cycle and increases efficiency of an application.

    So far we compiled programs where a single thread runs as a single process which is the running instance of the application. However, this way the application can perform one job at a time. To make it execute multiple tasks at a time, it could be divided into smaller threads.

    In .Net, the threading is handled through the 'System.Threading' namespace. Creating a variable of the System.Threading.Thread type allows you to create a new thread to start working with. It allows you to create and access individual threads in a program.

    Creating Thread

    A thread is created by creating a Thread object, giving its constructor a ThreadStart reference.

    ThreadStart childthreat = new ThreadStart(childthreadcall);
    

    Thread Life Cycle

    The life cycle of a thread starts when an object of the System.Threading.Thread class is created and ends when the thread is terminated or completes execution.

    Following are the various states in the life cycle of a thread:

    • The Unstarted State : It is the situation when the instance of the thread is created but the Start method is not called.

    • The Ready State : It is the situation when the thread is ready to execute and waiting CPU cycle.

    • The Not Runnable State : a thread is not runnable, when:

      • Sleep method has been called
      • Wait method has been called
      • Blocked by I/O operations
    • The Dead State : It is the situation when the thread has completed execution or has been aborted.

    Thread Priority

    The Priority property of the Thread class specifies the priority of one thread with respect to other. The .Net runtime selects the ready thread with the highest priority.

    The priorities could be categorized as:

    • Above normal
    • Below normal
    • Highest
    • Lowest
    • Normal

    Once a thread is created, its priority is set using the Priority property of the thread class.

    NewThread.Priority = ThreadPriority.Highest;
    

    Thread Properties & Methods

    The Thread class has the following important properties:

    Property Description
    CurrentContext Gets the current context in which the thread is executing.
    CurrentCulture Gets or sets the culture for the current thread.
    CurrentPrinciple Gets or sets the thread's current principal for role-based security.
    CurrentThread Gets the currently running thread.
    CurrentUICulture Gets or sets the current culture used by the Resource Manager to look up culture-specific resources at run time.
    ExecutionContext Gets an ExecutionContext object that contains information about the various contexts of the current thread.
    IsAlive Gets a value indicating the execution status of the current thread.
    IsBackground Gets or sets a value indicating whether or not a thread is a background thread.
    IsThreadPoolThread Gets a value indicating whether or not a thread belongs to the managed thread pool.
    ManagedThreadId Gets a unique identifier for the current managed thread.
    Name Gets or sets the name of the thread.
    Priority Gets or sets a value indicating the scheduling priority of a thread.
    ThreadState Gets a value containing the states of the current thread.

    The Thread class has the following important methods:

    Methods Description
    Abort Raises a ThreadAbortException in the thread on which it is invoked, to begin the process of terminating the thread. Calling this method usually terminates the thread.
    AllocateDataSlot Allocates an unnamed data slot on all the threads. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
    AllocateNamedDataSlot Allocates a named data slot on all threads. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
    BeginCriticalRegion Notifies a host that execution is about to enter a region of code in which the effects of a thread abort or unhandled exception might endanger other tasks in the application domain.
    BeginThreadAffinity Notifies a host that managed code is about to execute instructions that depend on the identity of the current physical operating system thread.
    EndCriticalRegion Notifies a host that execution is about to enter a region of code in which the effects of a thread abort or unhandled exception are limited to the current task.
    EndThreadAffinity Notifies a host that managed code has finished executing instructions that depend on the identity of the current physical operating system thread.
    FreeNamedDataSlot Eliminates the association between a name and a slot, for all threads in the process. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
    GetData Retrieves the value from the specified slot on the current thread, within the current thread's current domain. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
    GetDomain Returns the current domain in which the current thread is running.
    GetDomainID Returns a unique application domain identifier.
    GetNamedDataSlot Looks up a named data slot. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
    Interrupt Interrupts a thread that is in the WaitSleepJoin thread state.
    Join Blocks the calling thread until a thread terminates, while continuing to perform standard COM and SendMessage pumping. This method has different overloaded forms.
    MemoryBarrier Synchronizes memory access as follows: The processor executing the current thread cannot reorder instructions in such a way that memory accesses prior to the call to MemoryBarrier execute after memory accesses that follow the call to MemoryBarrier.
    ResetAbort Cancels an Abort requested for the current thread.
    SetData Sets the data in the specified slot on the currently running thread, for that thread's current domain. For better performance, use fields marked with the ThreadStaticAttribute attribute instead.
    Start Starts a thread.
    Sleep Makes the thread pause for a period of time.
    SpinWait Causes a thread to wait the number of times defined by the iterations parameter.
    VolatileRead() Reads the value of a field. The value is the latest written by any processor in a computer, regardless of the number of processors or the state of processor cache. This method has different overloaded forms.
    VolatileWrite() Writes a value to a field immediately, so that the value is visible to all processors in the computer. This method has different overloaded forms.
    Yield Causes the calling thread to yield execution to another thread that is ready to run on the current processor. The operating system selects the thread to yield to.

    Example

    The following example illustrates the uses of the Thread class. The page has a label control for displaying messages from the child thread. The messages from the main program are directly displayed using the Response.Write() method. Hence they appear on the top of the page.

    The source file is as follows:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="threaddemo._Default" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
    
       <head runat="server">
          <title>
             Untitled Page
          </title>
       </head>
       
       <body>
          <form id="form1" runat="server">
             <div>
                <h3>Thread Example</h3>
             </div>
             
             <asp:Label ID="lblmessage" runat="server" Text="Label">
             </asp:Label>
          </form>
       </body>
       
    </html>
    

    The code behind file is as follows:

    using System;
    using System.Collections;
    using System.Configuration;
    using System.Data;
    using System.Linq;
    
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    
    using System.Xml.Linq;
    using System.Threading;
    
    namespace threaddemo
    {
       public partial class _Default : System.Web.UI.Page
       {
          protected void Page_Load(object sender, EventArgs e)
          {
             ThreadStart childthreat = new ThreadStart(childthreadcall);
             Response.Write("Child Thread Started <br/>");
             Thread child = new Thread(childthreat);
             
             child.Start();
             
             Response.Write("Main sleeping  for 2 seconds.......<br/>");
             Thread.Sleep(2000);
             Response.Write("<br/>Main aborting child thread<br/>");
             
             child.Abort();
          }
          
          public void childthreadcall()
          {
             try{
                lblmessage.Text = "<br />Child thread started <br/>";
                lblmessage.Text += "Child Thread: Coiunting to 10";
                
                for( int i =0; i<10; i++)
                {
                   Thread.Sleep(500);
                   lblmessage.Text += "<br/> in Child thread </br>";
                }
                
                lblmessage.Text += "<br/> child thread finished";
                
             }catch(ThreadAbortException e){
             
                lblmessage.Text += "<br /> child thread - exception";
                
             }finally{
                lblmessage.Text += "<br /> child thread - unable to catch the  exception";
             }
          }
       }
    }
    

    Observe the following

    • When the page is loaded, a new thread is started with the reference of the method childthreadcall(). The main thread activities are displayed directly on the web page.

    • The second thread runs and sends messages to the label control.

    • The main thread sleeps for 2000 ms, during which the child thread executes.

    • The child thread runs till it is aborted by the main thread. It raises the ThreadAbortException and is terminated.

    • Control returns to the main thread.

    When executed the program sends the following messages:

    ASP.NET Thread
  • WEB & MACHINE CONFIGURATION ↓

    The behavior of an ASP.NET application is affected by different settings in the configuration files:

    • machine.config
    • web.config

    The machine.config file contains default and the machine-specific value for all supported settings. The machine settings are controlled by the system administrator and applications are generally not given access to this file.

    An application however, can override the default values by creating web.config files in its roots folder. The web.config file is a subset of the machine.config file.

    If the application contains child directories, it can define a web.config file for each folder. Scope of each configuration file is determined in a hierarchical top-down manner.

    Any web.config file can locally extend, restrict, or override any settings defined on the upper level.

    Visual Studio generates a default web.config file for each project. An application can execute without a web.config file, however, you cannot debug an application without a web.config file.

    The following figure shows the Solution Explorer for the sample example used in the web services tutorial:

    Solution Explorer-2

    In this application, there are two web.config files for two projects i.e., the web service and the web site calling the web service.

    The web.config file has the configuration element as the root node. Information inside this element is grouped into two main areas: the configuration section-handler declaration area, and the configuration section settings area.

    The following code snippet shows the basic syntax of a configuration file:

    <configuration>
    
       <!-- Configuration section-handler declaration area. -->
          <configSections>
             <section name="section1" type="section1Handler" />
             <section name="section2" type="section2Handler" />
          </configSections>
       <!-- Configuration section settings area. -->
       
       <section1>
          <s1Setting1 attribute1="attr1" />
       </section1>
       
       <section2>
          <s2Setting1 attribute1="attr1" />
       </section2>
       
       <system.web>
          <authentication mode="Windows" />
       </system.web>
       
    </configuration>
    

    Configuration Section Handler declarations

    The configuration section handlers are contained within the <configSections> tags. Each configuration handler specifies name of a configuration section, contained within the file, which provides some configuration data. It has the following basic syntax:

    <configSections>
       <section />
       <sectionGroup />
       <remove />
       <clear/>
    </configSections>
    

    It has the following elements:

    • Clear - It removes all references to inherited sections and section groups.

    • Remove - It removes a reference to an inherited section and section group.

    • Section - It defines an association between a configuration section handler and a configuration element.

    • Section group - It defines an association between a configuration section handler and a configuration section.

    Application Settings

    The application settings allow storing application-wide name-value pairs for read-only access. For example, you can define a custom application setting as:

    <configuration>
       <appSettings>
          <add key="Application Name" value="MyApplication" /> 
       </appSettings>
    </configuration>
    

    For example, you can also store the name of a book and its ISBN number:

    <configuration>
       <appSettings>
          <add key="appISBN" value="0-273-68726-3" />
          <add key="appBook" value="Corporate Finance" />
       </appSettings>
    </configuration>
    

    Connection Strings

    The connection strings show which database connection strings are available to the website. For example:

    <connectionStrings>
       <add name="ASPDotNetStepByStepConnectionString" 
          connectionString="Provider=Microsoft.Jet.OLEDB.4.0;
          Data Source=E:\\projects\datacaching\ /
          datacaching\App_Data\ASPDotNetStepByStep.mdb"
          providerName="System.Data.OleDb" />
          
       <add name="booksConnectionString" 
          connectionString="Provider=Microsoft.Jet.OLEDB.4.0;
          Data Source=C:\ \databinding\App_Data\books.mdb"
          providerName="System.Data.OleDb" />
    </connectionStrings>
    

    System.Web Element

    The system.web element specifies the root element for the ASP.NET configuration section and contains configuration elements that configure ASP.NET Web applications and control how the applications behave.

    It holds most of the configuration elements needed to be adjusted in common applications. The basic syntax for the element is as given:

    <system.web> 
       <anonymousIdentification> 
       <authentication> 
       <authorization> 
       <browserCaps> 
       <caching> 
       <clientTarget> 
       <compilation> 
       <customErrors> 
       <deployment> 
       <deviceFilters> 
       <globalization> 
       <healthMonitoring> 
       <hostingEnvironment> 
       <httpCookies> 
       <httpHandlers> 
       <httpModules> 
       <httpRuntime> 
       <identity> 
       <machineKey> 
       <membership> 
       <mobileControls> 
       <pages> 
       <processModel> 
       <profile> 
       <roleManager> 
       <securityPolicy> 
       <sessionPageState> 
       <sessionState> 
       <siteMap> 
       <trace> 
       <trust> 
       <urlMappings> 
       <webControls> 
       <webParts> 
       <webServices> 
       <xhtmlConformance> 
    </system.web>
    

    The following table provides brief description of some of common sub elements of the system.web element:

    AnonymousIdentification

    This is required to identify users who are not authenticated when authorization is required.

    Authentication

    It configures the authentication support. The basic syntax is as given:

    <authentication mode="[Windows|Forms|Passport|None]"> 
       <forms>...</forms>
       <passport/>
    </authentication>
    

    Authorization

    It configures the authorization support. The basic syntax is as given:

    <authorization> 
       <allow .../>
       <deny .../>
    </authorization>
    

    Caching

    It Configures the cache settings. The basic syntax is as given:

    <caching>
       <cache>...</cache>
       <outputCache>...</outputCache>
       <outputCacheSettings>...</outputCacheSettings>
       <sqlCacheDependency>...</sqlCacheDependency>
    </caching>
    

    CustomErrors

    It defines custom error messages. The basic syntax is as given:

    <customErrors defaultRedirect="url" mode="On|Off|RemoteOnly">
       <error. . ./>
    </customErrors>
    

    Deployment

    It defines configuration settings used for deployment. The basic syntax is as follows:

    <deployment retail="true|false" />
    

    HostingEnvironment

    It defines configuration settings for hosting environment. The basic syntax is as follows:

    <hostingEnvironment idleTimeout="HH:MM:SS" shadowCopyBinAssemblies="true|false" 
       shutdownTimeout="number" urlMetadataSlidingExpiration="HH:MM:SS" />
    

    Identity

    It configures the identity of the application. The basic syntax is as given:

    <identity impersonate="true|false" userName="domain\username"
       password="<secure password>"/>
    

    MachineKey

    It configures keys to use for encryption and decryption of Forms authentication cookie data.

    It also allows configuring a validation key that performs message authentication checks on view-state data and forms authentication tickets. The basic syntax is:

    <machineKey validationKey="AutoGenerate,IsolateApps" [String]
       decryptionKey="AutoGenerate,IsolateApps" [String]
       validation="HMACSHA256" [SHA1 | MD5 | 3DES | AES | HMACSHA256 | 
       HMACSHA384 | HMACSHA512 | alg:algorithm_name]
       decryption="Auto" [Auto | DES | 3DES | AES | alg:algorithm_name]
    />
    

    Membership

    This configures parameters of managing and authenticating user accounts. The basic syntax is:

    <membership defaultProvider="provider name"
       userIsOnlineTimeWindow="number of minutes" hashAlgorithmType="SHA1">
       <providers>...</providers>
    </membership>
    

    Pages

    It provides page-specific configurations. The basic syntax is:

    <pages asyncTimeout="number" autoEventWireup="[True|False]"
          buffer="[True|False]" clientIDMode="[AutoID|Predictable|Static]"
          compilationMode="[Always|Auto|Never]" 
          controlRenderingCompatibilityVersion="[3.5|4.0]"
          enableEventValidation="[True|False]"
          enableSessionState="[True|False|ReadOnly]"
          enableViewState="[True|False]"
          enableViewStateMac="[True|False]"
          maintainScrollPositionOnPostBack="[True|False]" 
          masterPageFile="file path" 
          maxPageStateFieldLength="number" 
          pageBaseType="typename, assembly"
          pageParserFilterType="string" 
          smartNavigation="[True|False]"
          styleSheetTheme="string"
          theme="string"
          userControlBaseType="typename"
          validateRequest="[True|False]"
          viewStateEncryptionMode="[Always|Auto|Never]" >
       
       <controls>...</controls>
       <namespaces>...</namespaces>
       <tagMapping>...</tagMapping>
       <ignoreDeviceFilters>...</ignoreDeviceFilters>
    </pages>
    

    Profile

    It configures user profile parameters. The basic syntax is:

    <profile enabled="true|false" inherits="fully qualified type reference"
       automaticSaveEnabled="true|false" defaultProvider="provider name">
       
       <properties>...</properties>
       <providers>...</providers>
       
    </profile>
    

    RoleManager

    It configures settings for user roles. The basic syntax is:

    <roleManager cacheRolesInCookie="true|false" cookieName="name"
       cookiePath="/" cookieProtection="All|Encryption|Validation|None"
       cookieRequireSSL="true|false " cookieSlidingExpiration="true|false "
       cookieTimeout="number of minutes" createPersistentCookie="true|false"
       defaultProvider="provider name" domain="cookie domain"> 
       enabled="true|false"
       maxCachedResults="maximum number of role names cached"
       
       <providers>...</providers>
    </roleManager>
    

    SecurityPolicy

    It configures the security policy. The basic syntax is:

    <securityPolicy>
       <trustLevel />
    </securityPolicy>
    

    UrlMappings

    It defines mappings to hide the original URL and provide a more user friendly URL. The basic syntax is:

    <urlMappings enabled="true|false">
       <add.../>
       <clear />
       <remove.../>
    </urlMappings>
    

    WebControls

    It provides the name of shared location for client scripts. The basic syntax is:

    <webControls clientScriptsLocation="String" />
    

    WebServices

    This configures the web services.


  • LOCALIZATION ↓

    Localization

    Introduction
    According to Wikipedia, "Localization is the process of adapting software for a specific region or language by adding locale-specific components and translating text", and that is exactly what we'll look into in the next couple of chapters. Offering your website in other languages than the default one can be a big job, but fortunately, ASP.NET makes the process a lot easier.

    There are quite a few concepts that you need to know about, right from the CultureInfo class to the concepts of local and global resources, as well as implicit and explicit localization. In the next couple of chapters, we will look into all of that, but first, let's see it in action, in our very own "Hello, localized world!" example.


    Hello, localized world!
    With the knowledge acquired from the previous chapters, let's try actually localizing some text, to see that it works. You should create a new project in Visual Studio. You can use the default page added, or create a new one for the purpose. The content should look something like this:
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Test.aspx.cs" Inherits="Test" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Demo</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <asp:Label runat="server" ID="lblHelloWorld" Text="Hello, world!" />
        </form>
    </body>
    </html>
    
    If you run it, you will get the good old "Hello, world!" message, in plain English as expected. Now let's add some localization magic to it. We will use local, implicit localization for this - both are new terms, which will be explained later on. For now, just right click on your project and from the Add ASP.NET folder sub menu, select App_LocalResources. This is the folder where we place local resources, each of them specific to a file in your project.

    Now, right click this new folder, and add a new item. This should be a Resource file, and the name should be the same as your page, but with a .resx extension. For instance, I called my page Test.aspx, so my Resource file should be named Test.aspx.resx. This part is important - if we want ASP.NET to automatically map a resource file to a specific ASP.NET page, the names should be like this. This is our default resource file, used to keep the default version of our strings. Let's add a couple of other languages. Once again, the filename is used to map the resource file, so for instance, to add a German language file, the name should be <filename>.aspx.de.resx, or in the culture specific version: <filename>.aspx.de-DE.resx

    I have added Test.aspx.de-DE.resx and Test.aspx.es-ES.resx, to translate the page into German and Spanish. Then I add a new row to Test.aspx.resx, with the name lblHelloWorld.Text. In my project, English is the default language, so I give this row a value of "Hello, world!". I then open Test.aspx.de-DE.resx, add a row with the same name as before, and set the value to "Hallo, Welt!". I do the same for Test.aspx.es-ES.resx, where I set the value to "Hola, mundo!". Your three resource files should now all have a row with the name of "lblHelloWorld.Text", and a localized version of the Hello world string.

    Now, go back to our ASP.NET page and use the meta:resourcekey property on our Label control, to make it use our resource string. It should look like this:
    <asp:Label runat="server" ID="lblHelloWorld" Text="Hello, world!" meta:resourcekey="lblHelloWorld" />
    
    As you can see, I've used the same string as for the ID of the control. You probably remeber that we added a resource row with the name of "lblHelloWorld.Text". This corresponds to a control with the resource key of "lblHelloWorld", mapped to the Text property of this control. Now, try setting the UICulture property on your page and run the example:
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Test.aspx.cs" Inherits="Test" UICulture="de-DE" %>
    
    The label is now in German. Change UICulture to "es-ES" and reload the page. It's now in Spanish. Then try changing it to something completely different, like fr-FR, and you will see our default language used instead, simply because we don't have a localized version of the string in French.

    This was a simple example, to show you how it can work, but you need a bit more information about HOW it works. In the next couple of chapters we will look into local and global localization, as well as implicit and explicit localization. First up is the CultureInfo class though, since it's used heavily when doing localization.


    The CultureInfo class
    When it comes to localization of your application, especially one class is of great importance: The CultureInfo class from the System.Globalization namespace. From this class, you can get information about pretty much every possible culture out there, including a wide range of culture specific settings. The CultureInfo class can really help you when localizing your webpages, most notably because ASP.NET will keep a reference to the specific CultureInfo instance related to a specific visitor. Does it sound complicated? Let me show you a little example:
    <%@ Page Language="C#" Culture="Auto" %>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>CultureInfo demo</title>
    </head>
    <body>
        <form id="MainForm" runat="server">
            <% Response.Write("Your current culture: " + System.Globalization.CultureInfo.CurrentCulture.DisplayName);    %>
        </form>
    </body>
    </html>
    
    Try running this and you will get a culture related to you - but how? Actually, since the Culture property of the Page directive is set to Auto, this is controlled by your browser. Most browsers allow you to set your favorite languages, and from that, ASP.NET tries to detect which culture to use for you. We will look into that in greater detail later on. Your current culture is used in lots of cases, for instance when formatting dates and numbers, since that varies from culture to culture. Now, you may want to use a specific culture, no matter what your visitors browser tells you. In that case, you can set the Culture property of the page, like this:
    <%@ Page Language="C#" Culture="en-US" %>
    
    If you run the example now, you will get the output "English (United States)", which is the language of English, with a specific US culture. English comes in other flavors too, for instance British or Australian. en-US is considered a specific culture, where en (just English) is considered a neutral culture, since it's just a language, not specific to any country. Now, to see the difference between two cultures, try running this example:
    <%@ Page Language="C#" Culture="en-US" %>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>CultureInfo demo</title>
    </head>
    <body>
        <form id="MainForm" runat="server">
            <% Response.Write("Current date, in a culture specific format: " + DateTime.Now.ToString()); %>
        </form>
    </body>
    </html>
    
    Now, try changing the page Culture to a German one, like this:
    <%@ Page Language="C#" Culture="de-DE" %>
    
    You will see the exact same line of code output a different result, because it's culture dependant. But you can actually output a culturally aware date (or number or anything else) without changing the culture of the page. For instance, like this:
    <% Response.Write("Current date, in a culture specific format: " + DateTime.Now.ToString(System.Globalization.CultureInfo.GetCultureInfo("de-DE").DateTimeFormat)); %>
    
    We simply get a reference to a German culture, and then use it as a parameter to the ToString() method on the DateTime class. CultureInfo comes with a NumberFormat property for formatting numbers too. Obviously, formatting dates and numbers is just a small part of localizing an application, but the CultureInfo class is (or at least can be) the foundation of this process, mainly because it's so well integrated with the .NET framework, and in particular ASP.NET.

    Culture vs. UICulture

    This was all about the Culture property, but the Page class does come with another related property: The UICulture property. UI stands for User Interface, so in fact, this is the property we can use to identify the language used for the visual part of the page, while the Culture property is used for the non-UI stuff, like date and number formatting, sorting and so on. In lots of situations, you would want to use the same Culture and UICulture, but there are cases where you would want to separate these two, for instance when you want the text of a website to be localized, while still outputting a consistent date or number format, no matter where the user comes from.


    Local & Global resources
    When localizing your ASP.NET websites, you can store your resources as either a local or a global resource. A local resource is specific to a certain page, which is the only one who can access it, while global resources can be accessed from anywhere.

    Local resources are kept in the special App_LocalResources folder, while global resources are kept in the App_GlobalResources folder. Local and global resource files will look exactly the same, so the only apparent difference, is the folder they're placed in. However, they are used differently. For instance, with local resources, you need a resource file for each of your pages, and an extra one of each of the desired languages. So if you have a website with 10 pages, each localized into two other languages, besides the default language, it will amount to 30 resource files. With global resources, you would only need (but not be limited to) one file per language, no matter how many pages you have. On the other hand, each of these files could get pretty hard to manage, if your site has lots of localized content.

    You will likely always need some global resources, but if you prefer, you may skip the local resources and only use global ones. It's really up to you.


    Implicit & Explicit localization
    Implicit localization is used within your markup, and its main advantage is that it allows you to localize several properties of the same control/object, without explicitly referencing each property. In our Localized Hello World chapter, we used it, and saw how we could set the meta:resourcekey property of a control, and then automatically have its Text property mapped to the resource row in our resource file. Let's expand a bit on that example, to have several properties localized. If you haven't already done so, you should read the Localized Hello World chapter now and create the project from it, as the following example uses it:
    <asp:Label runat="server" ID="lblHelloWorld" Text="Hello, world!" Font-Names="Verdana" ForeColor="Blue" meta:resourcekey="lblHelloWorld" />
    
    In the three resource files we created (default, Germand and Spanish), you can now add two extra rows to each of them, with the names "lblHelloWorld.ForeColor" and "lblHelloWorld.Font-Names", and then define different values for it. For instance, the default label color could be blue, the German version could be green and the Spanish version could be red, and you could define different font names for each of them as well. This makes it really easy to localize e.g. controls, because we only have to define the name of the resource row - each property is automatically mapped.

    Explicit localization

    With explicit localization, you pick out a specific resource row from your resource file, which is returned to you, and while implicit localization can be helpful when localizing webcontrols and other declarative objects, explicit localization is the only possible way of doing things in any other circumstance. Let's see how the above example would look with explicit localization:
    <asp:Label runat="server" ID="lblHelloWorld2" Text="<%$ Resources:lblHelloWorld.Text %>" Font-Names="<%$ Resources:lblHelloWorld.Font-Names %>" ForeColor="<%$ Resources:lblHelloWorld.ForeColor %>"  />
    
    We simply re-use the resource rows from our previous example, and as you can see, the markup for explicit localization is a bit more complicated and verbose than for implicit localization. The syntax for retrieving a resource row is like this:
    <%$ Resources:[resource class name,]RowName %>
    
    As you can see, we didn't specify a resource class name in our example, because we use a local resource. If you use a global resource, you should specify the name of the class it results it, which as a rule of thumb is the same as the filename, but without the .resx extension. So for instance, if you have a global resource file with the name of MyGlobalResources.resx, you would obtain a resource from it like this:
    <%$ Resources: MyGlobalResources,NameOfRow %>
    
    As simple as that.


    Localizing the CodeBehind
    In the previous chapters, we only used localization for the markup part of the webpage, but localizing your strings in Code Behind is just as simple. Here are the techniques for doing this, with some sample code to get you started.

    Direct access

    Since the .NET framework takes your global resource files and turns them into strongly typed classes, you can actually reference them as such. For instance, if you have a global resource file called MyGlobalResources.resx, with a resource row with a name of HelloWorldString, you can access it like this:
    lblHelloWorld.Text = Resources.MyGlobalResources.HelloWorldString;
    

    GetLocalResourceObject()

    With a call to GetLocalResourceObject(), you can get a specific row from your local resource file. It is returned as an object, but you can always call the ToString() method on it. For this to work, you have to be within a file that has a local resource file. To get a row from it, simply specify the name of the row as a parameter to the method, like this:
    lblHelloWorld.Text = GetLocalResourceObject("lblHelloWorld.Text").ToString();
    

    GetGlobalResourceObject()

    The GetGlobalResourceObject() method works pretty much like the local version described above, but for global resources instead. You have to specify an extra parameter though, to tell ASP.NET in which global resource file you want to look for the row in, so the first parameter is the name of the resource class generated from the resource file, while the secondary parameter is for specifying the name of the row you're looking for, like this:
    lblHelloWorld.Text = GetGlobalResourceObject("MyGlobalResources", "HelloWorldString").ToString();
    
    Which approach to use mostly depends on the situation and what you prefer, but the first one does have a big advantage: Since it's strongly typed, the compiler will alert you if the row you are trying to retrieve no longer exists, allowing you to catch any problems before they go into production.


    Changing the active culture
    In a previous chapter, we had a look at the CultureInfo class, and we briefly discussed how to change it for a page. However, since changing the current culture is so essential, this chapter will contain an in-depth look of the different ways to accomplish this.

    Automatic

    Both Culture and UICulture is automatically set based on the browser settings of your visitor. Try running the following page:
    <%@ Page Language="C#" %>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>CultureInfo demo</title>
    </head>
    <body>
        <form id="MainForm" runat="server">
            <% Response.Write("Your current culture: " + System.Globalization.CultureInfo.CurrentCulture.DisplayName); %>
        </form>
    </body>
    </html>
    
    Now, access your browsers language settings:

    Internet Explorer: Click the Tools button, select Internet Options, then click the Languages button.

    Firefox: Click the Tools menu, select Options, select the Content tab and then click the Choose button in the Languages group.

    Add another language, and then move it to the top of the list. Close the dialog and reload the page (F5). You will now see the name of the culture matching your newly selected language.

    The Page directive/class

    As we saw in the previous chapter, we can simply define both Culture and UICulture by accessing the properties in the Page directive:
    <%@ Page Language="C#" Culture="en-US" UICulture="en-US" %>
    
    Since the Page directive is just a shortcut to the Page class, this can be done from CodeBehind as well. However, we have to do it at a certain point, before the page is being rendered, to make sure that it has the desired effect. This is where the InitializeCulture() method comes into play, a method that is called by ASP.NET pretty early in the Page life cycle, which you can override:
    public partial class CultureInfoTest : System.Web.UI.Page
    {
        protected override void InitializeCulture()
        {
            Page.Culture = "en-GB";
            Page.UICulture = "en-GB";
        }
    
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write(Page.Culture);
        }
    }
    
    You should be aware that the Page.Culture and Page.UICulture properties them self are merely shortcuts to the System.Threading.Thread.CurrentThread.CurrentCulture and System.Threading.Thread.CurrentThread.CurrentUICulture.

    Globally

    You can set the Culture and UICulture for all your pages, via the web.config file. Use the globalization node, which is a child node of the system.web node, like this:
    <globalization uiCulture="en-US" culture="en-US" />
    
    If needed, you can still override this setting on individual pages.
  • ASP.NET & MYSQL ↓

    ASP.NET & MySQL

    Introduction
    MySQL is one of the most used database servers on the Internet. Part of its popularity comes from the tight integration with PHP, but ASP.NET can use it as well. By using the Odbc classes from the .NET framework, you can easily work with a MySQL database.

    This tutorial will not cover installing MySQL, nor will it cover SQL in general. It will focus on using MySQL with ASP.NET.

    Follow the next chapters to get started with using MySQL together with ASP.NET. We will cover topics from the first connection to databinding and much more.


    Getting started
    The easiest way to use MySQL with ASP.NET is to use the MySQL ODBC Connector from MySQL AB. If you're work is being hosted by a company which supports MySQL, they have probably already installed this, but if you're testing your code on your own machine with your own instance of MySQL, then you need to install this. MySQL Connector/ODBC 3.51 can be downloaded from this page: http://dev.mysql.com/downloads/connector/odbc/3.51.html

    Once installed, you will be able to connect to your MySQL database server. Doing so is quite easy, but we will also need some data to test on. During the next chapters, we will be using a table called test_users. You can find the SQL code to create and fill the table with test data below. Run it trough your favorite MySQL client's SQL function, or use the command prompt to import into a new or existing database.

    First of all, let's create a new project for this in Visual Studio. Secondly, let's store the connection information for the database in once place, so we can reuse all over our application. We will do this with the web.config file. You can add it by right clicking the project name in the Solution Explorer, and selecting "Add New Item". From the dialog that pops up, select "Web Configuration File". Press Add, and the file will be added to your project. It will automatically be opened. Now, find the part that says and replace it with this:
    <connectionStrings>
      <add name="MySQLConnStr" connectionString="DRIVER={MySQL ODBC 3.51 Driver};Database=YourDatabase;Server=localhost;UID=YourUsername;PWD=YourPassword;"/>
    </connectionStrings>
    
    By doing so, we can access the connection string from all over the application. You should replace 3 values in it: YourDatabase, YourUsername and YourPassword. They should of course be replaced with the name of the database that you care to use, as well as the username and password for one of the users of the MySQL database server. In the next chapter, I will show you how we retrieve the value and use it.

    Here is the SQL code to create and fill our test table with some data:
    CREATE TABLE `test_users` (
      `id` int(11) NOT NULL auto_increment,
      `name` varchar(100) NOT NULL default '',
      `country` varchar(100) NOT NULL default '',
      PRIMARY KEY  (`id`)
    );
    
    INSERT INTO `test_users` VALUES (1,'John','USA');
    INSERT INTO `test_users` VALUES (2,'Mark','Canada');
    INSERT INTO `test_users` VALUES (3,'Lukas','Germany');
    INSERT INTO `test_users` VALUES (4,'Ingrid','Sweden');
    



    First access
    Okay, let's try accessing our test table for the first time, using ASP.NET. First of all, we need to import the System.Data.Odbc namespace. Add the following line in the top of your CodeBehind file:
    using System.Data.Odbc;
    
    This will give us access to a bunch of ODBC related classes. For now, we will need 3 of them:

    OdbcConnection - Provides an ODBC connection to a database.
    OdbcCommand - Will execute an SQL command using an existing OdbcConnection.
    OdbcDataReader - Will provide fast access to the data which the OdbcCommand will bring us.


    The first example will focus on getting access to our test data, and simply printing it out, and while this is not how we normally do things with ASP.NET, it's simply meant to show you the most basic example of data access. Since we write directly to the (top of the) page, we don't need to add any markup code. Simply go to the CodeBehind (.cs) file, and add the following code to the Page_Load method:
    try
    {
        using(OdbcConnection connection = new OdbcConnection(ConfigurationManager.ConnectionStrings["MySQLConnStr"].ConnectionString))
        {
            connection.Open();
            using(OdbcCommand command = new OdbcCommand("SELECT name FROM test_users", connection))
            using(OdbcDataReader dr = command.ExecuteReader())
            {
                while(dr.Read())
                    Response.Write(dr["name"].ToString() + "<br />");
                dr.Close();
            }
            connection.Close();
        }
    }
    catch(Exception ex)
    {
        Response.Write("An error occured: " + ex.Message);
    }
    
    Okay, if you come from the PHP world, you're probably about to run away because of the big amount of code needed to perform a simple database extraction. However, C# is an Object Oriented language, and sometimes it just takes a bit more code to make a more elegant solution. Of course, code like this can be gathered in reusable classes and methods, but for now, we do it the basic way.

    Now, let me try to explain the various lines of code. First we create an OdbcConnection object, to establish the connection with the database. We use the ConfigurationManager class to obtain the connection string which we stored in the web.config file in the previous chapter. It's with in a using() construct, which is a convenint way to tell C# that when the block of code ends, it should dispose the object. If we didn't use it, we would instead have to call connection.Dispose(); when we were done. Next, we open the connection, and then we create an instance of the OdbcCommand class, which is used to fire off SQL queries against the database. Using the command object, we query the database, and in return we get an OdbcDataReader. The DataReader class is the simplest and fastest way to access a database in .NET.

    We loop through the datareader, and on each iteration, we output the name field from the database, along with a linebreak tag. Pretty simple, right? As you can see, the entire data access block is encapsulated in a try..catch block. Lots of things can go wrong when interacting with a database, so using a try..catch block is recommended. Using dr["name"], we get the result as an object, which is why I'm calling the ToString(). If you wish for more control of the datatype you receive from the reader, you can use the Get* methods, like GetInt32(), GetString() etc. However, these methods require you to use the index of the field in your query, and not the name of the field, which is not as convenient.

    Run the website, and have a look at the output. It should contain a bunch of names from our test table, or which ever table you're using.


    Data Binding
    Our first example was very little ASP.NET'ish. With ASP.NET, databinding is the big thing, and once you've used it for a while, you will likely understand why. Databinding can really save some time for you. We will start off with a very basic example of databinding, but even though it's simple, it's also extremely useful. Populating a dropdown list can be a boring job, but have a look how easy it can be done. Start off by adding a dropdown list to the page:
    <asp:DropDownList runat="server" id="ddlUsers" datavaluefield="id" datatextfield="name" />
    
    The datavaluefield property tells the control which database field should be used for the value property of each item, and the datatextfield tells the control which field to use for the actual text of the item. That's all we need in the markup department, so switch to CodeBehind. Here we will use almost the same code as in the last chapter, with a small modification:
    try
    {
        using(OdbcConnection connection = new OdbcConnection(ConfigurationManager.ConnectionStrings["MySQLConnStr"].ConnectionString))
        {
            connection.Open();
            using(OdbcCommand command = new OdbcCommand("SELECT id, name FROM test_users", connection))
            using(OdbcDataReader dr = command.ExecuteReader())
            {
                ddlUsers.DataSource = dr;
                ddlUsers.DataBind();
                dr.Close();
                
            }
            connection.Close();
        }
    }
    catch(Exception ex)
    {
        Response.Write("An error occured: " + ex.Message);
    }
    
    Only 2 things have changed from the last example: We've added a field to the query (the id field), and we have changed the loop to a couple of databinding lines. The first one assigns the datasource of the dropdown list to our datareader, and the second one tells the dropdown list to perform the databinding. That's all we need, which you will see if you run the website. The dropdown list will be filled with names from our test table.

    This is just a basic example. Later on, when we work with repeaters, datagrids etc. you will surely realize the true potential of databinding.
  • LINQ ↓

    Most applications are data-centric, however most of the data repositories are relational databases. Over the years, designers and developers have designed applications based on object models.

    The objects are responsible for connecting to the data access components - called the Data Access Layer (DAL). Here we have three points to consider:

    • All the data needed in an application are not stored in the same source. The source could be a relation database, some business object, XML file, or a web service.

    • Accessing in-memory object is simpler and less expensive than accessing data from a database or XML file.

    • The data accessed are not used directly, but needs to be sorted, ordered, grouped, altered etc.

    Hence if there is one tool that makes all kind of data access easy that allows joining data from such disparate data sources and perform standard data processing operations, in few lines of codes, it would be of great help.

    LINQ or Language-Integrated Query is such a tool. LINQ is set of extensions to the .Net Framework 3.5 and its managed languages that set the query as an object. It defines a common syntax and a programming model to query different types of data using a common language.

    The relational operators like Select, Project, Join, Group, Partition, Set operations etc., are implemented in LINQ and the C# and VB compilers in the .Net framework 3.5, which support the LINQ syntax makes it possible to work with a configured data store without resorting to ADO.NET.

    For example, querying the Customers table in the Northwind database, using LINQ query in C#, the code would be:

    var data = from c in dataContext.Customers
    where c.Country == "Spain"
    select c;
    

    Where:

    • The 'from' keyword logically loops through the contents of the collection.

    • The expression with the 'where' keyword is evaluated for each object in the collection.

    • The 'select' statement selects the evaluated object to add to the list being returned.

    • The 'var' keyword is for variable declaration. Since the exact type of the returned object is not known, it indicates that the information will be inferred dynamically.

    LINQ query can be applied to any data-bearing class that inherits from IEnumerable<T>, here T is any data type, for example, List<Book>.

    Let us look at an example to understand the concept. The example uses the following class: Books.cs

    public class Books
    {
       public string ID {get; set;}
       public string Title { get; set; }
       public decimal Price { get; set; }
       public DateTime DateOfRelease { get; set; }
    
       public static List<Books> GetBooks()
       {
          List<Books> list = new List<Books>();
          list.Add(new Books { ID = "001", 
             Title = "Programming in C#", 
             Price = 634.76m, 
             DateOfRelease = Convert.ToDateTime("2010-02-05") });
         
          list.Add(new Books { ID = "002", 
             Title = "Learn Jave in 30 days", 
             Price = 250.76m, 
             DateOfRelease = Convert.ToDateTime("2011-08-15") });
         
          list.Add(new Books { ID = "003", 
             Title = "Programming in ASP.Net 4.0", 
             Price = 700.00m, 
             DateOfRelease = Convert.ToDateTime("2011-02-05") });
         
          list.Add(new Books { ID = "004", 
             Title = "VB.Net Made Easy", 
             Price = 500.99m, 
             DateOfRelease = Convert.ToDateTime("2011-12-31") });
         
          list.Add(new Books { ID = "005", 
             Title = "Programming in C", 
             Price = 314.76m, 
             DateOfRelease = Convert.ToDateTime("2010-02-05") });
         
          list.Add(new Books { ID = "006", 
             Title = "Programming in C++", 
             Price = 456.76m, 
             DateOfRelease = Convert.ToDateTime("2010-02-05") });
         
          list.Add(new Books { ID = "007", 
             Title = "Datebase Developement", 
             Price = 1000.76m, 
             DateOfRelease = Convert.ToDateTime("2010-02-05") });
             
          return list;
       }
    }
    

    The web page using this class has a simple label control, which displays the titles of the books. The Page_Load event creates a list of books and returns the titles by using LINQ query:

    public partial class simplequery : System.Web.UI.Page
    {
       protected void Page_Load(object sender, EventArgs e)
       {
          List<Books> books = Books.GetBooks();
          var booktitles = from b in books select b.Title;
    
          foreach (var title in booktitles)
             lblbooks.Text += String.Format("{0} <br />", title);
       }
    }
    

    When the page is executed, the label displays the results of the query:

    LINQ Result

    The above LINQ expression:

    var booktitles = 
    from b in books 
    select b.Title;
    

    Is equivalent to the following SQL query:

    SELECT Title from Books
    

    LINQ Operators

    Apart from the operators used so far, there are several other operators, which implement all query clauses. Let us look at some of the operators and clauses.

    The Join clause

    The 'join clause' in SQL is used for joining two data tables and displays a data set containing columns from both the tables. LINQ is also capable of that. To check this, add another class named Saledetails.cs in the previous project:

    public class Salesdetails
    {
       public int sales { get; set; }
       public int pages { get; set; }
       public string ID {get; set;}
    
       public static IEnumerable<Salesdetails> getsalesdetails()
       { 
          Salesdetails[] sd = 
          {
             new Salesdetails { ID = "001", pages=678, sales = 110000},
             new Salesdetails { ID = "002", pages=789, sales = 60000},
             new Salesdetails { ID = "003", pages=456, sales = 40000},
             new Salesdetails { ID = "004", pages=900, sales = 80000},
             new Salesdetails { ID = "005", pages=456, sales = 90000},
             new Salesdetails { ID = "006", pages=870, sales = 50000},
             new Salesdetails { ID = "007", pages=675, sales = 40000},
          };
          
          return sd.OfType<Salesdetails>();
       }
    }
    

    Add the codes in the Page_Load event handler to query on both the tables using the join clause:

    protected void Page_Load(object sender, EventArgs e)
    {
       IEnumerable<Books> books = Books.GetBooks();
       IEnumerable<Salesdetails> sales = Salesdetails.getsalesdetails();
       
       var booktitles = from b in books join s in sales on b.ID equals s.ID
          select new { Name = b.Title, Pages = s.pages };
          
       foreach (var title in booktitles)
          lblbooks.Text += String.Format("{0} <br />", title);
    }
    

    The resulting page is as shown:

    LINQ Result2

    The Where clause

    The 'where clause' allows adding some conditional filters to the query. For example, if you want to see the books, where the number of pages are more than 500, change the Page_Load event handler to:

    var booktitles = from b in books join s in sales on b.ID equals s.ID
       where s.pages > 500 select new { Name = b.Title, Pages = s.pages };
    

    The query returns only those rows, where the number of pages is more than 500:

    LINQ Result3

    Orderby and Orderbydescending Clauses

    These clauses allow sorting the query results. To query the titles, number of pages and price of the book, sorted by the price, write the following code in the Page_Load event handler:

    var booktitles = from b in books join s in sales on b.ID equals s.ID
       orderby b.Price select new { Name = b.Title,  Pages = s.pages, Price = b.Price};
    

    The returned tuples are:

    LINQ Result4

    The Let clause

    The let clause allows defining a variable and assigning it a value calculated from the data values. For example, to calculate the total sale from the above two sales, you need to calculate:

    TotalSale = Price of the Book * Sales
    

    To achieve this, add the following code snippets in the Page_Load event handler:

    The let clause allows defining a variable and assigning it a value calculated from the data values. For example, to calculate the total sale from the above two sales, you need to calculate:

    var booktitles = from b in book join s in sales on b.ID equals s.ID
       let totalprofit = (b.Price * s.sales)
       select new { Name = b.Title, TotalSale = totalprofit};
    

    The resulting query page is as shown:

    LINQ Result5
  • ADO ↓

    ADO.NET provides a bridge between the front end controls and the back end database. The ADO.NET objects encapsulate all the data access operations and the controls interact with these objects to display data, thus hiding the details of movement of data.

    The following figure shows the ADO.NET objects at a glance:

    ADO.Net objects

    The DataSet Class

    The dataset represents a subset of the database. It does not have a continuous connection to the database. To update the database a reconnection is required. The DataSet contains DataTable objects and DataRelation objects. The DataRelation objects represent the relationship between two tables.

    Following table shows some important properties of the DataSet class:

    Properties Description
    CaseSensitive Indicates whether string comparisons within the data tables are case-sensitive.
    Container Gets the container for the component.
    DataSetName Gets or sets the name of the current data set.
    DefaultViewManager Returns a view of data in the data set.
    DesignMode Indicates whether the component is currently in design mode.
    EnforceConstraints Indicates whether constraint rules are followed when attempting any update operation.
    Events Gets the list of event handlers that are attached to this component.
    ExtendedProperties Gets the collection of customized user information associated with the DataSet.
    HasErrors Indicates if there are any errors.
    IsInitialized Indicates whether the DataSet is initialized.
    Locale Gets or sets the locale information used to compare strings within the table.
    Namespace Gets or sets the namespace of the DataSet.
    Prefix Gets or sets an XML prefix that aliases the namespace of the DataSet.
    Relations Returns the collection of DataRelation objects.
    Tables Returns the collection of DataTable objects.

    The following table shows some important methods of the DataSet class:

    Methods Description
    AcceptChanges Accepts all changes made since the DataSet was loaded or this method was called.
    BeginInit Begins the initialization of the DataSet. The initialization occurs at run time.
    Clear Clears data.
    Clone Copies the structure of the DataSet, including all DataTable schemas, relations, and constraints. Does not copy any data.
    Copy Copies both structure and data.
    CreateDataReader() Returns a DataTableReader with one result set per DataTable, in the same sequence as the tables appear in the Tables collection.
    CreateDataReader(DataTable[]) Returns a DataTableReader with one result set per DataTable.
    EndInit Ends the initialization of the data set.
    Equals(Object) Determines whether the specified Object is equal to the current Object.
    Finalize Free resources and perform other cleanups.
    GetChanges Returns a copy of the DataSet with all changes made since it was loaded or the AcceptChanges method was called.
    GetChanges(DataRowState) Gets a copy of DataSet with all changes made since it was loaded or the AcceptChanges method was called, filtered by DataRowState.
    GetDataSetSchema Gets a copy of XmlSchemaSet for the DataSet.
    GetObjectData Populates a serialization information object with the data needed to serialize the DataSet.
    GetType Gets the type of the current instance.
    GetXML Returns the XML representation of the data.
    GetXMLSchema Returns the XSD schema for the XML representation of the data.
    HasChanges() Gets a value indicating whether the DataSet has changes, including new, deleted, or modified rows.
    HasChanges(DataRowState) Gets a value indicating whether the DataSet has changes, including new, deleted, or modified rows, filtered by DataRowState.
    IsBinarySerialized Inspects the format of the serialized representation of the DataSet.
    Load(IDataReader, LoadOption, DataTable[]) Fills a DataSet with values from a data source using the supplied IDataReader, using an array of DataTable instances to supply the schema and namespace information.
    Load(IDataReader, LoadOption, String[]) Fills a DataSet with values from a data source using the supplied IDataReader, using an array of strings to supply the names for the tables within the DataSet.
    Merge() Merges the data with data from another DataSet. This method has different overloaded forms.
    ReadXML() Reads an XML schema and data into the DataSet. This method has different overloaded forms.
    ReadXMLSchema(0) Reads an XML schema into the DataSet. This method has different overloaded forms.
    RejectChanges Rolls back all changes made since the last call to AcceptChanges.
    WriteXML() Writes an XML schema and data from the DataSet. This method has different overloaded forms.
    WriteXMLSchema() Writes the structure of the DataSet as an XML schema. This method has different overloaded forms.

    The DataTable Class

    The DataTable class represents the tables in the database. It has the following important properties; most of these properties are read only properties except the PrimaryKey property:

    Properties Description
    ChildRelations Returns the collection of child relationship.
    Columns Returns the Columns collection.
    Constraints Returns the Constraints collection.
    DataSet Returns the parent DataSet.
    DefaultView Returns a view of the table.
    ParentRelations Returns the ParentRelations collection.
    PrimaryKey Gets or sets an array of columns as the primary key for the table.
    Rows Returns the Rows collection.

    The following table shows some important methods of the DataTable class:

    Methods Description
    AcceptChanges Commits all changes since the last AcceptChanges.
    Clear Clears all data from the table.
    GetChanges Returns a copy of the DataTable with all changes made since the AcceptChanges method was called.
    GetErrors Returns an array of rows with errors.
    ImportRows Copies a new row into the table.
    LoadDataRow Finds and updates a specific row, or creates a new one, if not found any.
    Merge Merges the table with another DataTable.
    NewRow Creates a new DataRow.
    RejectChanges Rolls back all changes made since the last call to AcceptChanges.
    Reset Resets the table to its original state.
    Select Returns an array of DataRow objects.

    The DataRow Class

    The DataRow object represents a row in a table. It has the following important properties:

    Properties Description
    HasErrors Indicates if there are any errors.
    Items Gets or sets the data stored in a specific column.
    ItemArrays Gets or sets all the values for the row.
    Table Returns the parent table.

    The following table shows some important methods of the DataRow class:

    Methods Description
    AcceptChanges Accepts all changes made since this method was called.
    BeginEdit Begins edit operation.
    CancelEdit Cancels edit operation.
    Delete Deletes the DataRow.
    EndEdit Ends the edit operation.
    GetChildRows Gets the child rows of this row.
    GetParentRow Gets the parent row.
    GetParentRows Gets parent rows of DataRow object.
    RejectChanges Rolls back all changes made since the last call to AcceptChanges.

    The DataAdapter Object

    The DataAdapter object acts as a mediator between the DataSet object and the database. This helps the Dataset to contain data from multiple databases or other data source.

    The DataReader Object

    The DataReader object is an alternative to the DataSet and DataAdapter combination. This object provides a connection oriented access to the data records in the database. These objects are suitable for read-only access, such as populating a list and then breaking the connection.

    DbCommand and DbConnection Objects

    The DbConnection object represents a connection to the data source. The connection could be shared among different command objects.

    The DbCommand object represents the command or a stored procedure sent to the database from retrieving or manipulating data.

    Example

    So far, we have used tables and databases already existing in our computer. In this example, we will create a table, add column, rows and data into it and display the table using a GridView object.

    The source file code is as given:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="createdatabase._Default" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" >
    
       <head runat="server">
          <title>
             Untitled Page
          </title>
       </head>
       
       <body>
          <form id="form1" runat="server">
          
             <div>
                <asp:GridView ID="GridView1" runat="server">
                </asp:GridView>
             </div>
             
          </form>
       </body>
       
    </html>
    

    The code behind file is as given:

    namespace createdatabase
    {
       public partial class _Default : System.Web.UI.Page
       {
          protected void Page_Load(object sender, EventArgs e)
          {
             if (!IsPostBack)
             {
                DataSet ds = CreateDataSet();
                GridView1.DataSource = ds.Tables["Student"];
                GridView1.DataBind();
             }
          }
          
          private DataSet CreateDataSet()
          {
             //creating a DataSet object for tables
             DataSet dataset = new DataSet();
    
             // creating the student table
             DataTable Students = CreateStudentTable();
             dataset.Tables.Add(Students);
             return dataset;
          }
          
          private DataTable CreateStudentTable()
          {
             DataTable Students = new DataTable("Student");
    
             // adding columns
             AddNewColumn(Students, "System.Int32", "StudentID");
             AddNewColumn(Students, "System.String", "StudentName");
             AddNewColumn(Students, "System.String", "StudentCity");
    
             // adding rows
             AddNewRow(Students, 1, "M H Kabir", "Kolkata");
             AddNewRow(Students, 1, "Shreya Sharma", "Delhi");
             AddNewRow(Students, 1, "Rini Mukherjee", "Hyderabad");
             AddNewRow(Students, 1, "Sunil Dubey", "Bikaner");
             AddNewRow(Students, 1, "Rajat Mishra", "Patna");
    
             return Students;
          }
    
          private void AddNewColumn(DataTable table, string columnType, string  columnName)
          {
             DataColumn column = table.Columns.Add(columnName,  Type.GetType(columnType));
          }
    
          //adding data into the table
          private void AddNewRow(DataTable table, int id, string name, string city)
          {
             DataRow newrow = table.NewRow();
             newrow["StudentID"] = id;
             newrow["StudentName"] = name;
             newrow["StudentCity"] = city;
             table.Rows.Add(newrow);
          }
       }
    }
    

    When you execute the program, observe the following:

    • The application first creates a data set and binds it with the grid view control using the DataBind() method of the GridView control.

    • The Createdataset() method is a user defined function, which creates a new DataSet object and then calls another user defined method CreateStudentTable() to create the table and add it to the Tables collection of the data set.

    • The CreateStudentTable() method calls the user defined methods AddNewColumn() and AddNewRow() to create the columns and rows of the table as well as to add data to the rows.

    When the page is executed, it returns the rows of the table as shown:

    ADO.Net Result
  • LOCAL & GLOBAL DEPLOYMENT ↓

    There are different techniques used for deployment, however, we will discuss the following most common and easiest ways of deployment:

    • XCOPY deployment
    • Copying a Website
    • Creating a set up project

    XCOPY Deployment

    XCOPY deployment means making recursive copies of all the files to the target folder on the target machine. You can use any of the commonly used techniques:

    • FTP transfer
    • Using Server management tools that provide replication on a remote site
    • MSI installer application

    XCOPY deployment simply copies the application file to the production server and sets a virtual directory there. You need to set a virtual directory using the Internet Information Manager Microsoft Management Console (MMC snap-in).

    Copying a Website

    The Copy Web Site option is available in Visual Studio. It is available from the Website -> Copy Web Site menu option. This menu item allows copying the current web site to another local or remote location. It is a sort of integrated FTP tool.

    Using this option, you connect to the target destination, select the desired copy mode:

    • Overwrite
    • Source to Target Files
    • Sync UP Source And Target Projects

    Then proceed with copying the files physically. Unlike the XCOPY deployment, this process of deployment is done from Visual Studio environment. However, there are following problems with both the above deployment methods:

    • You pass on your source code.
    • There is no pre-compilation and related error checking for the files.
    • The initial page load will be slow.

    Creating a Setup Project

    In this method, you use Windows Installer and package your web applications so it is ready to deploy on the production server. Visual Studio allows you to build deployment packages. Let us test this on one of our existing project, say the data binding project.

    Open the project and take the following steps:

    Step (1) : Select File -> Add -> New Project with the website root directory highlighted in the Solution Explorer.

    Step (2) : Select Setup and Deployment, under Other Project Types. Select Setup Wizard.

    Select Setup Wizard

    Step (3) : Choosing the default location ensures that the set up project will be located in its own folder under the root directory of the site. Click on okay to get the first splash screen of the wizard.

    splash screen Wizard

    Step (4) : Choose a project type. Select 'Create a setup for a web application'.

    splash screen Wizard2

    Step (5) : Next, the third screen asks to choose project outputs from all the projects in the solution. Check the check box next to 'Content Files from...'

    splash screen Wizard3

    Step (6) : The fourth screen allows including other files like ReadMe. However, in our case there is no such file. Click on finish.

    splash screen Wizard4

    Step (7) : The final screen displays a summary of settings for the set up project.

    splash screen Wizard5

    Step (8) : The Set up project is added to the Solution Explorer and the main design window shows a file system editor.

    splash screen Wizard6

    Step (9) : Next step is to build the setup project. Right click on the project name in the Solution Explorer and select Build.

    splash screen Wizard7

    Step (10) : When build is completed, you get the following message in the Output window:

    splash screen Wizard8

    Two files are created by the build process:

    • Setup.exe
    • Setup-databinding.msi

    You need to copy these files to the server. Double-click the setup file to install the content of the .msi file on the local machine.