| Styles | Masterpages | Usercontrols | Cookies | AJAX


SSE 698: Web Development

Project 3 (Summer 2010) - Course Syllabus

by Chris A. Bombardo

This project has grown substanially since project 2. As you can see from the screen shot a lot of pages have been added.

image31.jpg

Even the looks of many of the screens changed. Things as simple as the login screen now have customized look.

image35.jpg

With all of that said, I picked several areas to concentrate on for the paper. The areas covered include Styles, Masterpages, UserControls, Cookies and AJAX.

Styles


In project 2 I did not do much with styles. As the project progress styles have started to have a larger part of the project. Currently, there is now several places styles are intergrated into the project. The first is the manual upload page, which was talked about in project 2. The new places include the masterpages. Since the styles are so intergrated with the masterpages I will cover them there.

Masterpages


Masterpages was something completely new to me. I happened to come across them while researching something else. Though I have only been working with them for a week or so, masterpages is the best thing I have learned working on this project.

What is a masterpage? My definition of a masterpage is a template which defines the content areas and layout of the pages it is applied. In this project, thus far, I have created two masterpages. The first masterpage is for administrator and faculty pages. This masterpage will setup the feel and layout of the administrator and faculty pages. It contains the header, the footer, side menu, and main content area.
Once the four content areas are defined, the next step is to layout each of the areas with styles sheet. In this project the administator sheets will be called adminStyles.css.


body {
    font-family: Verdana;
    font-size: medium;
    margin: 0px;
}
 
h1, h2 {
    margin: 0px;
}
 
#topContent {
    text-align: right;
    background-color: #00008B;
    color: White;
    font-size: x-large;
    text-decoration: none;
    font-weight: bold;
    padding: 10px;
    height: 50px;
}
 
#topContent a {
    text-decoration: none;
    color: White;
}
 
#leftContent {
    width: 85px;
    padding: 10px;
    font-size: 90%;
    text-align: left;
    position: absolute;
    top: 60px;
    margin-top: 10px;
    left: 0px;
}
 
#leftContent h3 {
    text-transform: uppercase;
    letter-spacing: 2px;
    text-align: center;
    border-top: dotted 1px #660;
    border-bottom: dotted 1px #660;
}
 
#mainContent {
    text-align: left;
    margin-left: 120px;
    padding: 10px;
}
 
#footerContent {
    text-align: center;
    padding: 5px;
 


As you can see in the styles sheet control the font, margins, alignment, padding, borders, location and so forth of each section in the masterpage. The masterpage layout used in this project is based on the tutorial provied by www.asp.net.

The next setp is the asp portion of the masterpage:

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="AdminMasterPage.master.cs" Inherits="AdminMasterPage" %>
 
<!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>Electronic Bluebook Exam System Administrator</title>
    <asp:ContentPlaceHolder id="head" runat="server">
    </asp:ContentPlaceHolder>
 

We need to apply the styles to the page:

<link href="~/resources/styles/adminStyles.css" rel="stylesheet" type="text/css" />
</head>
<body>
 

Next we will layout the form on the masterpage:

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

Top Content:


        <div id="topContent">
            <a href="/admin/ebbmain.aspx">Electronic Bluebook<br />
            <font size="1" face="Verdana">by CompuTest, LLC</font></a>
        </div>
 

Main Content:


        <div id="mainContent">
             <asp:ContentPlaceHolder id="MainContent" runat="server">
            </asp:ContentPlaceHolder>
        </div>
 

Left Menu:


        <div id="leftContent">
            <p style="text-align: center;">
                <asp:Label ID="DateDisplay" runat="server"></asp:Label>
            </p>
 
            <h3>Task</h3>
                <asp:Repeater ID="side_menu" runat="server">
                <ItemTemplate>
                <li>
 

