Hostingheaderbarlogoj
Join InMotion Hosting for $3.49/mo & get a year on Tuts+ FREE (worth $180). Start today.
Advertisement

ASP.NET for PHP Developers

by
Gift

Want a free year on Tuts+ (worth $180)? Start an InMotion Hosting plan for $3.49/mo.

This tutorial, for PHP developers, will provide you with an introduction to ASP.NET using the C# language. If you've wondered what ASP.NET is about, this tutorial will strive to answer at least some of your questions. Even if you're an ardent open-source fan, ASP.NET contains some techniques and features that are useful to know about. And, as some might say, it's good to know your enemy!


Before you Start

ASP.NET is no longer a Microsoft-only technology. Thanks to the hard work of the Mono project contributors, ASP.NET can be used on Linux and Mac platforms, as well as Windows.

They've even created an IDE within which you can write your web and desktop applications. Download a copy of MonoDevelop and install it. We'll be using that IDE for this tutorial, as it offers some useful features to speed up development time. However, just like PHP, ASP.NET applications can be written in nothing more complex than a text editor.


ASP.NET and C# at a Glance

ASP.NET is Microsoft's web development technology framework, and was originally designed as a replacement for the old Active Server Pages technology. If you've used classic ASP (normally using VBScript) you'll find parts of ASP.NET very familiar. ASP.NET can be used with a wide range of programming languages, including VB.NET (the new version of Visual Basic), J# and C#. This tutorial will be using C#.

ASP.NET is available in two flavours:

  • ASP.NET WebForms: the original framework allowing developers to create web applications using many of the same techniques used in .NET Windows desktop applications
  • ASP.NET MVC: a newer framework offering Model-View-Controller architecture and more control over client-side code

As this tutorial is aimed at PHP developers, who a lot of the time prefer to get "closer to the metal," I won't be using either of these. Instead, I'll be rolling my own application based on the features of the .NET runtime and C# languages, with ASP.NET as a wrapper, rather than a framework as it was intended to be. Don't worry if that doesn't make sense, just continue with the tutorial and you'll see what I mean.

I'm also running MonoDevelop in Xubuntu Linux, but it should work the same on other platforms.

Important: ASP.NET is very much built on object-oriented programming (OOP). If you have no experience with OOP I strongly suggest you read this introduction to OOP in PHP. You'll need to understand words like "class", "instance", "method", "property" and "inherit".


Five Things to Watch Out For

C# can confuse PHP developers, especially if you switch between the two languages on a regular basis. Here's my top five gotchas.

String concatenation

In C# string concatenation is done with "+" rather than ".".

// PHP
"This is part 1 " . "and this is part 2!";
// C#
"This is part 1 " + "and this is part 2!";

Referencing class methods and properties

To call a method or property in PHP you'd use:

$myclass = new MyClass();
$var = $myclass->var;
$myclass->doMethod();

In C# you use a "." instead of "->", like this:

MyClass myclass = new MyClass();
string var = myclass.var;
myclass.doMethod();

Strong typing

C# is a strongly-typed language, so you can't, for example, just treat strings as integers like you can in PHP. In PHP, this is true:

"1" == 1

In C# it would cause an error. You need to convert one of the elements:

Convert.ToInt32("1") == 1

Or:

"1" == 1.ToString()

