A day with .Net

My day to day experince in .net

Archive for July, 2009

State management in ASP.NET Part-2

Posted by vivekcek on July 29, 2009

2. Hidden Field
Hidden fields are just input fields that are embedded in HTML tag that is not visible to user. Hidden fields stores information of a single page like view state.
3. Cookies
A cookie is a small amount of data stored in client side, and passed with all page requests. There are two types of cookies persistent and temporary. Persistent cookies are stored in client side as a text file, and these cookies will not be destroyed even if the user shut down the system. So these cookies are used in a later time. But the temporary cookies are stored in browsers memory, which will be active for the current session only. For using cookies you have to add the System.Net name space.
An example code to implement Remember me feature in your login

Using System.Net;  

protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            HttpCookie cookie = Request.Cookies["mycookie"];

            if (cookie != null)
            {
                string s = cookie["uname"].ToString();
                if (s == "vivek")
                {
                    Response.Redirect("Default2.aspx");
                }
            }
        }
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        HttpCookie cookie = new HttpCookie("mycookie");
        cookie["uname"] = txtCookie.Text;
        cookie.Expires = DateTime.Now.AddYears(1);
        Response.Cookies.Add(cookie);
    }

In the above code

cookie.Expires = DateTime.Now.AddYears(1);

Specifies the scope of cookie,Another properties avilable for setting cookie scope are.

cookie.Value=DateTime.Now.ToString();
cookie.Path="/MyFolder";
cookie.Domain="mysite.com";

4.Query String
Adding query string to URL from page1.aspx