In this project the menu items are going to be stored in a database. This will make it easier to add and remove menu items. In the long run it will also make it possible for the user to customize the menu items. This means we need to create a asp.Repeater, create a hyperlink, and bind the data to the link. The asp repeater will do this for each of the items returned in the SQLDataReader, which will be touched on later.

                <asp:HyperLink id= "HyperLink2"
                    runat="server"
                    Font-Size="Smaller"
                    ForeColor="#0000CC"
                    Font-Names="verdana"
                    NavigateUrl= '<%#"~/admin/" + DataBinder.Eval(Container.DataItem, "url") + "?TaskID=" + DataBinder.Eval(Container.DataItem,"menu_category_ID")%>'>
                     <%#DataBinder.Eval(Container.DataItem, "menu_name")%>
                </asp:HyperLink>
                </li>
            </ItemTemplate>
        </asp:Repeater>
 

Next we put in secondary menu. It has two static links to home and logout, plus an additional data repeater to pull links from the database. In the database the links are given and menu_id to identify which menu each links should be placed.

            <h3>Misc.</h3>
               <li>
                 <asp:HyperLink id= "HyperLink1"
                    runat="server"
                    Font-Size="Smaller"
                    ForeColor="#0000CC"
                    Font-Names="verdana"
                    NavigateUrl="~/admin/ebbmain.aspx">
                     Home
                </asp:HyperLink>
               </li>
 
 
   <asp:Repeater ID="side_menu2" runat="server">
                <ItemTemplate>
                <li>
                <asp:HyperLink id= "HyperLink2"
                    runat="server"
                    Font-Size="Smaller"
                    ForeColor="#0000CC"
                    Font-Names="verdana"
                    NavigateUrl='<%#"~/admin/" + DataBinder.Eval(Container.DataItem, "url") + "?TaskID=" + DataBinder.Eval(Container.DataItem,"menu_category_ID")%>'>
                     <%#DataBinder.Eval(Container.DataItem, "menu_name")%>
                </asp:HyperLink>
                </li>
                <li>
                 <asp:HyperLink id= "HyperLink3"
                    runat="server"
                    Font-Size="Smaller"
                    ForeColor="#0000CC"
                    Font-Names="verdana"
                    NavigateUrl="~/logout.aspx">
                     Logout
                </asp:HyperLink>
                </li>
            </ItemTemplate>
        </asp:Repeater>
        </div>
 

Finally, we come to the footer content.

        <div id="footerContent">
            <img src="~/resources/images/footer.gif" alt="Powered by ASP.NET!" />
        </div>
    </form>
</body>
</html>
 

Once the asp is complete the final stop is to complete any C# code behind the masterpage. There are several here.


using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Diagnostics;
 
public partial class AdminMasterPage : System.Web.UI.MasterPage
{
 

First we need to create a data connectors. Continued from project two we can tie into the dataControl class.

    dataControl myDataControl;
 
    protected void Page_Load(object sender, EventArgs e)
    {
 

This is going to be a roll specfic page, so in the page load I do not want the user to be able to use the back button. To stop the page from caching the code below was added. If the user's session cookie (covered later) is out of date the page will send the user back to the login page. The session cookie may be out-dated if the user logged out or if the session was left open too long without activity.

        Response.Expires = 0;
        Response.Cache.SetNoStore();
        Response.AppendHeader("Pragma", "no-cache");
 

Next, on the page load we are going to verify the user has the correct permission level to view the page. The permission level is pulled from the database when the user logs in and then stored encrypted in the cookie. Each time the user visits a protected page it is first check with forms authentication then check the permission level on the page load. If the permission level is null or underrated currently the user is pushed back to the login page.

        if(Request.Cookies["PermLevel"] != null)
        {
 

I had the System.Diagnostics referenced and using the writing to the immediate window to verify the proper permission level was being pulled from the cookie.

Debug.Write(Server.HtmlEncode(Request.Cookies["PermLevel"].Value));
 

Currenty I am checking 2 permission levels at this page with a nested if statement. It probably needs to be changed to remove the nested if. I could use a > 1. However, I am still developing the different permission level possibilites.

            if (Server.HtmlEncode(Request.Cookies["PermLevel"].Value).ToString() != "3")
            {
                if (Server.HtmlEncode(Request.Cookies["PermLevel"].Value).ToString() != "2")
                {
                    Response.Redirect("~/EBBLogon.aspx", true);
                }
            }
        }
 

Since I wanted to display the date on every page, I can easily place it in the masterpage.

        DateDisplay.Text = DateTime.Now.ToString("dddd, MMMM dd");
 

Now to building the side menus. In the administrator page even though I have two different users with permissions to view the page I needed different side menus based on permissions (ex. a faculty member should not be able to create a user, but an administrator should.)

DATA


        myDataControl = new dataControl();
 

Open a data connection

        myDataControl.Open_Data_Con();
 

If the permission level is set to administrator run the selected SQL query. If it is anything other than three we have a different SQL statement.

        if (Server.HtmlEncode(Request.Cookies["PermLevel"].Value).ToString() == "3")
        {
            side_menu.DataSource = myDataControl.ReadDataSet("Select menu_category_id, menu_name, url from side_menu where (permissionLevel = 1) OR permissionLevel = 2");
        }
        else
        {
            side_menu.DataSource = myDataControl.ReadDataSet("Select menu_category_id, menu_name, url from side_menu where permissionLevel = 2");
        }
 

Bind the data to the datarepeater (side_menu).

        side_menu.DataBind();
        myDataControl.Close_Connection();
 

Get the second side menu and bind the data.

        myDataControl.Open_Data_Con();
        side_menu2.DataSource = myDataControl.ReadDataSet("Select menu_category_id, menu_name, url from side_menu where permissionLevel = 3");
        side_menu2.DataBind();
        myDataControl.Close_Connection();
 
    }
}
 