You'll find yourself using that .ToString() method a lot...

  • Methods return types

    With PHP, the type of the return value of a function or method doesn't matter. In C# methods must declare the type of value they return:

    protected string MyStringMethod()
    {
    	return "I am a string";
    }
    protected int MyIntMethod()
    {
    	// return an int
    	return 100;
    }

    Methods that don't return anything must have the void keyword:

    protected void MyMethod() {  }

    Scope

    Watch out for the scope of methods and properties. The three important keywords are "public", "protected" and "private". These work the same as they do in PHP.

    // this is public, can be called from anywhere
    public int MyInt;
    // this is protected, can only be called by the declaring class and any descendents
    protected int MyInt;
    // this is private, can only be called by the declaring class
    private int MyInt;

    Creating your first ASP.NET Page

    Open MonoDevelop.

    MonoDevelop

    Choose "Start a New Solution" in the main screen. A "solution" is a collection of one or more related projects. They can be projects of different types, for example a web application and a desktop application that works with it, and perhaps a web service as well.

    Create a new solution

    Select C# ASP.NET Web Application, type a name for your application (I'm using "WebApplication1") and choose a location for your solution then click "Forward". Ignoring the options on the next page, click "OK" and a new ASP.NET application will be created at the location you specified.

    The IDE will open the default page, called "Default.aspx" and you'll see the following code:

    <%@ Page Language="C#" Inherits="WebApplication1.Default" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html>
    <head runat="server">
    	<title>Default</title>
    </head>
    <body>
    	<form id="form1" runat="server">
    		<asp:Button id="button1" runat="server" Text="Click me!" OnClick="button1Clicked" />
    	</form>
    </body>
    </html>

    You'll see it's mostly standard HTML, with a few extra bits. There's already a <form> element with a strange <asp:Button> element inside it. Let's try running the application.

    Running your Application in Debug Mode

    MonoDevelop can run your ASP.NET application with one button. Rather than having to set up a local development server and configure your app, simple press F5. A development server will be launched on a non-standard port and you'll see your application open in a browser. Note port 8080 in the URLs below.

    Note: In Xubuntu I had to manually install the Mono web server named XSP2 with this command: sudo apt-get install mono-xsp2.

    So, press F5 to run the application, you'll hopefully see a browser window open that looks like this.

    Default page

    Clicking the button shows this.

    Default page - button clicked

    What you've just done is clicked an ASP.NET button, which automatically wires-up events to server-side code. In other words, when the button is clicked the page knows about it - this is one of the main advantages of the WebForms framework, it works much like desktop application development. But we're not going to use this feature as it leads to a world of pain (which is explained in Part 2 of this tutorial). Instead we're going to do things a little more manually. It's the PHP way.

    So, we're going to change this code slightly as we don't want to use the WebForms framework. Edit the opened "Default.aspx" by removing the <form> element and adding a <h1> element so the code is:

    <%@ Page Language="C#" Inherits="WebApplication1.Default" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html>
    <head runat="server">
    	<title>Default</title>
    </head>
    <body>
    	<h1>This is the text</h1>
    </body>
    </html>

    Browsing your Solution

    On the left hand side of the IDE there are three views of the application. The first view is Classes, and shows the class diagram of the application.

    View of the application classes

    The second view is Solution, and shows the projects and files which comprise the entire solution (you can have multiple projects in a solution).

    View of the solution

    And there's also a Files view which shows you all the directories and files in the solution, including the "WebApplication1.csproj" file which is the C# project file for our application.

    View of the files

    Choose the Solution view. You've already got "Default.aspx" open, which is the page you've just edited. Double-click the file called "Default.aspx.cs" to open it in the IDE. Here's the first important lesson.

    Code-behind Files

    The "Default.aspx.cs" file is a code-behind file. Rather than peppering your .html (or in this case .aspx, and for PHP applications .php) files with server-side code, it's possible in ASP.NET to put all your server-side code in a code-behind file. In the same way you don't have to put all your CSS and JavaScript in every HTML page but can put them in separate files which are included, you can do that with ASP.NET code.

    The neat thing is these code-behind files are automatically included in your .aspx page. (That's why the code-behind is called "Default.aspx.cs", so it is associated with the "Default.aspx" file.) The code of "Default.aspx.cs" is pretty short. Here's an explanation, line-by-line:

    // reference the System namespace
    using System;
    // reference the System.Web namespace
    using System.Web;
    // reference the System.Web.UI namespace
    using System.Web.UI;
    // put this class in the WebApplication1 namespace
    namespace WebApplication1
    {
    	// declare a new partial class called "Default" which inherits (":") from System.Web.UI.Page
    	public partial class Default : System.Web.UI.Page
    	{
    		// NOTE: we're going to delete this method
    		// declare a public void method which is called when button1 is clicked
    		public virtual void button1Clicked (object sender, EventArgs args)
    		{
    			// set the text 
    			button1.Text = "You clicked me";
    		}
    	}
    }
    A Note About Namespaces

    Wikipedia defines a namespace as:

    a namespace is an abstract container providing context for the items (names, or technical terms, or words) it holds and allowing disambiguation of homonym items having the same name (residing in different namespaces)

    Which is pretty complicated. I mean, homonym? I see namespaces as virtual directories for classes. Just as in a file system you can't have two files called "test.txt" in the same folder, you can't have two classes with the same name in a single namespace. Namespaces can be nested, just like directories (hence the System, System.Web, System.Web.UI references in the code above) and have to be referenced from your ASP.NET code-behind files so you can use the classes contained in them.

    You'll also have noticed that our application is in the namespace WebApplication1, which means any code we write is within that namespace. We'll use that to our advantage later on.

    A Note About Pages

    In ASP.NET, a web page is actually a class. It belongs in a namespace in a project, and inherits from the System.Web.UI.Page class. In the code-behind file this is expressed as:

    public partial class Default : System.Web.UI.Page { ... }

    (The "Partial" keyword means that part of this class is also in another file, namely the "Default.aspx.designer.cs" file. As that file is automatically-created and maintained we don't need to worry about it.)

    Your "Default.aspx" inherits from the page we've just created, using this code:

    <%@ Page Language="C#" Inherits="WebApplication1.Default" %>

    In the "Page" declaration we're setting the language for the page and the class it inherits from, in this case WebApplication1.Default. That means that if we create another page, for example "Contact.aspx", the "Page" declaration and code-behind file would be:

    // code-behind file
    public partial class Contact : System.Web.UI.Page { ... }
    // .aspx page
    <%@ Page Language="C#" Inherits="WebApplication1.Contact" %>

    This can be hard to get your head round to start with, but by the time you've created a few pages it will be second nature.

    Creating Some Custom Functionality

    We're now ready to write something ourselves. Remove the "button1Clicked" method and in it's place add the following code:

    protected void Page_Load(object sender, EventArgs e)
    {
    
    }

    The "Page_Load" method is one of several life-cycle events that get automatically called when the page's Load event fires. There are quite a few events that happen in the life-cycle of an ASP.NET page, see the full list here. Generally the "Page_Load" method is where you put anything you want to happen when that page is loaded (security checks, fetching data from a database for display, loading an advert etc.). We're going to declare a new method for the page called "SetText" which is called from the "Page_Load" method;

    protected void Page_Load(object sender, EventArgs e)
    {
    	SetText();
    }
    
    protected void SetText()
    {
    	headertext.InnerHtml = "This is the changed text";
    }

    You can guess this sets the "InnerHtml" property on the element "headertext" to "This is the changed text". But what is "headertext"? Go back to "Default.aspx" and modify the <h1> element to this:

    <h1 id="headertext" runat="server">This is the header</h1>

    Then press F5 to run the application. If everything works OK you should see this:

    Header text changed

    Check the source of the page. You'll see the runat="server" attribute has gone. What just happened? We turned an HTML control into a server-side control, that's what.

    Server-side Controls

    My favourite feature of ASP.NET by far is the ability to turn almost any standard HTML control (elements are also known as controls) into a server-side control. This means that ASP.NET knows what the control is, and can change its properties and run methods on it from the code-behind page. In our example above, the <h1> element had two attributes added:

    <h1 id="headertext" runat="server">This is the text</h1>

    Now in our code-behind file ("Default.aspx.cs") we could access the control and change its properties.

    headertext.InnerHtml = "This is the changed text";

    One of the best features of using an IDE such as MonoDevelop rather than a text editor is Intellisense, which gives you a menu of options as you type. Properties of objects, system classes and methods, custom classes and methods, it's all there:

    Intellisense

    (I believe "Intellisense" may be a Microsoft trademark, but I'm unsure what MonoDevelop call it!)

    There are loads of other properties available for different controls (for example an input type="text" control has a "value" property), and they all appear in a list as you type. There's also a massively useful property called Visible. This sets whether the control is visible in the source. Look at this example:

    <div id="notloggedin" runat="server">
    	<h1>You are not logged in</h1>
    	<p>Please <a href="/login">log in to the site here</a>.</p>
    </div>
    
    <div id="loggedin" runat="server" visible="false">
    	<h1>Thanks, you've logged in</h1>
    	<p>Welcome back, user!</p>
    </div>

    Notice I've manually added the visible="false" for the loggedin element. When used with this server-side code we can make each <div> control visible or invisible.

    protected void Page_Load(object sender, EventArgs e)
    {
    	User currentuser = new User();
    	currentuser.CheckSecurity();
    	if (currentuser.IsLoggedIn)
    	{
    		notloggedin.Visible = false;
    		loggedin.Visible = true;
    	}
    }

    You can imagine how easy that makes configuration of pages, and how much cleaner your code can be.

    How about form elements? Let's make a <select> control server-side:

    <select name="genre" id="genre" runat="server">
    	<option value="1">Jazz</option>
    	<option value="2">Blues</option>
    	<option value="3">Rock</option>
    	<option value="4">Pop</option>
    	<option value="5">Classical</option>
    </select>

    Selecting a particular option is as easy as this:

    int chosengenre = 4;
    genre.Items.FindByValue(chosengenre.ToString()).Selected = true;

    Told you you'd use the ToString() method a lot. The <select> control Items property also has a useful method called FindByText() which does this:

    string chosengenre = "Blues";
    genre.Items.FindByText(chosengenre).Selected = true;

    Intellisense will even give you a list of controls it finds, so you don't even need to remember what you called all those different text boxes. As we're using normal HTML controls converted to be server-side (rather than true ASP.NET controls) we lose some functionality, but nothing we can't live without. In Part 2 of the tutorial we'll be using a true ASP.NET control. But first, a word about configuration.


    The Web.config File

    In your PHP applications you have not doubt had a configuration file named "config.php" or similar. ASP.NET has a special file type for configuration files called ".config" which are automatically disabled from public view. Your ASP.NET application already has a "Web.config" file, open it from the Solution view in MonoDevelop.

    Web.config file

    You'll see it's a standard XML file. We're going to add some application-wide settings, so edit the file adding this code just above </configuration>

      <appSettings>
        <add key="ApplicationName" value="My first ASP.NET Application"/>
        <add key="Developer" value="Chris Taylor"/>
      </appSettings>

    Going back to our "Default.aspx.cs" file we reference the System.Configuration namespace:

    using System;
    using System.Web;
    using System.Web.UI;
    using System.Configuration;

    And we can now access our "ApplicationName" setting using:

    ConfigurationSettings.AppSettings["ApplicationName"];

    So to jazz things up a bit, let's try:

    headertext.InnerHtml = "Welcome to " + ConfigurationSettings.AppSettings["ApplicationName"] + " by " + ConfigurationSettings.AppSettings["Developer"];

    F5 to run the application and you'll see:

    Application settings in use

    As you'll appreciate, this gives you a huge amount of power over site-wide settings.


    Sessions, Cookies and Post/Get Parameters

    You can't get very far developing web applications without dealing with Sessions, Cookies and Post or Get parameters. ASP.NET handles these pretty well, with a couple of gotchas.

    Sessions

    To get the session ID use: Session.SessionID. Warning: if you don't store anything in the session the SessionID property *may* change on every page request. Yes, I know, it's madness. The fix is to store something in the session.

    To store something in the session use: Session["var"] = "value";.

    To retrieve something from the session use: string value = Session["var"];.

    Cookies

    To store something in a cookie use: Response.Cookies["name"].Value = "value";.

    To retrieve something from a cookie use: string value = Request.Cookies["name"].Value;.

    Note the different use of Request and Response and the fact you have to set the Value property. You can also set other properties of each cookie (check Intellisense for full details):

    Request.Cookies[0].Domain = "http://domain.com";
    Request.Cookies[0].Expires = DateTime.Now.AddMonths(1);
    Request.Cookies[0].Secure = true;

    In that last example you got your first look at the DateTime class. This, in a word, is fantastic. Although it lacks the "numbery-ness" of PHPs time() function, it provides a massive array of chainable methods to create and modify datetimes. This is a good introductory article.

    Post/get Parameters

    These are contained, like cookies, in the Request object. That object contains loads of stuff useful for application developers, and can be roughly compared with PHPs $_SERVER variable. Here are a few other useful things:

    NameValueCollection headers = Request.Headers;
    bool issecure = Request.IsSecureConnection;
    string url = Request.RawUrl;
    string scriptname = Request.ServerVariables["SCRIPT_NAME"];
    string useragent = Request.ServerVariables["HTTP_USER_AGENT"];

    For a full list of Request.ServerVariables this is a good resource.

    Getting back to the point; to retrieve something from a post parameter (submitted by a form) use: string value = Request.Form["param"];.

    And to retrieve something from a get parameter (in the querystring) use: string value = Request.QueryString["param"];.

    For session variables, cookies, and post and get properties, always check the parameter is not null before trying to access it. This is the equivalent of PHPs isset() function. C# is very unforgiving when it comes to null objects, so in general it always pays to check something exists before trying to use it.

    // session variable
    if (Session["var"] != null) { ... }
    // cookie
    if (Request.Cookies["cookiename"] != null) { ... }
    // post parameter
    if (Request.Form["param"] != null) { ... }
    // get parameter
    if (Request.QueryString["param"] != null) { ... }

    You can also put multiple parts in an if statement. So to check if the user has a cookie with the name "loggedin" with the value "true", this will work:

    if (Request.Cookies["loggedin"] != null && Request.Cookies["loggedin"].Value == "true") { ... }

    Just like PHP, if the first part of the if statement fails the second one is not run.


    Quick Reference

    Here's a table of common code snippets in PHP with their equivalents in C#.



    Click image to view at full size.

    Over to You...

    You now have the knowledge to build basic ASP.NET pages, and use the MonoDevelop IDE to create simple sites. In part two of this tutorial, you'll be shown some of the more advanced features of ASP.NET including:

    • MasterPages: page layouts on steroids
    • Data sources and data binding
    • Custom classes: getting all object-oriented on yo' ass
    • Custom controls: reuse to the max, baby!
  • Advertisement