Response.Redirect(page2.aspx?qid=" + 123 + "&tId=" + 34);

Acessing the query strings in page2.aspx

 string key = Request.QueryString["qid"];
 string _Tid = Request.QueryString["tId"]; ;

4. Application State
The ASP.NET application variables are not user specific. Application variables are initialized when the application started and destroys when server is restarted or IIS restarted. You can declare an application variable at the Application Start method in Global.asax file. Application variables are normally used to count application hits and finding number of users online.

protected void Page_Load(object sender, EventArgs e)
    {
        Application.Lock();
        int count = 0;
        if (Application["hit"].ToString() != string.Empty)
        {
            count = Convert.ToInt32(Application["hit"]);
        } 
            count++;
            Application["hit"] = count;
            Response.Write(count);
            Application.UnLock();
    }

 void Application_Start(object sender, EventArgs e) 
    {
        Application["hit"] = "";

    }

5.Session State

Session variables are user specific.Applicable to a single session,They are also declared in Global.asax as.

void Session_Start(object sender, EventArgs e) 
    {
        Session["uname"] = "";

    }

Every client that accesses the application has a different session and a distinct collection of information.it forces the web server to store additional information in memory. This extra memory requirement,even if it is small, can quickly grow to performance-destroying levels as thousands of clients access the site.

ASP.NET tracks each session using a unique 120-bit identifier

Advertisements

Posted in MCTS ASP.NET 3.5 | 1 Comment »

State Management in ASP.NET-Part 1

Posted by vivekcek on July 28, 2009

State management in ASP.NET concerns with tracking the user state in the application. Two types of state management in ASP.NET are client-side state management and server-side state management.
In the case of client side state management data is stored in user’s browser cache, or in browser cookies. But in the case of server side state management state is stored in server memory or in a database.
Various techniques used in state management are.
1: View State
View state is the default mechanism used by asp.net to store user specific request response data between page requests.
The Page.ViewState property returns a dictionary object for storing values in multiple requests of the same page.
When an asp.net page is processed the state of the page and its controls is hashed into a string and stored in a hidden field named _VIEWSTATE.

<input Type=”Hidden” name=”_VIEWSTATE” id=”_VIEWSTATE” value=”/jkhsdjkahdjsh5765”/>

View state is not secure; view state can be encrypted by ViewStateEncryptionMode property of a page
This will affect performance due to encryption and decryption. The view state encryption for an entire page can be set by the following code in the web.config file

<Configuration>
</system.web>
<pages ViewStateEncryptionMode=”always”/>
</system.web>
<Configuration>

Adding data to view state


this.ViewState.Add(“key”,”mydata”);

Retrieve data from view state

String myData=(string)ViewState[“key”];

The following code demonstrates a page that uses view state. It allows the user to save a set of values
(all the text that’s displayed in all the text boxes of a table) and restore it later. This example uses
recursive logic to dig through all child controls, and it uses the control ID for the view state key,
because this is guaranteed to be unique in the page.

protected void Button1_Click(object sender, EventArgs e)
    {
        SaveAllText(TABLE1.Controls, true);
        txtName.Text = "";
        txtPhone.Text = "";
    }

    private void SaveAllText(ControlCollection controls, bool saveNested)
    {

        foreach (Control control in controls)
        {
            if (control is TextBox)
            {
                // Store the text using the unique control ID.
                ViewState[control.ID] = ((TextBox)control).Text;
            }
            if ((control.Controls != null) && saveNested)
            {
                SaveAllText(control.Controls, true);
            }
        }
    
    }
    protected void Button2_Click(object sender, EventArgs e)
    {
        RestoreAllText(TABLE1.Controls, true);
    }
    private void RestoreAllText(ControlCollection controls, bool saveNested)
    { 
       foreach (Control control in controls)
           {
               if (control is TextBox)
                  {
                     if (ViewState[control.ID] != null)
                             ((TextBox)control).Text = (string)ViewState[control.ID];
                  }
                if ((control.Controls != null) && saveNested)
                 {
                     RestoreAllText(control.Controls, true);
                 }
           }
     }

Posted in MCTS ASP.NET 3.5 | Leave a Comment »

MCTS 70-562 Introduction

Posted by vivekcek on July 28, 2009

Yes today onwards i am starting a free training for MCTS 70-562 paper,70-562 includes the web application development with ASP.NET 3.5.Each day i will try to post some abstract of topics specified by Microsoft for this exam. I have no plan to cover the topic in syllabus order beginners please excuse me because this post will be helpful for guys having 1 year experience asp.net.Also I have latest dumps for all 3,5 frame work also e books of self paced training kits.

Posted in MCTS ASP.NET 3.5 | Leave a Comment »

Back up/Restore SQL SERVER 2000 database using SQLDMO.DLL

Posted by vivekcek on July 24, 2009

So in the previous post i discussed about how attach .mdf file to sql server 2000 by using sqldmo.dll.Now i am discussing about how back up and restore sql server databse using sqldmo.

The UI and code is given below.UI include one open file dialog and save file dialog.

BACKRESTORE

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using SQLDMO;
using System.Xml;
using System.Data.SqlClient;
namespace eStock
{
    public partial class frmBackUp : Form
    {
        private string server, uid, pwd, database;
        public frmBackUp()
        {
            InitializeComponent();
        }

        private void frmBackUp_Load(object sender, EventArgs e)
        {
           Getinfo();
           txtServer.Text=  server; 
           txtUid.Text= uid; 
           txtPwd.Text= pwd;
           txtDatabase.Text= database;

        }
       private void Getinfo()
        {
            try
            {
                XmlTextReader xmlreadr = new XmlTextReader("config.xml");
                xmlreadr.WhitespaceHandling = WhitespaceHandling.None;
                xmlreadr.MoveToContent();
                XmlReader readr = xmlreadr;
                server = readr.ReadElementString();
                uid = readr.ReadElementString();
                pwd = readr.ReadElementString();
                database = readr.ReadElementString();
                readr.Close();

            
            
            }
           catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
           }
        
        }

        private void cmdBackupRestore_Click(object sender, EventArgs e)
        {
            if (this.rdbBackUp.Checked)
            {
                Backup();
            }
            else
                Restore();
            
        }

        private void Backup()
        {
            try
            {
                this.Cursor = Cursors.WaitCursor;
                //create an instance of a server class
                SQLDMO._SQLServer srv = new SQLDMO.SQLServerClass();
                //connect to the server
                srv.Connect(this.txtServer.Text, this.txtUid.Text, this.txtPwd.Text);
                //create a backup class instance
                SQLDMO.Backup bak = new SQLDMO.BackupClass();
                //set the backup device = files property ( easy way )
                bak.Devices = bak.Files;
                //set the files property to the File Name text box
                bak.Files = this.txtFile.Text;
                //set the database to the chosen database
                bak.Database = this.txtDatabase.Text;
                //perform the backup
                bak.SQLBackup(srv);
                MessageBox.Show("Database successfully backed up.", "Backup Successfull");
                this.Cursor = Cursors.Default;
            }
            catch (Exception err)
            {
                this.Cursor = Cursors.Default;
                MessageBox.Show(err.Message, "Error");
            }
        }

        private void Restore()
        {
           
            try
            {
                SqlConnection.ClearAllPools();
                this.Cursor = Cursors.WaitCursor;
                
                //create an instance of a server class
                SQLDMO._SQLServer srv = new SQLDMO.SQLServerClass();
                //connect to the server
                srv.Connect(this.txtServer.Text, this.txtUid.Text, this.txtPwd.Text);
                //create a restore class instance
                SQLDMO.Restore res = new SQLDMO.RestoreClass();
                //set the backup device = files property ( easy way )
                res.Devices = res.Files;
                //set the files property to the File Name text box
                res.Files = this.txtFile.Text;
                //set the database to the chosen database
                res.Database = this.txtDatabase.Text;
                // Restore the database
                res.ReplaceDatabase = true;
                res.SQLRestore(srv);
                MessageBox.Show("Database restored successfully,Restart eStock.", "Restore Successfull");
                this.Cursor = Cursors.Default;
            }
            catch (Exception err)
            {
                this.Cursor = Cursors.Default;
                MessageBox.Show(err.Message, "Error");
            }
        }

        private void cmdFile_Click(object sender, EventArgs e)
        {
            if (this.rdbBackUp.Checked)
            {
                //backup
                this.saveFileDialog1.ShowDialog();
                if (this.saveFileDialog1.FileName != "")
                    this.txtFile.Text = this.saveFileDialog1.FileName;
            }
            else
            {
                //restore
                this.openFileDialog1.ShowDialog();
                if (this.openFileDialog1.FileName != "")
                    this.txtFile.Text = this.openFileDialog1.FileName;
            }
        }

        private void rdbBackUp_CheckedChanged(object sender, EventArgs e)
        {
            this.cmdBackupRestore.Text = "Back Up";
        }

        private void rdbRestore_CheckedChanged(object sender, EventArgs e)
        {
          this.cmdBackupRestore.Text = "Restore";
        }
    }
}