Now we have completed the current masterpage.


image32.jpg


Similar to the administrator masterpage I created a student masterpage. The student masterpage is nearly identical to the administrator at the time, with the exception of different menu identifies.

Now the masterpage is complete it is time to visit the actual asp. The original goal was to place a form on each page. The problem with this is there would have been so many pages it might have been more difficult to manage them. So after a little research the user of usercontrols came into play.

Usercontrols


Many of the pages were very similar with only slight changes in the input form displayed to the user. Instead of hiding and showing individual components I created a usercontrol for each of the forms a page may display. Then I would display the proper usercontrol in the main contain of the page. This did several things, first is limited the number of pages I needed to create. It made editing\modifing the project much easier. It provides for a more organized and readable project.
To start 10 usercontrols were created. We will look at the editStudent.

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="editStudent.ascx.cs" Inherits="controls_editStudent" %>
 

The user control simple contains a base form:

Edit Student:&nbsp;
<asp:TextBox ID="userid" runat="server" Visible="False" Width="25px"></asp:TextBox>
<br />
<br />
<asp:Label ID="Label1" runat="server" Text="First Name:"></asp:Label>
 
&nbsp;
<asp:TextBox ID="firstname" runat="server"></asp:TextBox>
&nbsp;&nbsp;
 
<asp:Label ID="Label2" runat="server" Text="Last Name:"></asp:Label>
 
&nbsp;
<asp:TextBox ID="lastname" runat="server" TabIndex="1"></asp:TextBox>
<br />
<br />
 
&nbsp;
<br />
 
<asp:Label ID="Label3" runat="server" Text="Email:"></asp:Label>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<asp:TextBox ID="email" runat="server" TabIndex="2"></asp:TextBox>
 
&nbsp;&nbsp;
 
<asp:Label ID="Label4" runat="server" Text="Username:"></asp:Label>
 
&nbsp;<asp:TextBox ID="username" runat="server" TabIndex="3"></asp:TextBox>
 
<br />
<br />
<asp:Label ID="Label5" runat="server" Text="Password"></asp:Label>
&nbsp;&nbsp;&nbsp;
<asp:TextBox ID="password" runat="server" TabIndex="4" TextMode="Password"></asp:TextBox>
&nbsp;&nbsp;
<asp:Label ID="Label6" runat="server" Text="Verify Password"></asp:Label>
&nbsp;<asp:TextBox ID="verifypassword" runat="server" TabIndex="5"
    TextMode="Password"></asp:TextBox>
&nbsp;<br />
<br />
<br />
<asp:Button ID="Button1" runat="server" Text="Save Changes" Height="40px"
    Width="94px" onclick="Button1_Click" TabIndex="6" />
 


image34.jpg



The C# sharp code behind the user control writes the data to the database on the on_click event. There still needs to be a text validation written to verify no junk data is trying to be wrote to the database. The validation also needs to make sure someone is not trying to SQL inject, even within the administrator login.

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
 
