Archives

Archives / 2011 / February
  • Data caching in ASP.Net applications

    In this post I will continue my series of posts on caching.

    You can read my other post in Output caching here.You can read on how to cache a page depending on the user's browser language.

    Output caching has its place as a caching mechanism. But right now I will focus on data caching.The advantages of data caching are well known but I will highlight the main points.

    • We have improvements in response times
    • We have reduced database round trips
    • We have different levels of caching and it is up to us as developers to use the appropriate one

    I will demonstrate data caching with a hands on example.Embrace yourselves for a very long post.

    I assume that you have access to a version of SQL Server and Northwind database.

    If you do not, you can download and install the free SQL Server Express edition from here. If you need the installation scripts for the sample Northwind database, click here

    1) Launch Visual Studio 2010/2008/2005 (express editions will work fine). Create a new empty website and choose a suitable name for it. Choose C# as the development language.

    2) Add a new item to your site, a web form. Leave the default name, Default.aspx

    3) Add ASP.Net folder in your site, App_Code. Add another item in your file, a class file and call it DataAccess.cs.Add a namespace in the same class file and name it Caching.

    4) Go to View - > Server Explorer (Database Explorer) and add a connection to the Northwind database.You have just to set the instance of the SQL Server and the name of the database.Test the connection.

    5) In your web.config (which is pretty much empty) add a <connectionStrings> section. Ιn my case it like the one below. In your case you must set the Data Source property to your SQL server instance.

    <connectionStrings> <add name="NorthwindConnectionString" connectionString="Data Source=USER-PC\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True" providerName="System.Data.SqlClient"/>

    </connectionStrings>

    6) My intention is to populate a datatable object witn some data from the Customers table from the Northwind database.I will create a static method inside the static class.

     Inside my DataAccess.cs file I have this code so far

    namespace Caching

    {

    public static class DataAcess

    {

    public static DataTable GetCustomers()

    {

    string conn = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].

    ConnectionString;

    SqlDataAdapter adapt = new SqlDataAdapter("select top 10 * from customers order by country", conn);

    DataTable mydatatable = new DataTable();

    adapt.Fill(mydatatable);

    return mydatatable;

    }

    }

    }

    This is very simple static method. It returns a Datatable object as intented.Inside this method I do the following,

    • I get the connection string from the configuration file

    • I create a new adapter object by passing in as parameters, the SQL statement and the connection string

    • I create a new DataTable object and fill it in with data by calling the Fill method of the adapter object.

    7) Make sure you have added the following using statements at the beginning of the file.

    using System.Data;

    using System.Data.SqlClient;

    using System.Configuration;

    8) Add a Gridview and an ObjectDatasource control on the form.Leave the default names. Set the DataSourceID of the GridView to ObjectDataSource1.

    Configure the ObjectDatasource control to select as the Select method the GetCustomers() method of the DataAccess class.The markup for this specifi control should look like this. <asp:ObjectDataSource ID="ObjectDataSource1" runat="server"

    SelectMethod="GetCustomers" TypeName="Caching.DataAcess">

    </asp:ObjectDataSource>

    9) Run your application and you will see the returning rows displayed to the database.So far we have done nothing regarding caching. We just laid down the foundation.

    10) We will make some changes in our GetCustomers() method to incorporate caching.

    namespace Caching

    {

    public static class DataAcess

    {

    public static DataTable GetCustomers()

    {

    DataTable mydatatable = null;if (HttpContext.Current.Cache["customers"] == null)

    {

    string conn = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].

    ConnectionString;

    SqlDataAdapter adapt = new SqlDataAdapter("select top 10 * from customers order by country", conn);mydatatable = new DataTable();

    adapt.Fill(mydatatable);

    HttpContext.Current.Cache["customers"] = mydatatable;

    }

    else

    mydatatable = HttpContext.Current.Cache["customers"] as DataTable;return mydatatable;

    }

     

    }

    }

    I make a simple check, if the data is already in the cache I take it from there. If not, I get it from the datasource.Run your application and you will see the results in the grid. Refresh the page and the records will be served from the cache.

    11) Every time we add something into the cache we can specify several attributes regarding the chach entry. We can specify attributes like Expires-we  specify when the cache will be flushed. We also can congifure the Priority,Dependency (The dependency, this cache entry has on a file or another cache entry) of the cache entry.

    12) We can rewrite the code above to use the attributes.

    Replace this line of code, in the GetCustomers() method.

     HttpContext.Current.Cache["customers"] = mydatatable;

    with this line of code

    HttpContext.Current.Cache.Insert("customers", mydatatable, null, DateTime.Now.AddHours(6), Cache.NoSlidingExpiration);

    I use the Insert method of the Cache object. 

    If you want to find out more about/understand better what I do here have a look here. 

    The parameters I pass are a key to reference the object,then the object to be added to the cache,then I specify I have no dependencies,the expiration date is 6 hours from now and finally I specify that the object in the cache will not be removed regarding the time it was last accessed.

    Run your application and you will see the results in the grid. Refresh the page and the records will be served from the cache.

    13) Now let's see how to remove objects from the cache. We can call the Remove method.We can have implicitly removed data from the cache for reasons like data expiration and memory consumption.

    Let's add another method in our DataAccess class file.

    public static void RemoveFromCache()

    {

    HttpContext.Current.Cache.Remove("customers");

    }

     Add a button to the web form. Inside the Button1_Click even thandling routine type,

     protected void Button1_Click(object sender, EventArgs e)
        {
            DataAcess.RemoveFromCache();
        }

     

    Do not forget to add the namespace in the beginning of the file, in my case is

    using Caching; 

    Run your application. The data will be inserted in the cache and the second request will be served from the cache. Now click the button. The items will be removed from the cache.

    14) Add a new item to your site, a web form. Leave the default name.Connect to your Northwind database. From the Server Explorer window( Database Explorer ) drag and drop the customers table on the form. A Gridview and a sqldatasource control will be added to the form. You can specify caching in the declarative datasources.

    I enabled caching in the sqldatasource control by settting the EnabledCaching to true and CacheDuration to 7200 seconds.

    Run your application and you will see the customers records being served from the database in the initial request. After that they are cached and cache serves the coming requests.

    15) While designing our application, we must be very careful about caching. Sometimes the user must see the latest data, in some cases caching makes no sense at all.Sometimes an item can remain in the cache while a certain other condition is valid.We want to have the data cached for performance reasons but at the same time we want them to have the latest data(most recent updated data) when something changes in the underlying data store. So we must have some sort of depedency between the underlying data store and the cache. There is something that is called Cache Dependency that brings together cache and the origininal data source.

    Add another item on your website, a web form.Leave the default name.Add a GridView control and an ObjectDataSource control on the form.Add another item in your website, an xml file. This is going to be an xml file about footballers.The contents of the xml file are,

    <?xml version="1.0" ?>  

    <footballers>  
      <footballer Position="Attacking Midfielder">  
        <team>Liverpool</team>  
        <name>Steven Gerrard</name>  
        <manager>Kenny Dalglish</manager>  
        <price>40.000.000</price>  
      </footballer>  
      <footballer Position="Striker">  
        <team>Manchester United</team>  
        <name>Wayne Rooney</name>  
        <manager>Alex Ferguson</manager>  
        <price>60.000.000</price>  
      </footballer>  
      <footballer Position="Striker">  
        <team>Barcelona</team>  
        <name>Lionel Messi</name>  
        <manager>Pep Guardiola</manager>  
        <price>110.000.000</price>  
      </footballer>  
      <footballer Position="Central Defender">  
        <team>Chelsea</team>
        <name>John Terry</name>  
        <manager>Carlos Anchelotti</manager>  
        <price>30.000.000</price>  
      </footballer>  
      <footballer Position="Striker">  
        <team>Manchester City</team>  
        <name>Carlos Tevez</name>  
        <manager>Roberto Manchini</manager>  
        <price>65.000.000</price>  
      </footballer>  
      <footballer Position="Stiker">  
        <team>Panathinaikos</team>  
        <name>Cibril Cisse</name>  
        <manager>Zesualdo Ferreira</manager>  
        <price>15.000.000</price>  
      </footballer>  
    </footballers

    16) We want to get the records displayed in the GridView control through the ObjectDataSource control and the intermediate data access layer.

    We must write a static method in the data access layer class file to get the footballers data back from the xml file.We must write the code in a way that the data is cached until changes take place in the underlying xml file.

    public static DataTable GetFootballers()

    {

    DataTable myxmltable = null;if (HttpContext.Current.Cache["footballers"] == null)

    {

    string xmlfilename = HttpContext.Current.Server.MapPath("Footballers.xml");

    DataSet ds = new DataSet();

    ds.ReadXml(xmlfilename);

    myxmltable = ds.Tables[0];

    CacheDependency dependency = new CacheDependency(xmlfilename);HttpContext.Current.Cache.Insert("footballers", myxmltable, dependency);

    }

    else

    myxmltable = HttpContext.Current.Cache["footballers"] as DataTable;return myxmltable;

     

    }

    The code is more or less similar with the one we wrote previously.We check if the data is in the cache and if not I read the file name, I create a dataset,fill it with data from the xml file and I return the datatable.THe most important bit of the method are these 2 lines.

    CacheDependency dependency = new CacheDependency(xmlfilename);

    HttpContext.Current.Cache.Insert("footballers", myxmltable, dependency);

    I create a dependency object by passing as a parameter the xml filename. I insert then in the cache the key, the datatable and the dependency. 

    Set the ObjectDataSource SelectMethod attribute to the method GetFootballers and the TypeName to the Caching.DataAccess.The markup follows below

    <asp:ObjectDataSource ID="ObjectDataSource1" runat="server"

    SelectMethod="GetFootballers" TypeName="Caching.DataAcess"></asp:ObjectDataSource>

    Then set the DataSourceID property of the GridView control to the ObjectDataSource1 control.Run your application.You will see the xml data  being displayed on the screen.

    Refresh the browser window. XML data is being served from the cache.Leave the browser window open. Change something in the xml file and then refresh the page.The browser window will reflect the new changes. In that case the dependency rule comes into place. The data is cached is flushed from the cache and retrieved from the xml file as intended.

    17) Add a new item on the form, a web form. Name it SQLDependencycache.aspx.We will demonstrate in this example how to use sql dependency cache with sql server databases.Add a GridView control and an ObjectDataSource control on the form.

    We will need to add another static method in our data access layer.We will get data from the Categories table of the Northwind database.THe code looks like this

    public static DataTable GetCategories()

    {

    DataTable thedatatable = null;if (HttpContext.Current.Cache["categories"] == null)

    {

    string conn = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].

    ConnectionString;

    using (SqlConnection connection = new SqlConnection(conn))

    {

    connection.Open();

    SqlCommand cmd = new SqlCommand("select CategoryName,Description from dbo.Categories", connection);

    SqlDataAdapter dapt = new SqlDataAdapter(cmd);

    SqlCacheDependency dependency = new SqlCacheDependency(cmd);thedatatable = new DataTable();

    dapt.Fill(thedatatable);

    HttpContext.Current.Cache.Insert("categories", thedatatable, dependency, DateTime.Now.AddHours(6), Cache.NoSlidingExpiration);

    }

    }

    else

    thedatatable = HttpContext.Current.Cache["categories"] as DataTable; return thedatatable;

    }

    The code is very easy to follow. The most important bit is the following lines. We create an SQL cache Dependency that is linked with the specific command object.

    Then when I insert the item in the cache I specify the dependency object.

    SqlCacheDependency dependency = new SqlCacheDependency(cmd);

    HttpContext.Current.Cache.Insert("categories", thedatatable, dependency, DateTime.Now.AddHours(6), Cache.NoSlidingExpiration);

    Set the ObjectDataSource SelectMethod attribute to the methods GetCategories  and the TypeName to the Caching.DataAccess.The markup follows below

    <asp:ObjectDataSource ID="ObjectDataSource1" runat="server"

    SelectMethod="GetCategories" TypeName="Caching.DataAcess"></asp:ObjectDataSource>

    Then set the DataSourceID property of the GridView control to the ObjectDataSource1 control.

    18) In order for this to work we must add another item in the website.Add a global application class file, Global.asax. In the Application_Start() event we should type,

    <%@ Import Namespace = "System.Data.SqlClient" %>

    ....... 

    void Application_Start(object sender, EventArgs e)

    {

    // Code that runs on application startup

    string conn = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].

    ConnectionString;

    SqlDependency.Start(conn); 

    }

    Run your application.You will see the data from the table being displayed on the screen.Refresh the browser window and you will see that the data is being served from the cache.Leave the window open.Make some changes in the Categories table and refresh the page. You will see the updated data being reflected on the screen causing the cache to flush due to the changes in the resultset and the sql cache dependency.

    Email me if you need the code.

    Hope it helps!!!

    Read more...

  • Using the Items collection for state management

    I have explained some of the state mechanisms that we have in our disposal for preserving state in ASP.Net applications in various posts in this blog.

    You can have a look at this post , this post , this post and this one.My last post was on Application state management and you can read it here.

    In this post I will show you how to preserve state using the Items collection. Many developers do not know that we have this option as well for state management.

    With Items state we can pass data between pages and I will show you how to do that with a hands-on example.

    1) Launch Visual Studio 2005,2008/2010. Express editions will work fine. I am using Visual Studio 2010 Ultimate edition.

    2) Create an empty asp.net web site. Choose an appropriate name. Choose C# as the development language.

    3) Add an item to your website, a web form.Leave the default name.Drag and drop a 2 textboxes, a label and a button control on the form.We will want to pass the user's favourite team and colour to another web form. The markup for this web form could be something like this

    <form id="form1" runat="server">

    <div>

    enter your favourite team:<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

    <br />

    enter your favourite color:<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>

    </div>

    <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />

    <p>

    &nbsp;</p>

    </form>

    4) Add a new item on your site, a web form and leave the default name (Default2.aspx). Add a label control on the form.

    5) Add a new item to your website, a global application class, Global.asax.

    6) In the Button1_Click event handling routine type,

    string team = TextBox1.Text;

    string colour = TextBox2.Text;

    Context.Items["team"]=team;

    Context.Items["colour"]=colour;

    Server.Transfer("Default2.aspx");

    I use the Items collection to store the user's preferences. 

    7) In the Page_Load event handling routine of the Default2.aspx page type, 

    string myteam = (string)Context.Items["team"];

    string mycolour = (string)Context.Items["colour"];

    Label1.Text = "My team is " + myteam + " my color is " + mycolour;

    Run your application and insert your favourite team and colour in the textboxes. Hit the button and you will see your preferences being printed on the screen.

    8) With Items state we can have data available to all our pages. We can do that by placing information when our application begins and then access the Items collection from an individual page.In the Global.asax page type,

    void Application_BeginRequest(object sender, EventArgs e)

    {

    Context.Items[
    "email"] = "info@mycompany.gr";

     

    }

    9) In the Page_Load event handling routine of the Default.aspx type,

    string email = (string)Context.Items["email"];

    Label1.Text = "My email is " + email;

    Run your application and you will see the email that was stored in the Items collection in the Application_BeginRequest being displayed on the screen.

    Using Items state is not to most obvious choice or the most popular one. Most developers I know have never used it to implement state management. But as everything in ASP.Net development has its place.

    Hope it helps!!!

    Read more...

  • State management using the Application class in ASP.Net applications

    I have explained some of the state mechanisms that we have in our disposal for preserving state in ASP.Net applications in various posts in this blog.

    You can have a look at this post , this post , this post and this one.

    I have not presented yet an example in using the Application class/object for preserving state within our application.

    Application state is available globally in an application.The way we access Application State is through the HttpApplication object's Application property.

    Let's move on to our hands on example.

    I assume that you have access to a version of SQL Server and Northwind database.

    If you do not, you can download and install the free SQL Server Express edition from here. If you need the installation scripts for the sample Northwind database, click here .

    1) Launch Visual Studio 2005,2008/2010. Express editions will work fine. I am using Visual Studio 2010 Ultimate edition.

    2) Create an empty asp.net web site. Choose an appropriate name. Choose C# as the development language.

    3) Add an item to your website, a web form.Leave the default name.Drag and drop a Gridview web server control on the form.

    4) Add a new item to your website, a global applicatio class, Global.asax.

    5) In the web.config add a new connection string that points to the database.In my case it looks like this,

    <connectionStrings> <add name="NorthwindConnectionString" connectionString="Data Source=USER-PC\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True" providerName="System.Data.SqlClient"/>

    </connectionStrings>

    6) In the Application_Start event of the Global.asax type

    DataTable MyCategories = new DataTable();

    string conn= ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].

    ConnectionString;

    SqlDataAdapter adapter = new SqlDataAdapter("SELECT CategoryName, Description from Categories", conn);

    adapter.Fill(MyCategories);

    Application["categories"] = MyCategories;

    I create a new datatable. Then I use the ConfigurationManager class to get the connection string.

    I create a new adapter object by passing the Sql statement and the connection string as parameters. Then I fill with data the datatable.

    Then I use the Application class to store in memory the datatable.I want to point out that the Application_Start will run the moment the application launches. So it will be available from the very first moments in the lifetime of our application.

    7) Now we need to get this datatable data that lives inside the "categories" application object in the memory and bind it to the Gridview

    In the Page_Load event handling routine of the default.aspx page type,

    DataTable categories = (DataTable)Application["categories"];

    GridView1.DataSource = categories;

    GridView1.DataBind();

    8) We just cast the Application object back to a DataTable object and simply bind it to the GridView control.

    In most ASP.Net application, Application state will not be the best solution to do things.In this particular example we could cache the datatable.

    I have observed in some ASP.Net applications that use Application state management functionality to have performance and scalability problems.

    In the case that have many concurrent users that need to access the data, using Application state management we should use the Lock and Unlock methods of the Application class.

    This will degrade performance and as more users want to access our application the performance will not be acceptable.

    Despite all that,it is good to know how to use the Application state mechanism.

    Hope it helps!!!!

    Read more...

  • Membership in ASP.Net applications - part 4

    This is the fourth post in a series of posts regarding ASP.Net built in membership functionality,providers,controls. You can read the first one  here .You can read the second post here . You can read the third post here.

    In this post I will show you how to add users programmatically to a role. In the third post we saw how to get users in a specific role.I will also show you how to delete a user and a role programmatically.

    1) Launch Visual Studio 2005,2008/2010. Express editions will work fine. I am using Visual Studio 2010 Ultimate edition.

    2) Create an empty asp.net web site. Choose an appropriate name. 

    3) Add an item to your website, a web form. Leave the default name.

    4) Now go to the Visual Studio menu and choose Website->ASP.NET configuration

    You will see a new web page loading. Refresh your solution in the Solution Explorerwindow. You will see the App_Data special folder added to your solution and inside the special folder you will see the ASPNETDB.MDF database.This is a SQL database.

    5) Go back to your web configuration web page that was loaded when we clicked theWebsite->ASP.NET configuration.Choose Forms Authetication

    6) Choose Security and enable roles. When you do that you will see changes in theweb.config file. A new line will be added.
    <roleManager enabled="true" />
    7)  Add a new role called e.g "friends".Now we must add some users to these roles.In the security tab (in the web environment), click "Create user". All this data is saved into the ASPNETDB.MDF database.

    I created a new user and added him to the friends role. Make sure you use a strong password with 7 characters or more containing at least one non-alphanumeric character.

     

    8) Create 2-3 more roles and 3-4 users and add them to those roles through the WAT(Web administration tool)

     

    9) Add a label,2 dropdown list,a bulleted list and a button control on the form.

     

    We will get the users and the roles we have so far and bind them to the dropdown list controls. In the Page_Load event handling routine type,

     

    if (!Page.IsPostBack)

    {

    DropDownList1.DataSource =
    Roles.GetAllRoles();

    DropDownList1.DataBind();

    DropDownList2.DataSource =
    Membership.GetAllUsers();

    DropDownList2.DataBind();

    }

     

    This is very easy code to follow.

     

    10) In the bulleted list control we will bind the users in the specific role when the user selects the role from the first dropdown list.

     

     protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)

    {

    BulletedList1.DataSource =
    Roles.GetUsersInRole(DropDownList1.SelectedItem.Text.ToString());

    BulletedList1.DataBind();

    }

     

    11) Now we need to select the role from the first dropdownlist control and the user from the second dropdownlist control.

     

    The user in the second dropdownlist control should not be a member of the role in the first dropdownlist control.

     

    In the Button1_Click() event handling routine type,

     

    try

    {

    Roles.AddUserToRole(DropDownList2.SelectedItem.Text.ToString(), DropDownList1.SelectedItem.Text.ToString());BulletedList1.DataSource = Roles.GetUsersInRole(DropDownList1.SelectedItem.Text.ToString());

    BulletedList1.DataBind();

    Label1.Text = "<em>" + DropDownList2.SelectedItem.Text.ToString() + "</em>" +

    " has been added to the " +

    "<em>" + DropDownList1.SelectedItem.Text.ToString() + "</em>" +

    " role";

    }

    catch (Exception ex)

    {

    Response.Write(ex.Message);

    }

     

     

    12) Run your application and select any role you want. All the users of the specified role will appear. Now select a role and a user that does not belong to the role. Hit the button. That user will be added to the role.

     

    13) Now we will see how to delete a user and a role using the Membership and Roles static classes.

     

    14) Add a new item to your site, a web form. Name it DeleteUser.aspx.

     

    Add a button, a label, a dropdowlist control on the form.

     

    15) We will create a void method to get all existing users.

     

    private void GetExistingUsers()

    {

    DropDownList1.DataSource =
    Membership.GetAllUsers();

    DropDownList1.DataBind();

    }

     

    In the Page_Load event handling routine type,

     

      if (!Page.IsPostBack)
            {

                GetExistingUsers();
            }

     

    16) In the Button1_Click() event handling routine type,

     

    try

    {

    Membership.DeleteUser(DropDownList1.SelectedItem.Text);

    Label1.Text = "<em>" + DropDownList1.SelectedItem.Text.ToString() + "</em>" +

    " has been deleted";

    GetExistingUsers();

    }

    catch (Exception ex)

    {

    Label1.Text = ex.Message;

    }

     

    I am using the DeleteUser method to delete the user.

     

    Run your application and select a user from the dropdownlist control. Hit the button. The selected user will be deleted.

     

    17) Let's do something very similar when deleting the role. Add a new item to your site, a web form. Name it DeleteRole.aspx

    I know we repeat some code in these posts but I think it will be of great benefit to people to type a few times the code.

     

    Add a button, a label, a dropdowlist control on the form.

     

    15) We will create a void method to get all existing users.

     

    private void GetExistingRoles()

    {

    DropDownList1.DataSource = Roles
    .GetAllRoles();

    DropDownList1.DataBind();

    }

     

    In the Page_Load event handling routine type,

     

      if (!Page.IsPostBack)
            {

                GetExistingRoles();
            }

     

    16) In the Button1_Click() event handling routine type,

     

    try

    {

    string[] myusers = Roles.GetUsersInRole(DropDownList1.SelectedItem.Text);

    int length = myusers.Length;

    if (length == 0)

    {

    Roles.DeleteRole(DropDownList1.SelectedItem.Text);

    Label1.Text = "<em>" + DropDownList1.SelectedItem.Text.ToString() + "</em>" +

    " has been deleted";

    GetExistingRoles();

    }

    else

    Label1.Text = "you cannot delete a role that has existing users attached to it";

    }

    catch (Exception ex)

    {

    Label1.Text = ex.Message;

    }

     

    I am using the DeleteRole method to delete the role.Before that I must check to see if there are any users under the role.

     

    Run your application and select a role from the dropdownlist control. Hit the button. The selected role will be deleted,unless it has users.

     

    Hope it helps!!!

    Read more...

  • Membership in ASP.Net applications - part 3

    This is the third post in a series of posts regarding ASP.Net built in membership functionality,providers,controls. You can read the first one post one here .

    You can read the second post here. In this post I would like to investigate how to use the Membership class methods to achieve the same functionality we have with the login web server controls.The login web server controls live inside the .aspx pages and access the underlying abstract membership classes to perform the desired functionality. We can access them directly when we do not want to have our users logged in/authenticated through the Login web server control.Some people will say that there is no point to do that. Well, we might want to implement some sort of bussiness logic when the user is validated.

    1) Launch Visual Studio 2005,2008/2010. Express editions will work fine. I am using Visual Studio 2010 Ultimate edition.

    2) Create an empty asp.net web site. Choose an appropriate name. 

    3) Add an item to your website, a web form. Leave the default name.

    4) Now go to the Visual Studio menu and choose Website->ASP.NET configuration

    You will see a new web page loading. Refresh your solution in the Solution Explorerwindow. You will see the App_Data special folder added to your solution and inside the special folder you will see the ASPNETDB.MDF database.This is a SQL database.

    5) Go back to your web configuration web page that was loaded when we clicked the Website->ASP.NET configuration.Choose Forms Authetication

    6) Choose Security and enable roles. When you do that you will see changes in the web.config file. A new line will be added.
    <roleManager enabled="true" />
    7)  Add a new role called e.g "friends".Now we must add some users to these roles.In the security tab (in the web environment), click "Create user". All this data is saved into the ASPNETDB.MDF database.

    I created a new user and added him to the friends role. Make sure you use a strong password with 7 characters or more containing at least one non-alphanumeric character.

    8) In the Default.aspx page I am going to use the LoginView control and the LoginStatus control.There are 2 templates,AnonymousTemplate and LoggedInTemplate. I place a LoginStatus control in the AnonymousTemplate.I place a LoginStatus control and the same LoginNamecontrol I had before in the  LoggedInTemplate.

    <asp:LoginView runat="server">

    <AnonymousTemplate>

    you are not logged in .

    <br />

    <asp:LoginStatus ID="LoginStatus1" runat="server" />

    </AnonymousTemplate>

    <LoggedInTemplate>

    You are logged in, <asp:LoginName ID="LoginName1" runat="server" /><br />

    <asp:LoginStatus ID="LoginStatus1" runat="server" />

    </LoggedInTemplate>

    </asp:LoginView>

    9) So far we have the same steps as in the previous steps. Now we will add another web form to the site and name it Login.aspx.

    We will not use the Login control.

    We will add 2 textboxes, a button and a label on the Login.aspx. The markup looks like this

    <form id="form1" runat="server">

    <div>

    Username<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><br />

    Password<asp:TextBox ID="TextBox2"

    runat="server" TextMode="Password"></asp:TextBox>

    </div>

    <p>

    <asp:Button ID="Button1" runat="server" Text="Log in" Height="26px"

    onclick="Button1_Click" />

    </p>

    <asp:Label ID="Label1" runat="server" Text="Failed!!!!" Font-Bold="true" Visible="False"></asp:Label>

    </form>

    10) In the Button1_Click event handler routine type

      if (Membership.ValidateUser(TextBox1.Text, TextBox2.Text))
            {
               
                FormsAuthentication.RedirectFromLoginPage(TextBox1.Text,false);
            }
         

          Label1.Visible=true;

    I use the ValidateUser() method to verify that the supplied username and password are valid.Then redirect the authenticated user to the originally requested page.

    Run your application and try to log in. Try first with the correct username and password. Then try with the wrong username or password.

    11) Now we will add a new page to our site.I name it GetRoles.aspx. We will get the roles that already exist and add a new role.

    12) We add a bulleted list control, a textbox control,a label control and a button control.The markup for the GetRoles.aspx looks like this.

    <form id="form1" runat="server">

    <div>

    <asp:BulletedList ID="BulletedList1" runat="server">

    </asp:BulletedList>

    </div>

    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

    <p>

    <asp:Button ID="Button1" runat="server" onclick="Button1_Click"

    Text="Create a new role" />

    </p>

    <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>

    </form>

     

    13) We create a simple void method to show the existing roles. We call this method from the Page_Load event handling routine.

    The method looks like this

    private void ShowRoles()

    {

    BulletedList1.DataSource =
    Roles.GetAllRoles();

    BulletedList1.DataBind();

    }

    In the Page_Load event handling routine we just call the method

    protected void Page_Load(object sender, EventArgs e)

    {

     if (!IsPostBack)
     
            
            ShowRoles();

    }

    Run the application and see the role(s) you created earlier.

    14) In the Button1_Click() event handling routine type,

    if (Roles.RoleExists(TextBox1.Text) == false)

    {

    Roles.CreateRole(TextBox1.Text);

    Label1.Text = TextBox1.Text +

    " :New role added";

    ShowRoles();

    }

    else

    {

    Label1.Text = TextBox1.Text +

    "You cannot add this role because it exists in our database";

    }

    Basically I am just using the various methods(RoleExists,CreateRole,GetAllRoles) of the Roles static class.

    Run the application,create a new role and see the new role added.

    15) Now we will add a new web form to the site and we will try to get the users that belong to a specified role.Name the new form UsersInRole.aspx

    16) We will add a button, a dropdownlist and bulletedlist control

    <form id="form1" runat="server">

    <div>

    </div>

    <asp:DropDownList ID="DropDownList1" runat="server">

    </asp:DropDownList>

    <p>

    <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />

    </p>

    <asp:BulletedList ID="BulletedList1" runat="server">

    </asp:BulletedList>

    </form>

    17) We will have a method that gets all the roles and bind them to the dropdownlist control.

    private void ShowRoles()

    {

    DropDownList1.DataSource =
    Roles.GetAllRoles();

    DropDownList1.DataBind();

    }

    In the Page_Load event handling routine we just call the method

    protected void Page_Load(object sender, EventArgs e)

    {

    ShowRoles();

    }

    18) In the Button1_Click() event handling routine type, BulletedList1.DataSource=Roles.GetUsersInRole(DropDownList1.SelectedItem.Text.

    ToString());

    BulletedList1.DataBind();

     

    Run your application and select from the dropdown list the role and click the button to see the users in that role.

    Hope it helps!!!

    Read more...

  • Membership in ASP.Net applications - part 2

    This is the second post in a series of posts regarding ASP.Net built in membership functionality,providers,controls. You can read the first one post one here .

    In order to follow this post, complete the steps in the first post. It will only take 10 minutes or so.

    1) Launch Visual Studio 2005,2008/2010. Express editions will work fine. I am using Visual Studio 2010 Ultimate edition.


    2) Follow all the steps in the first post of the series.

    3) Run your application to make sure it runs.

    4) Change the web.config file by commenting out these lines of code.

    <!--<authorization>

    <deny users="?"/>

    </authorization>
    -->

     

    5) In the Default.aspx page I am going to make some changes. I am going to use the LoginView control and the LoginStatus control.There are 2 templates,AnonymousTemplate and LoggedInTemplate. I place a LoginStatus control in the AnonymousTemplate.I place a LoginStatus control and the same LoginName control I had before in the  LoggedInTemplate.

    <asp:LoginView runat="server">

    <AnonymousTemplate>

    you are not logged in .

    <br />

    <asp:LoginStatus ID="LoginStatus1" runat="server" />

    </AnonymousTemplate>

    <LoggedInTemplate>

    You are logged in, <asp:LoginName ID="LoginName1" runat="server" /><br />

    <asp:LoginStatus ID="LoginStatus1" runat="server" />

    </LoggedInTemplate>

    </asp:LoginView>

     

    6) Run your application and the first time you try to access the default.aspx page you will see a link prompting you to log in. When you click on it you will be redirected to Login.aspx page where you can log in and if you are logged in successfully you will see your username and a link labelled "Logout".

    7) Let's add another item in our site, a web form.We will call it RecoverPassword.aspx. We want to provide a way for a user to recover the password in case he has forgotten it. Drag and drop a PasswordRecovery control on the form.

    There are 3 Views in this control, Username,Question,Success. You can fully configure this control and add you own text. In order for this control work you need to configure the smtp settings. You can do that from that the WAT tool.

    8) In the Login.aspx page we must add a link to RecoverPassword.aspx page.the We can do that by setting the property PasswordRecoveryText to forgot password? and PasswordRecoveryUrl to RecoverPassword.aspx

    9) Run your application again. Click on the link above that takes you to the RecoverPassword.aspx page.Follow the steps of the wizzard. You will get an error in the last step but this is due to the lack of configuration of the smtp settings.

    10) Now we need a way to let the user sign up to the site. Up to this point we created users from our WAT tool. Add another item to your site, a web form. Name it Register.aspx.

    Drag and drop a CreateUserWizard control on the form.You can configure this control from the properties. There are so many options in this control to set texts and styles.

    Set the ContinueDestinationPageUrl to Login.aspx page.

    11) In the Login.aspx page we must add a link to Register.aspx page.the We can do that by setting the property CreateUserText to Register and CreateUserUrl to Register.aspx

    Run your application and register with the site by creating a new user.

    12) We will modify the default.aspx page so we can add the functionality of changing the password when the user logs in.

    We will do that by adding a ChangePassword control to the LoggenInTemplate of the LoginView control.In my case the markup looks like that

    <asp:LoginView runat="server">

    <AnonymousTemplate>

    you are not logged in .

    <br />

    <asp:LoginStatus ID="LoginStatus1" runat="server" />

    </AnonymousTemplate>

    <LoggedInTemplate>

    You are logged in, <asp:LoginName ID="LoginName1" runat="server" /><br />

    <asp:LoginStatus ID="LoginStatus1" runat="server" />

    <br />

    <asp:ChangePassword ID="ChangePassword1" runat="server">

    </asp:ChangePassword>

    </LoggedInTemplate>

    </asp:LoginView>

    13) Run your application, log in, change the password and logout. Log in again with the new password.

    So what have we achieved so far?We managed to create a membership based portal without writing any code.Stay tuned for more posts on the isue

    Hope it helps!!!

    Read more...

  • Membership in ASP.Net applications - part 1

    So far in all my posts, I have never mentioned anything about how to implement authentication/authorisation mechanisms in a web site.  In all our professional web applications we do need some sort of mechanism to verify who users are and what privileges have in our site. 

    This is the first post in a series of posts investigating how to implement membership (authentication+authorisation) in ASP.Net applications.

    We will look into the built-in web server security controls.We will look at the built-in providers and the provider architecture.

    The membership and role providers were introduced in ASP.Net 2.0. Through that we can have role management,login functionality and many features out of the box like (password complexity,forgot your password,security question,password reset).

    So if you are looking for a RAD solution when it comes to membership you can use the out of the box membership model that ships out of the box since ASP.Net 2.0. The default membership and login controls are not ideal for any situation. It depends on the authentication/authorisation requirements of your application.

    I will start by showing you how to use the standard controls for a RAD of a membership web site.

    We will use a hands on example to demonstrate that, as always.Bear in mind this is a beginner level post.

    1) Launch Visual Studio 2005,2008/2010. Express editions will work fine. I am using Visual Studio 2010 Ultimate edition.

    2) Create an empty asp.net web site. Choose an appropriate name.

    3) Add an item to your website, a web form. Leave the default name.

    4) Add the following markup in the default.aspx page (inside the form element)

     You are 
            <asp:LoginName ID="myLoginName" runat="server" BackColor="Silver" 
                BorderColor="#CC3300" Font-Bold="True" ForeColor="Blue" />.
        Welcome to our home page!!!

     

     5) Now we have to make some changes to our rather (empty) web.config file.We want to have Forms authentication and deny all anonymous requests.Add the following lines in the configuration file.

     <authentication mode="Forms"></authentication>
          <authorization>
            <deny users="?"/>
          </authorization>

     

    At this point it is important to highight these

    • Default authentication is set to Windows
    • Default authorisation is set to allow anomymoys access. 

    6) Now we have to add another item in our website, another web form. This is going to be our Login page. Name it Login.aspx page. Drag and drop the Login web server control on the form.In my case the markup looks like this

       <asp:Login runat="server" BackColor="#E3EAEB" BorderColor="#E6E2D8" 
       BorderPadding="4" BorderStyle="Solid" BorderWidth="1px" Font-Names="Verdana" 
       Font-Size="0.8em" ForeColor="#333333" TextLayout="TextOnTop">
       <InstructionTextStyle Font-Italic="True" ForeColor="Black" />
       <LoginButtonStyle BackColor="White" BorderColor="#C5BBAF" BorderStyle="Solid" 
       BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em" ForeColor="#1C5E55" />
       <TextBoxStyle Font-Size="0.8em" />
       <TitleTextStyle BackColor="#1C5E55" Font-Bold="True" Font-Size="0.9em" 
       ForeColor="White" />
       </asp:Login>

    7) Now go to the Visual Studio menu and choose Website->ASP.NET configuration

    You will see a new web page loading. Refresh your solution in the Solution Explorer window. You will see the App_Data special folder added to your solution and inside the special folder you will see the ASPNETDB.MDF database.This is a SQL database.

    8) Go back to your web configuration web page that was loaded when we clicked the Website->ASP.NET configuration.

    Choose Security and enable roles. When you do that you will see changes in the web.config file. A new line will be added.

    <roleManager enabled="true" />
    9) Go back to the security page and add 2 new roles. I added "friends" and "Manager" as my two roles. 

    10) Now we must add some users to these roles.In the security tab (in the web environment), click "Create user". All this data is saved into the ASPNETDB.MDF database.

    I created a new user and added him to the friends role. Make sure you use a strong password with 7 characters or more containing at least one non-alphanumeric character.

    11)  We will create another user and add him to the Manager role.

    12)  Launch your site. You will see that instead of seeing the Default.aspx page you will be redirected to the Login.aspx page.Remember we do not want any anonymous requests. We have an authentication system set up with no code.That is pretty impressive.

    13) Try to login to your site using the credentials of the user that you have just created.As soon as we do that we are redirected to the Default.aspx page and our username is displayed to the page. In my case it displays

    "You are nikolaosk. Welcome to our home page!!!" 

    So we write no code and we have great functionality. When someone types some credentials in the Login control, the OnAuthenticate method is called.

    Then inside that method a call to the ValidateUser() method is made and under the hood a stored procedure is called (takes 2 paramaters : username,password) and that is how you are validated. The stored procedure and the tables are inside the ASPNETDB.MDF database. I urge you to have a look at the schema and data-objects of the ASPNETDB.MDF database.

    Basically a call is made to the current membership provider. The default provider is "AspNetSqlMembershipProvider".

    That is set up from the machine.config file. We can change that if we want by specifying another provider in our web.config file.

    14)  The way it works is like this.In the .aspx pages we add security controls or type our own custom code. These security controls know how to talk to the membership/role abstract classes.

    Inside the web.config file we can select the authetication,authorisation settings and other things like the provider (SQL provider e.t.c). You can write your own provider.

    I will continue with more posts on membership in ASP.Net.Stay tuned.

    Hope it helps!!!

     

     

    Read more...