In this two part post we will create a simple data entry application that will provide the following functionality.
- A page that will allow the user to enter the information regarding the recruiter and whether a call back or email is required
- A validation page which will validate the information entered.
- A page that will confirm whether you need to call back the recruiter or not and the details for this recruiter
- A page that list all the recruiters that have called and whether I needed to call them back or send them a email or not
The first part of this tutorial will deal with creating the data model and repository and creating the page to enter the user information and creating the validation page.
Creating the application
So as before go to Add New Project and select ASP.NET Empty Web Application. and give it the name RecruiterContacts
Creating the Data Model and Repository
In this example we will create the Data model that will store the recruiter information and a repository that will store all the recruiters that have contacted me. Since this is a simple example, we will not store the repository in a Database it will just stay in memory and will be discarded once the application is ended or timed out.
Recruiter.cs
Before creating this class, firstly create a new folder and call it Model. Next add a new class in there called Recruiter and add the following code to it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace RecruiterContacts.Model
{
public class Recruiter
{
public string Company { get; set; }
public string Name {get;set;}
public string URL { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public bool? ContactThem { get; set; }
}
}
This is the model that will be used, next lets create the Repository where we will store the recruiters added.
RecruiterRepository.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace RecruiterContacts.Model
{
public class RecruiterRepository
{
private static RecruiterRepository repository = new RecruiterRepository();
private List Recruiters = new List();
public static RecruiterRepository GetRepository()
{
return repository;
}
public IEnumerable GetAllRecruiters()
{
return Recruiters;
}
public void AddRecruiter(Recruiter recruit)
{
Recruiters.Add(recruit);
}
}
}
Now that the repository is done the next thing to do is to create the web form where we will enter the recruiter details.
Default.aspx
Create a new web form called Default.aspx and add the following code to it.
<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Default.aspx.cs” Inherits=”RecruiterContacts.Default” %>
<!DOCTYPE html>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head runat=”server”>
<title></title>
</head>
<body>
<form id=”recruiterform” runat=”server”>
<div>
<h1>Recruiter Information</h1>
</div>
<div>
<label>Company:</label>
<input type=”text” id=”company” />
</div>
<div>
<label>Name:</label>
<input type=”text” id=”name” />
</div>
<div>
<label>URL:</label>
<input type=”text” id=”URL” />
</div>
<div>
<label>Phone Number:</label>
<input type=”text” id=”phone” />
</div>
<div>
<label>Email:</label>
<input type=”text” id=”email” />
</div>
<div>
<label>Contact Them?</label>
<select id=”contactedthem”>
<option value=””>Choose an Option</option>
<option value=”true”>Yes</option>
<option value=”false”>No</option>
</select>
</div>
<div>
<button type=”submit”>Submit Recruiter</button>
</div>
</form>
</body>
</html>
Lets just go over a few things with this page.
Firstly the very first line is used to specify the language to use, i.e. C#, whether the auto event is turned on and the code behind class to use.
Next the form declaration has been given the id recruiterform, which we will use later for the CSS and as usual we have runat=”server”, if this was not there then the form would not work.
Then for each of the member variables in the recruiter class, there is a corresponding label and input html tag allowing the user to enter these values.
The select tag is used as a drop down to allow the user to select either true or false for whether the user has contacted them or not.
Finally we have a submit button, which will post the page back to the server passing the results back as viewstate.
So build the application and run. As you can see there is nothing special in how the app looks and if you click the button nothing is currently happening it is just posting back to the same page.
Also it looks crappy, its like a classic html page that was created long back, so lets add a bit of CSS to make it better
Styles.css
Add a new style sheet called Styles.css and add the following to it
#recruiterform label {
width: 120px;
display: inline-block;
}
#recruiterform input {
margin: 2px;
margin-left: 4px;
width: 150px;
}
#recruiterform select {
margin: 2px;
margin-left: 4px;
width: 154px;
}
button[type=submit] {
margin-top: 5px;
}
What this does is to format the labels, input, select and button to use these styles when rendering the HTML to the page.
Now to make this work we have to tell the page to use this new style sheet.
Default.aspx
Update the page as follows
<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Default.aspx.cs” Inherits=”RecruiterContacts.Default” %>
<!DOCTYPE html>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head runat=”server”>
<title></title>
<link rel=”stylesheet” href=”Styles.css” />
</head>
As you can see we have told the page to use the stylesheet Styles.css. So if you run the application again you will see that the inputs, drop down and button are all lined up correctly.
Model Binding
I will get into model binding in another tutorial, lets just say the point of it is to allow the binding of html tags with actual model data. This is similar in a Winform when you can bind a collection to the datasource of the datagridview, which then enumerates through this collection and displays the collections data.
The advantage of this is obvious, if this was not possible the only way to figure out what was in the Html tag would be to interrogate them one by one and extract the data required.
Postback to the Page
So to demonstrate this we will show how Postback works. Postback is when the user wants to postback to the server a change that requires some kind of validation or response. In most cases this is when a button is pressed. So usually when a button is pressed a postback is generated and posted back to the server, when this happens the code behind file Load method is called, there are other functions called as well, but for now I am keeping this simple, Within the Load method we have to decide whether the call is a postback or just the start of the page being processed by the server, this is done using the IsPostback property that is supported by the Page class. So lets have a quick look at the code that will handle the postback and will perform the model binding.
Default.aspx.cs
using RecruiterContacts.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.ModelBinding;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace RecruiterContacts
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
Recruiter recruit = new Recruiter();
if (TryUpdateModel(recruit,
new FormValueProvider(ModelBindingExecutionContext)))
{
RecruiterRepository.GetRepository().AddRecruiter(recruit);
if (recruit.ContactedThem.HasValue && recruit.ContactedThem.Value)
{
Response.Redirect(“youhavecontactedthem.html”);
}
else
{
Response.Redirect(“youneedtocallthem.html”);
}
}
}
}
}
}
So you can see in the page there are few things to discuss
The first is the IsPostback member variable, this is used to discover whether this is a postback or not and from this will handle the postback rather than the startup of the page.
The next thing to look at is TryUpdateModel, the purpose of this method is to allow the binding of the form data into the model data directly without having to do this yourself. The secret to how this works is that the names of the input and selects are the same as the Recruiter model class meaning this method would use some kind of reflection to figure out which property matches to which html tab and then set the model data with the html tag data.
The final thing to look at is the checking of the ContactedThem property. In that if the value is set to yes or no then a page will be displayed to the user informing them of the decision, if it is not set then no page is displayed.
So lets run the app, enter the company, name, url, etc and choose whether you contacted them or not and click the submit button. Right now when you click the submit button you will see that an error is thrown because we did not create the html pages yet, however if you look at the page that it tried to display it is youneedtocallthem.html. Why is this page being called since it should have some values, well lets check it out.
Put a breakpoint on the line highlighted below
if (IsPostBack)
{
Recruiter recruit = new Recruiter();
if (TryUpdateModel(recruit,
new FormValueProvider(ModelBindingExecutionContext)))
{
RecruiterRepository.GetRepository().AddRecruiter(recruit);
if (recruit.ContactedThem.HasValue && recruit.ContactedThem.Value)
{
Response.Redirect("youhavecontactedthem.html");
}
else
{
Response.Redirect("youneedtocallthem.html");
}
}
}
Run the app again, enter the values and then when it hits the breakpoint press F10 to step over the line. If you look at the recruit class it shows that all the values in there are null, why is that. Well the problem is that if you look at the Default.aspx page and all the input html tags they are missing something vital the runat=”server’ attribute. Without this the tag is not processed on the server and ignored meaning it display correctly on the client. but the server does not care about it, hence the model binding will fail.
To overcome this issue lets alter the Default.aspx page as follows.
Default.aspx
<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Default.aspx.cs” Inherits=”RecruiterContacts.Default” %>
<!DOCTYPE html>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head runat=”server”>
<title></title>
<link rel=”stylesheet” href=”Styles.css” />
</head>
<body>
<form id=”recruiterform” runat=”server”>
<div>
<h1>Recruiter Information</h1>
</div>
<div>
<label>Company:</label>
<input type=”text” id=”company” runat=”server” />
</div>
<div>
<label>Name:</label>
<input type=”text” id=”name” runat=”server” />
</div>
<div>
<label>URL:</label>
<input type=”text” id=”URL” runat=”server” />
</div>
<div>
<label>Phone Number:</label>
<input type=”text” id=”phone” runat=”server” />
</div>
<div>
<label>Email:</label>
<input type=”text” id=”email” runat=”server” />
</div>
<div>
<label>Contacted Them?</label>
<select id=”contactedthem” runat=”server”>
<option value=””>Choose an Option</option>
<option value=”true”>Yes</option>
<option value=”false”>No</option>
</select>
</div>
<div>
<button type=”submit”>Submit Recruiter</button>
</div>
</form>
</body>
</html>
Now run the application and enter the same values, this time we still get the error, but now we see that the other page is being requested.
Lets fix the error add the following 2 html pages
youhavecontactedthem.html
<!DOCTYPE html>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<title>Contacted Them</title>
</head>
<body>
<p>You have already contacted them</p>
</body>
</html>
youneedtocallthem.html
<!DOCTYPE html>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<title>Call Them</title>
</head>
<body>
<p>You need to call them back</p>
</body>
</html>
If you run the app now and select Yes then you will see that the you need to call them page will appear otherwise the other one will.
Conclusion
This concludes the first part of this tutorial on creating a simple data entry application, in the 2nd part of this tutorial we will create a summary page, validation, dynamic HTML, calling code behind members from the page and creating model validation.