public partial class controls_editStudent : System.Web.UI.UserControl
{
    dataControl myDataControl;
 
    protected void Page_Load(object sender, EventArgs e)
    {
 
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
 

Grab the data class.

        myDataControl = new dataControl();
        myDataControl.Open_Data_Con();
 


Write the data to the database.

        myDataControl.WriteData("UPDATE students SET first_name = '" + firstname.Text + "', last_name = '" + lastname.Text + "', email = '" + email.Text + "' Where user_id = " + userid.Text);
        myDataControl.WriteData("UPDATE users SET username = '" + username.Text + "', password = '" + password.Text + "' Where user_id = " + userid.Text);
        myDataControl.Close_Connection();
    }
}
 

Now to use the usercontrol. We will look at editUser.aspx. The first thing is to register the userControl.

<%@ Page Title="" Language="C#" MasterPageFile="~/resources/masterpages/AdminMasterPage.master" AutoEventWireup="true" CodeFile="edituser.aspx.cs" Inherits="admin_editstudent" %>
 

On the editUser we are going to register 3 user controls. The correct one will show based on the users selection.

<%@ Register  TagPrefix="EBBControl" Tagname="editStudent"  Src="~/controls/editStudent.ascx" %>
<%@ Register  TagPrefix="EBBControl" Tagname="editFaculty"  Src="~/controls/editFaculty.ascx" %>
<%@ Register  TagPrefix="EBBControl" Tagname="editAdministrator"  Src="~/controls/editAdministrator.ascx" %>
 

Next, to load the header of the masterpage.

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
 

After the header is the MainContent, which will contain our data.

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server">
 
 <h2>Edit User:</h2>
<p>&nbsp;</p>
<p>&nbsp;</p>
 

We will add two DropDownList. The first one the user will select the user type. After selecting the user type the code will load the second DropDownList with all the users with the selected type. Next the user will be selected and the user control will be displayed.

Here is the DropDownList 1

        <asp:DropDownList ID="DropDownUserType" runat="server" Width="170px"
        onselectedindexchanged="DropDownUserType_SelectedIndexChanged"  AutoPostBack="true" >
        </asp:DropDownList>
 
    <p>
 

image36.jpg


Here is the DropDownList 2

        <asp:DropDownList ID="DropDownUsers" runat="server" Width="170px"
        onselectedindexchanged="DropDownUsers_SelectedIndexChanged" AutoPostBack="true" >
        </asp:DropDownList>
 
    </p>
        <br />
        <br />
        <br />
 


image37.jpg


Loading of the user controls. Notice they are all marked as visiable = false.

        <EBBControl:editStudent ID="editStudent" Runat="server" Visible="false" > </EBBControl:editStudent>
        <EBBControl:editFaculty ID="editFaculty" Runat="server" Visible="false" > </EBBControl:editFaculty>
        <EBBControl:editAdministrator ID="editAdministrator" Runat="server" Visible="false" > </EBBControl:editAdministrator>
</asp:Content>
 


image33.jpg


Now the C# code in the editUser.aspx

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
 
public partial class admin_editstudent : System.Web.UI.Page
{
    dataControl myDataControl;
    int userType = 0;
 
    protected void Page_Load(object sender, EventArgs e)
    {
 
        if (!IsPostBack)
        {
 

First, we will load all of our user types into the first dropdownlist on page load.

            myDataControl = new dataControl();
            SqlDataReader myReader;
            myDataControl.Open_Data_Con();
            myReader = myDataControl.ReadDataSet("Select * from user_types ORDER BY userType");
 
            this.DropDownUserType.DataSource = myReader;
            this.DropDownUserType.DataTextField = "userName";
            this.DropDownUserType.DataValueField = "userType";
            this.DropDownUserType.DataBind();
            this.DropDownUserType.SelectedValue = "0";
        }
    }
 

When the user makes a change in dropdownlist1 dropdownlist2 is updated with all the users based dropdownlist1 user type selected.