Posted in c#.net | 6 Comments »

Attaching .mdf file to sql server 2000 using SQLDMO.DLL

Posted by vivekcek on July 24, 2009

Ya in the application for my shop that i described in the previous post,actually my client was my uncle in oman,the application was for his elctronic shop there,I helped him to install SQL SERVER 2000 via chatting on his PC,But he dont know attching database restoring operations.So i need to attch the databse associated with my application when it first time load after installtion.Ya there are some methods to install and attch database using the setup program and sql expree,i will explained it later.So now come to topic.

You can download SQLDMO.DLL freely by some google serch then add a refrence to this dll
Then the UI and code is explained below.
Attach
Be free to ask ny doubts related it

I n this after attching the database to server i create an XML file and stores the SQLSERVER connection information for future use

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using SQLDMO;
using System.Xml;

namespace eStock
{
    public partial class frmAttachDatabase : Form
    {
        private xmlop XmlObj;
        // Create an SQLDMO application 
        SQLDMO.Application sqlApp = new SQLDMO.ApplicationClass();
        // Create an Server, which resembles to your actual server
        SQLDMO.SQLServer srv = new SQLDMO.SQLServerClass(); 
        public frmAttachDatabase()
        {
            InitializeComponent();
        }

        private void frmAttachDatabase_Load(object sender, EventArgs e)
        {
            
        }

        private void cmdAttach_Click(object sender, EventArgs e)
        {
            if (txtDatabase.Text != string.Empty && txtServer.Text != string.Empty && txtUid.Text != string.Empty)
            {
                try
                {
                    srv.Connect(this.txtServer.Text, this.txtUid.Text, this.txtPwd.Text); 
                    srv.AttachDB(txtDatabase.Text.Trim(), "[" +System.Windows.Forms.Application.StartupPath + @"\eStock.mdf]");
                    CreateConnectionString();
                    XmlObj = new xmlop();
                    ConString.cons = XmlObj.GetConString();
                    this.Close();
                    
                }

                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }

            }
            else 
            {
                MessageBox.Show("Server Name,User Name,Database Name are required");
            }
        }