    protected void DropDownUserType_SelectedIndexChanged(object sender, EventArgs e)
    {
        myDataControl = new dataControl();
        SqlDataReader myReader;
        myDataControl.Open_Data_Con();
        myReader = myDataControl.ReadDataSet("Select * from users where accountType = " + Convert.ToInt32(this.DropDownUserType.SelectedValue));
 
        this.DropDownUsers.DataSource = myReader;
        this.DropDownUsers.DataTextField = "username";
        this.DropDownUsers.DataValueField = "user_id";
        this.DropDownUsers.DataBind();
        this.DropDownUsers.Items.Insert(0, new ListItem(String.Empty, String.Empty));
        this.DropDownUsers.SelectedIndex = 0;
    }
 

Next, when the user selects a user the proper user control is displayed and the data is populated.

    protected void DropDownUsers_SelectedIndexChanged(object sender, EventArgs e)
    {
        userType = Convert.ToInt32(this.DropDownUserType.SelectedValue);
        switch (userType)
        {
 
            case 1: //Student
                ShoweditStudent();
                HideeditFaculty();
                HideeditAdministrator();
                populateEditForm(editStudent);
                break;
            case 2: //Faculty
                HideeditStudent();
                ShoweditFaculty();
                HideeditAdministrator();
                populateEditForm(editFaculty);
                break;
            case 3: //Administrator
                HideeditStudent();
                HideeditFaculty();
                ShoweditAdministrator();
                populateEditForm(editAdministrator);
                break;
            default:  //None
                HideeditStudent();
                HideeditFaculty();
                HideeditAdministrator();
                break;
        }
    }
 

Showing the usercontrols.

    void ShoweditStudent()
    {
 
        if (editStudent.Visible == false)
            editStudent.Visible = true;
    }
    void ShoweditFaculty()
    {
        if (editFaculty.Visible == false)
            editFaculty.Visible = true;
    }
    void ShoweditAdministrator()
    {
 
        if (editAdministrator.Visible == false)
            editAdministrator.Visible = true;
    }
 

Hiding the non-used usercontrols.

    void HideeditStudent()
    {
        if (editStudent.Visible == true)
            editStudent.Visible = false;
    }
    void HideeditFaculty()
    {
        if (editFaculty.Visible == true)
            editFaculty.Visible = false;
    }
    void HideeditAdministrator()
    {
        if (editAdministrator.Visible == true)
            editAdministrator.Visible = false;
    }
 

Populate the usercontrols form fields.

    void populateEditForm(UserControl userControl)
    {
        myDataControl = new dataControl();
        SqlDataReader myReader = null;
        myDataControl.Open_Data_Con();
 
        if (userType == 1)
            myReader = myDataControl.ReadDataSet("SELECT students.first_name, students.last_name, students.email, users.username, users.password, users.lastlogin FROM students INNER JOIN users ON students.user_id = users.user_id WHERE(users.user_id = " + Convert.ToInt32(this.DropDownUsers.SelectedValue) + ")" );
        if (userType == 2)
            myReader = myDataControl.ReadDataSet("SELECT faculty.first_name, faculty.last_name, faculty.email, users.username, users.password, users.lastlogin FROM faculty INNER JOIN users ON faculty.user_id = users.user_id WHERE(users.user_id = " + Convert.ToInt32(this.DropDownUsers.SelectedValue) + ")" );
        if (userType == 3)
            myReader = myDataControl.ReadDataSet("SELECT administrator.first_name, administrator.last_name, administrator.email, users.username, users.password, users.lastlogin FROM administrator INNER JOIN users ON administrator.user_id = users.user_id WHERE(users.user_id = " + Convert.ToInt32(this.DropDownUsers.SelectedValue) + ")");
 
        TextBox firstname = (TextBox)userControl.FindControl("firstname");
        TextBox lastname = (TextBox)userControl.FindControl("lastname");
        TextBox email = (TextBox)userControl.FindControl("email");
        TextBox username = (TextBox)userControl.FindControl("username");
        TextBox password = (TextBox)userControl.FindControl("password");
        TextBox verifypassword = (TextBox)userControl.FindControl("verifypassword");
        TextBox userid = (TextBox)userControl.FindControl("userid");
 
        userid.Text = this.DropDownUsers.SelectedValue.ToString();
 
        while (myReader.Read())
        {
            firstname.Text = (string)myReader["first_name"];
            lastname.Text = (string)myReader["last_name"];
            email.Text = (string)myReader["email"];
            username.Text = (string)myReader["username"];
            password.Attributes["value"] = (string)myReader["password"];
            verifypassword.Attributes["value"] = (string)myReader["password"];
        }
 
        myDataControl.Close_Connection();
    }
}
 


Cookies


Since cookies have been talked about several times above, I wanted to briefly touch on the writing of the cookie. This code resides on the EBBLogon.aspx.cs. Once a user is authenticated the a cookie is created, as covered in project 2. However, the change here is the permission level is stored in the cookie.

        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, username, DateTime.Now
            , DateTime.Now.AddMinutes(30), isPersistent, userData, FormsAuthentication.FormsCookiePath);
 
        // Encrypt the ticket.
        string encTicket = FormsAuthentication.Encrypt(ticket);
 
 

First, we need to get the permission level from the database, which we can grab from the accountType table based on the username – note: it may be more stable to pull the data with the user_id key.

        int permLevel = 0;
        SqlDataReader myDataSet;
        mydataControl.Open_Data_Con();
        myDataSet = mydataControl.ReadDataSet("Select accountType from users where username='" + username + "'");
 
 
        while (myDataSet.Read())
        {
            permLevel = Convert.ToInt32(myDataSet[0]);
        }
 

Once the data is a in a variable we can write it to the cookie.

        // Create the cookie.
        Response.Cookies["PermLevel"].Value = permLevel.ToString();
        Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
 

Next, to send the user to the correct page. As noted above the page the user goes to will re-evaulate the permission level to verify the user has permission to load the page.

        switch (permLevel)
        {
            case 1: //Student
                Response.Redirect("student//ebbmain.aspx");
                break;
 
            case 2: //Faculty
                Response.Redirect("admin//ebbmain.aspx");
                break;
 
            case 3: //Admin
                Response.Redirect("admin//ebbmain.aspx");
                break;
 
            default: //Unknown
                break;
        }
 

Exceptions to forms authentication:


One of the changes additions to project two I wanted to point out was the addition of exceptions to the forms authentication. By defaults forms authentication requires every page to be authenticated before access. In this project there was several pages authentication was not needed. Additionally, there have been issues reported with forms authentication and styles. This brought a need to have exception to the forms authentication.

The first exception was the automatic upload page. This page the EBB application talks to and at this time authentication is not needed. To make an exception we will use the location tag in the web.Config file. The path can be the relative path the a file or folder.

    <location path="EBBAUpload.aspx">
        <system.web>
            <authorization>
 


We will allow all users.

                <allow users="*"/>
            </authorization>
        </system.web>
    </location>
 


Then we will move on to the next item. Authentication rules are read in order. So the deny must be place prior to the the exceptions.

    <location path="EBBMUpload.aspx">
        <system.web>
            <authorization>
                <allow users="*"/>
            </authorization>
        </system.web>
    </location>
    <location path="resources/images">
        <system.web>
            <authorization>
                <allow users="*"/>
            </authorization>
        </system.web>
    </location>
    <location path="resources/styles">
        <system.web>
            <authorization>
                <allow users="*"/>
            </authorization>
        </system.web>
    </location>
 

Masterpages are suppose to have an automatic exception, however, I figured if I placed it in the exceptions I would be able to keep track of all the exceptions.

    <location path="resources/masterpages">
        <system.web>
            <authorization>
                <allow users="*"/>
            </authorization>
        </system.web>
    </location>
 

AJAX


The final portion of the program I am working on for the class is creating collapsable panels. I wanted to be able organize the main content of the page displayed to the user in several categories such as user profile, course tied to the user profile, and exams tied to the coures and user profile. After researching this for a while collapsalbe panels seemed to be the best looking and most functional. The user will be able to expand one the panel for the select users and see the information within the panel.