        private void CreateConnectionString()
        {

            XmlTextWriter xmlwritr = new XmlTextWriter("config.xml", Encoding.ASCII);
            xmlwritr.Formatting = Formatting.Indented;
            xmlwritr.WriteStartDocument();
            xmlwritr.WriteComment("Making any cahnges to this file cause application error");
            xmlwritr.WriteStartElement("ConnectionString");
            xmlwritr.WriteElementString("server", txtServer.Text);
            xmlwritr.WriteElementString("uid", txtUid.Text);
            xmlwritr.WriteElementString("pwd", txtPwd.Text);
            xmlwritr.WriteElementString("database", txtDatabase.Text);
            xmlwritr.WriteEndElement();
            xmlwritr.WriteEndDocument();
            xmlwritr.Flush();
            xmlwritr.Close();

        
        
        }

        private void cmdClose_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.Application.Exit();
        }
    
    }

}

Posted in c#.net | Leave a Comment »

Storing connection string in XML and read it

Posted by vivekcek on July 23, 2009

When i was developing an inventory for my shop i done this code,about 1 year ago,Now i am just documenting it from old source files avilable in my recycle bin.

The XML file I used to hold SQL server info was like this

<?xml version="1.0" encoding="us-ascii" ?> 
- <!-- Making any cahnges to this file cause application error
  --> 
- <ConnectionString>
  <server>(local)</server> 
  <uid>sa</uid> 
  <pwd /> 
  <database>eStock</database> 
  </ConnectionString>

And the c# code to read this given below

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace eStock
{
    class xmlop
    {
        public string cons=string.Empty,server,uid,pwd,database;
        public string GetConString()
        {
            try
            {
                XmlTextReader xmlreadr = new XmlTextReader("config.xml");
                xmlreadr.WhitespaceHandling = WhitespaceHandling.None;
                xmlreadr.MoveToContent();
                XmlReader readr = xmlreadr;
                server = readr.ReadElementString();
                uid = readr.ReadElementString();
                pwd = readr.ReadElementString();
                database = readr.ReadElementString();
                readr.Close();
                cons = "server=" + server + ";uid=" + uid + ";pwd=" + pwd + ";database=" + database;
                return cons;


            }
            catch (Exception ex)
            {
                 return(ex.Message);
            }
            
        
        }

    }
}

Posted in c#.net | Leave a Comment »

SSL in ASP.NET

Posted by vivekcek on July 23, 2009

SSL is the standard protocol to secure communications of web sites and applications. If you are developing your application using ASP.NET on a windows server, making the necessary configurations for SSL is not very difficult.

Unfortunately, while trying to accomplish this task at work, I discovered there isn’t one good source of information to get the whole job done.

In this series of (about) three posts I will try to get you up to speed on everything you need to do and how it’s done.

So, on to part one: “What is SSL and How Do We Create a Certificate?”. Let’s go.

A Short Intro on SSL

(Ugly oversimplification coming at you)

SSL is the standard protocol for (1)authenticating one or both parties and (2)encrypting communication between the parties.

Authentication is accomplished by a party presenting a valid certificate.

Encryption is accomplished in two steps:

Negotiating encryption key(s).
Encrypting communication using the negotiated key.

Setting up SSL for an ASP.NET App

The basic steps to do this are:

Obtaining a certificate for use by the server.
Configuring IIS.
(Optional) Enforcing the use of SSL by creating a redirection mechanism in IIS and ASP.NET.

Usually, it’s desired to create the setup at the development stage so you will be able to develop, debug and test your application in the same structure it will exist come production-time. So, in this post I will explain the whole setup for you developer station (referred to as localhost).

Obtaining a Server Certificate

What’s a certificate? A certificate is simply a character string that contains the public key of some entitiy (like your server) signed by a third party. Presenting a valid certificate guarantees to the person who wants to communicate with you that you are who you claim you are (think drivers license).

To have SSL working in the real world you need to buy a certificate from an Authorized Certification Authority (CA) like Verisign, for example. An authorized CA is an organization that is recognized (“trusted”) by client software (the web browser you’re using, for example). Continuing with the driver’s license metaphor, the CA in that case is the state government that issues the license.

A verified certificate costs money and is only valid for the specific machine it was issued to, so for development and testing purposes you can create your own “self-signed” certificate.

On a side note, the fellows over at Verisign are basically charging people 1,500 USD for a short string in a file. Talk about a sweet and sustainable business model – no advertising revenue required, thank you very much.

Introducing makecert.exe

Luckily, on a Windows mcahine you can use the makecert command-line utility to create a self-signed certificate.

It has a s**t-load of arguments, so here is the minimal command you need to run on the machine that hosts the application:

makecert -pe -n “CN=localhost” -ss my -sr localMachine -sky exchange

The interesting bits are:

-n “CN=localhost” : creates the certificate suitable for use by server “localhost”. Remember that every certificate is server-specific.
-ss my : places the certificate in the “personal” certificates folder.

Last argument deserves a word: to view all certificates installed on your machine – use the Certificates MMC snap-in. Choose “local computer” and you are presented with various “stores” which are basically folders of certificates. To consume a certificate in IIS you need it to reside in the “personal” store of local computer.

There are additional useful arguments to the makecert utility, but the basic ones I presented will get you up an running. If you can see a certificate named “localhost” in your personal certificates store you are doing fine so far.

Stay tuned for the next part, where I will cover configuring IIS for SSL support using the certifcate we created.

This is the second part in an article series about setting up SSL in an ASP.NET application.

You can read the first part here. Go ahead, read it now.

Okay.

Now, that we’ve created an SSL certificate for testing and development purposes, we are ready to make the required configuration in IIS.

Setting Up IIS to Work with SSL

First thing we have to do is configure the web site to use the certificate we created:

From the IIS MMC snap-in, select your web site, right-click “properties” and under “directory security” click “Server Certificate…”.
Click “Assign an existing certificate”. You should be able to see the self-signed certificate you created. Select it and finish the wizard.

At this state IIS is able to respond to SSL HTTP requests with this certificate.

To test that everything is okay, try to navigate to an existing URL in your application, with https in the beginning of the URL.

Forcing SSL for an application

If your application requires SSL encryption for all traffic you want to force the application to only handle SSL requests.

You can do this on the application level (so that other applications on the same web site in IIS will not require SSL) or on the web site level.

Here’s how:

In IIS MMC, right click the application virtual directory or the web site.
Select “Directory Security” tab and click “Edit…”.
Check “Require secure channel” and “Require 128-bit encryption”.

Now, any request to a URL that starts with http and not https – will receive a 403.4 error from the web server.

Supporting Debugging in Visual Studio

Now that you’ve setup the web server on your machine to require SSL traffic, you need to update the application URL in Visual Studio in order to be able to run the application from Visual Studio:

Right click the project in Solution Explorer and select “Properties”.
Under the “Web” tab change the value of “Project Url” to start with https.

Auto-Redirecting non-SSL Traffic

Perhaps some of your users will try to navigate to your application via a non SSL URL (most users assume a web page URL starts with http).

You can silently redirect your users to the correct SSL address using the following technique:

Users trying to reach a non-SSL URL will be automatically redirected by IIS to the standard 403.4 error page. First step is to change that page to your own page:

In your project, create a new web form called “NonSslRedirect.aspx”.
In IIS MMC, right click your application virtual directory, click the “Custom Errors” tab and select the 403;4 error.
Click “Edit Properties…”, select “URL” in “Message Type” and type the address of the page you added in step 1 (for example: /MyApp/NonSslRedirect.aspx).

Try again to navigate to a URL starting with http. You should be redirected by IIS to NonSslRedirect.aspx.

Now, in the code-behind file of NonSslRedirect.aspx, add code similar to the following to automatically redirect the users to the matching SSL URL:

protected void Page_Load(object sender, EventArgs e)

{

string originalUrl = Request.Url.ToString().Split(new char[1] { ';' })[1];

string urlWithHttps = "https" + originalUrl.Substring(4);

Response.Redirect(urlWithHttps);

}