Using AJAX within asp was something I have never done nor seen. This is an ok example and and some information at http://www.asp.net/ajaxlibrary/act_CollapsiblePanel.ashx. I used the example to get a start, it is not completed yet, to adding collapsible panels to this project.
All of the code is controlled in the asp. This is after you add the Ajax Control Toolkit to the project. The tool kit must be added to the asp special folder Bin. In this project I added the .Net 3.5 version because it is what the project is based on.
Now to the asp code. The code is to be added to the aspx page needed to show the collapsible panel. In this case it is the editUser.aspx. The edit user will have three collapsible panels, which means 6 total panels. A collapsible panel is a combiniation of two panels. The first panel is the title panel, it contains the title and action buttom for the collapsible panel. The second panel is the actual panel which expands or collapsise based on the clicking of the action button.

<%@ Page
    Language="C#"
    MasterPageFile=" ~/resources/masterpages/AdminMasterPage.master "
    AutoEventWireup="true"
    Inherits="CommonPage"
    Title="Electron Bluebook Exam System" %>
 
<%@ Register  TagPrefix="EBBControl" Tagname="editStudent"  Src="~/controls/editStudent.ascx" %>
<%@ Register  TagPrefix="EBBControl" Tagname="editFaculty"  Src="~/controls/editFaculty.ascx" %>
<%@ Register  TagPrefix="EBBControl" Tagname="editAdministrator"  Src="~/controls/editAdministrator.ascx" %>
 

Notice we are registering the Ajax control tool kit now.

<%@ Register
    Assembly="AjaxControlToolkit"
    Namespace="AjaxControlToolkit"
    TagPrefix="ajaxToolkit" %>
 
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
 
 
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server">
 

In side of the mainContent we start the ajax. The first line is setup the script.

<ajaxToolkit:ToolkitScriptManager runat="Server" ID="ScriptManager1" />
 

In the title panel is called panel2 here.

        <asp:Panel ID="Panel2" runat="server" CssClass="collapsePanelHeader" Height="30px">
            <div style="padding:5px; cursor: pointer; vertical-align: middle;">
 
Give the title panel a caption.
 
[[code format="asp"]]
 
<div style="float: left;">User Profile div>
<div style="float: left; margin-left: 20px;">
<asp:Label ID="Label1" runat="server">( Edit User Profile...)</asp:Label>
</div>
<div style="float: right; vertical-align: middle;">
 

The image controls the click.

<asp:ImageButton ID="Image1" runat="server" ImageUrl="~/images/expand_blue.jpg" AlternateText="(Edit User Profile...)"/>
</div>
</div>
</asp:Panel>
 

Panel1 is now our content panel. It will contain the usercontrols (forms) for editing the users in this case.

<asp:Panel ID="Panel1" runat="server" CssClass="collapsePanel" Height="0">
<br />
<p>
<h2>Edit User:</h2>
<p>&nbsp;</p>
<p>&nbsp;</p>
 
<asp:DropDownList ID="DropDownUserType" runat="server" Width="170px"
onselectedindexchanged="DropDownUserType_SelectedIndexChanged"  AutoPostBack="true" >
</asp:DropDownList>
 
<p>
 
<asp:DropDownList ID="DropDownUsers" runat="server" Width="170px"
onselectedindexchanged="DropDownUsers_SelectedIndexChanged" AutoPostBack="true" >
</asp:DropDownList>
 
</p>
<br />
<br />
<br />
 
<EBBControl:editStudent ID="editStudent" Runat="server" Visible="false" > </EBBControl:editStudent>
<EBBControl:editFaculty ID="editFaculty" Runat="server" Visible="false" > </EBBControl:editFaculty>
<EBBControl:editAdministrator ID="editAdministrator" Runat="server" Visible="false" > </EBBControl:editAdministrator>
 
</p>
</asp:Panel>
</div>
 

Finally, we close the panel and set the options for expanding followed by collapising.

<ajaxToolkit:CollapsiblePanelExtender ID="userProfile_exp" runat="Server"
TargetControlID="Panel1"
ExpandControlID="Panel2"
CollapseControlID="Panel2"
Collapsed="True"
TextLabelID="Label1"
ImageControlID="Image1"
ExpandedText="(Hide Details...)"
CollapsedText="(Show Details...)"
ExpandedImage="~/images/collapse_blue.jpg"
CollapsedImage="~/images/expand_blue.jpg"
SuppressPostBack="true"
SkinID="CollapsiblePanelDemo" />
 
</asp:Content>
 

The program is not completed, but I have learned a great deal working through the program as a project.