This code will replace the http prefix in the requested URL with an https prefix and redirect the user to new URL.

Posted in Asp.net | 1 Comment »

Opening a page in a pop up’s parent window or in it’s grand parent window

Posted by vivekcek on July 22, 2009

Today i faced a problem,The problem was that open a link in a pop up windows parent window
this can be done the following javascript functions

In parent


window.opener.parent.location ='../../folder/folder/somepage.aspx?tId='+TrId;

In grand parent

window.opener.opener.parent.location ='../../folder/folder/somepage.aspx?tId='+TrId;

Posted in Asp.net | Leave a Comment »

Binding formated data to gridview by Bind()

Posted by vivekcek on July 22, 2009

<asp:GridView ID="ccGvAdv" runat="server" AutoGenerateColumns="False" CellPadding="4"
                            CssClass="grid" DataKeyNames="ccr_CurrencyExchangeRateID" GridLines="None" Width="100%"
                            AllowPaging="True" OnPageIndexChanging="ccGvAdv_PageIndexChanging" OnRowDataBound="ccGvAdv_RowDataBound">
                            <PagerSettings NextPageText="NextPage" PreviousPageText="PreviousPage" />
                            <Columns>
                                <asp:BoundField DataField="cur_Name" HeaderText="Currency" />
                                <asp:TemplateField HeaderText="Updated Date&amp;Time">
                                    <ItemTemplate>
                                        <asp:Label ID="Label2" runat="server" Text='<%# Bind("ccr_DateTime","{0:dd MMM-yyy HH:mm:ss}") %>'></asp:Label>
                                    </ItemTemplate>
                                </asp:TemplateField>
                                <asp:TemplateField HeaderText="Original Rate">
                                    <ItemTemplate>
                                        <asp:Label ID="Label1" runat="server" Text='<%# Bind("ccr_OriginalRate","{0:#.##}")  %>'></asp:Label>
                                    </ItemTemplate>
                                </asp:TemplateField>
                                <asp:TemplateField HeaderText="ISV Charges">
                                    <ItemTemplate>
                                        <asp:Label ID="Label1" runat="server" Text='<%# Bind("InterserveCharge")  %>'></asp:Label>
                                    </ItemTemplate>
                                </asp:TemplateField>
                                <asp:TemplateField HeaderText="Summed Rate">
                                    <ItemTemplate>
                                        <asp:Label ID="Label2" runat="server" Text='<%# Bind("ccr_Rate","{0:#.##}")  %>'></asp:Label>
                                    </ItemTemplate>
                                </asp:TemplateField>
                            </Columns>
                            <AlternatingRowStyle CssClass="grid_row_alternate" />
                            <HeaderStyle CssClass="grid_row_header" />
                            <FooterStyle CssClass="grid_row_footer" />
                            <RowStyle CssClass="grid_row_normal" />
                            <PagerStyle CssClass="grid_row_pager" />
                        </asp:GridView>

Posted in Asp.net | Leave a Comment »

Using skin in asp.net

Posted by vivekcek on July 22, 2009

A skin is a definition of styles applied to the server controls in your ASP.NET page.
Skins can work in conjunction with CSS files or images.
The skin file can have any name, but it must have a .skin file extension.
The Summer.skin file.

<asp:Label Runat="server" 
           ForeColor="#004000" 
           Font-Names="Verdana"
           Font-Size="X-Small" />

<asp:Textbox Runat="server" 
             ForeColor="#004000" 
             Font-Names="Verdana"
             Font-Size="X-Small" 
             BorderStyle="Solid" 
             BorderWidth="1px"
             BorderColor="#004000" 
             Font-Bold="True" />

<asp:Button Runat="server" 
            ForeColor="#004000" 
            Font-Names="Verdana"
            Font-Size="X-Small" 
            BorderStyle="Solid" 
            BorderWidth="1px"
            BorderColor="#004000" 
            Font-Bold="True" 
            BackColor="#FFE0C0" />

Control definitions must contain the Runat=”server” attribute.
No ID attribute is specified in the skinned version of the control.
Using the Summer theme in an ASP.NET page.

skin

Posted in Asp.net | Leave a Comment »