First C# Web Application - Tutorial

(using Validation Classes)

Objectives

Functional Requirements for the Web Application

Design Web Form

Coding Advice

Add a Data Repository Class and Test It

Add a Data Validation Utility Class and Test It

Test the Data Validation Class

Add Record Validation Class and Test It

Backing Up your Web Application

Try it Yourself

Objectives

In this tutorial, you’ll learn how to create your first C# web application using Visual Studio .NET – using classes[1]. This web application is fairly simple – it only validates user data; it will not connect to a database (this will be done in later tutorials).

This tutorial assumes that you have already been introduced to the basics of how to create, run, debug, save, and backup Visual Studio web applications.

Functional Requirements for the Web Application

The web application we will create will have a single webform that is designed to accept and validate (check) data that is entered by a user. When the user clicks on a “submit button”, the application will check to ensure that all the data is valid (e.g., character fields are there, if required, and not longer than allowed, date fields contain valid dates, number fields contain nothing but digits).

Here is a sample of how your completed web form might look when it is first run.

If the user enters bad data and presses the submit button, here’s how the web form should look (individual error messages listed for each field that doesn’t pass validation):

When the user enters good data and presses the submit button, here’s how the web form should look. The individual error messages are all “” (empty string) and a summary of all entered data is listed at the bottom of the form.

Design Web Form

Here is a sample web formthat it set up appropriately for this assignment.

  • Set Flow Layout. After creating the empty web application, change the page layout of your web form to “flow layout”. Do this by clicking anywhere on the blank web form, then select flow layout from the “page layout” property (of the web form or document).
  • Insert Table. Insert a (html) table to help with the alignment of the text on the form. To do this, click on the web form where you want to insert the table, then click on Table – Insert – Table from VS’s menu. Select the number of columns (3) and rows (4 -- as many fields as you have created in your table).
  • Add Field Labels into first column. Then, drag labels from the Toolbox into the leftmost column. Since these labels will never be referenced from within your program, do not change the name (id) of these labels (leave them named “Label1”, “Label2’, etc). After dragging the label onto the form, single click on each label, then change the text property (use the property window) – as appropriate to let the user know what to enter in each row.
  • Add Input Items into second column. Then, drag the textboxes into the second column of your table. Since these WILL be referenced by your program, name these items with proper prefix (txt for textboxes). It’s easiest and best to be consistent with your naming, so I suggest you name each textbox, “txt” then the actual field name in your database table. Remember that to change the name of a textbox, you put the name into the textbox’s (ID) property.
  • Add Labels for error messages into third column. Drag a label from the Toolbox into the rightmost column. Make it red (set property “forecolor”). You can copy/paste this red label into each cell in the rightmost column (to save yourself from having to change the color of all 4 labels). Then, name each label appropriately (e.g., lblStockIdMsg). We rename these labels (in column 3) because yourprogram will reference these labels; we don’t rename the labels in column 1 because they are static labels that the program will not reference (and therefore we don’t want to have these labels look like something we might want to change).
  • Add Submit button. Drag a button from the Toolbox onto the web form. Name the button btnSubmit (by setting the (id) property). Change the text property to “Submit”. It is important to name buttons before adding code into button click events.
  • Add label for Record Message. The final label (called lblMsg below) is used to put a message for the whole record. For example, “Record was entered correctly” or “Please edit and resubmit record”.

Always remember these things as you designa web form:

  1. Always change the page layout property from gridlayout to flowlayout (makes your web form lighter – positions and sizes are not hard-coded).
  2. Drag the form controls (UI elements like textbox, button, label, etc.) onto the form. With flowlayout, it acts like a word document. The first item can only be inserted at the top left. Then, as you add more items, new items can be inserted before or after them. Add spaces or newlines to create space.
  3. Name all UI elements EXCEPT static labels(i.e., where the text of the label will never be changed when the program is running). Static labels do not need to have any special name because they will not be referenced by the program, so they can be left with the default names like “Label1”.
  • Textboxes, checkboxes, picklists, and dynamic labels (labels whose text value may be changed by the program as it’s run) should be named with prefixes like txt, chk, ddl (dropdownlist), and lbl (respectively).
  • Name the buttons too: btnSubmit or something like this.

If you do happen to mistakenly double click on a button before you manage to change the button’s name, Visual Studio will add a method named like this: Button1_click (which is associated with that button’s click event). It’s ok to leave the method named this way -- you’ll get compiler errors if you try to delete the method. Just add in a comment into that method that says something like this:

// This is really the code for btnSubmit.

Coding Advice

You always want to make small incremental improvements. Don’t write lots of code then test and try to find the errors within the large set of code changes/additions you just made. Here are some ideas for how to break down this task into small pieces.

  1. If you think a button should do something but it is not doing anything, you can try doing something simple like putting “hello” in a label when they press the button (put this code in the button click event).

this.lblMsg.Text = "hello";

TIP: Remember that the keyword “this” means the object we are in. Therefore, when you type this. (in your web form), “this” means the form. Pause after typing this.to take advantage of the intellisense (type-ahead) feature that shows all the UI elements on the form. Using intellisense helps you by preventing spelling errors.

TIP: Remember that a textbox is NOT a string – the Text property of a textbox is. Always remember to use the .Text property of a textbox or label when you want to check or set the string values that are displayed on the form.

  1. Use the debugger to see what your program is doing and where its going wrong.

Add a Data Repository Class and Test It

Add a class to hold all the input the user enters into the form.

  • Select Project – Add Class from the Visual Studio menu. I named my class Stock – you should name your class the same name as the database table you plan to have for your own individual web application. Remember to start class names with a capital letter – (all objects and variable names should start with a lower case).
  • Note that all data members of your class should be declared of type string even though some of them may end up being stored as other data types (e.g., numeric or date type) in the database. This is because the user will add text into the web form and we will check the text and try to convert it to the proper data type (e.g., number). If we can’t convert it, we’ll provide the user with an error message.
  • It’s a good idea to name the data members of your data repository class the same as the column names you gave in your database table (just to minimize all the things you have to remember).

/* Stock objects just hold all the values for a single

* stock record -- values that were entered by a user

* before validation. That's why all the fields

* (data members) are string even though they may be

* stored eventually as other datatypes in the database.

* For example, we cant store retailPrc as a decimal type

* if we are not certain that whatever the user entered

* for this field will actually convert OK to a decimalnumber. */

publicclass Stock {

// Data members - string versions of all fields of a stock record.

private string stockId = "";

private string desc = "";

private string retailPrc = "";

private string nextSaleDate = "";

// Single constructor that needs one string per data member.

public Stock(string stockId,

string desc,

string retailPrc,

string nextSaleDate) {

this.stockId = stockId;

this.desc = desc;

this.retailPrc = retailPrc;

this.nextSaleDate = nextSaleDate;

}

// Label and show all fields of the stock object.

publicstring getSummary() {

string msg = "";

msg += "Stock Id: " + this.stockId + "<br/>";

msg += "Description: " + this.desc + "<br/>";

msg += "Retail Price: " + this.retailPrc + "<br/>";

msg += "Next Sale Date: " + this.nextSaleDate + "<br/>";

return msg;

}

// All other methods are just getters and setters.

publicstring getStockId() {

returnthis.stockId;

}

publicvoid setStockId (string stockId) {

this.stockId=stockId;

}

publicstring getDesc() {

returnthis.desc;

}

publicvoid setDesc (string desc) {

this.desc=desc;

}

publicstring getRetailPrc () {

returnthis.retailPrc;

}

publicvoid setRetailPrc (string retailPrc) {

this.retailPrc=retailPrc;

}

publicstring getNextSaleDate () {

returnthis.nextSaleDate;

}

publicvoid setNextSaleDate (string nextSaleDate) {

this.nextSaleDate=nextSaleDate;

}

}

As you work on coding up this (or any class), start with just a few data members and methods and test it from the web form. Remember never write too much code between test cycles. You could test your new class by putting this kind of code in the button click event:

Stock stock = new Stock (this.txtStockId.Text, this.txtDesc.Text,

this.txtRetailPrc.Text, this.txtNextSaleDate.Text);

this.lblMsg.Text = stock.getSummary();

TIP: After typing the object (e.g., stock), pause to see all the available methods of that object. Select from the list. After you have selected the method, pause after entering the left parenthesis and let Visual Studio show you what parameters the method is expecting.

Add a Data Validation Utility Class and Test It

You may use the Validation Utility Class that I have in my sample code, but you need to take a moment to fully understand what all the methods are doing.

To add my Validation Utility class to your project, click on Project – Add Existing Item. Then select my file (ValidateUtils.cs). Then this file will show up in your solution explorer. Next, you need to edit this file so that the namespace matches your project name exactly (case matters). So, change “cis410wk1ValidForm” to the name of your project.

/* ValidateUtils is a class that contains methods for

* validating various types, such as string, integer (int),

* currency (decimal), and date. Each method takes in

* a string (as entered by the user), checks to ensure that

* it is valid (non-empty if required, valid type if non-empty,

* etc.) Each method returns an error message that can be

* displayed on the form (or "" if the string is actually valid).

* Methods are declared static since there is no need to instantiate

* objects just to call these methods. */

publicclass ValidateUtils {

// no data members

public ValidateUtils() {

}

public static string stringValidationMsg (string enteredString,

int maxlength, bool required) {

// Returning empty string as message means entered string was OK.

string message = "";

// Handle empty input

if (required) {

if (enteredString.Equals("")) {

// if required and nothing entered, this is error.

return "Please enter a value.";

}

}

else { // is not required

if (enteredString.Equals("")) {

// If nothing entered and not required, OK

return "";

}

}

if (enteredString.Length > maxlength)

message = "Input is too long. Pls shorten to ["

+ enteredString.Substring(0,maxlength) + "]";

return message;

}

public static string dateValidationMsg(string enteredDate, bool required){

// Returning empty string as message

// means entered date was OK, else return error msg.

// If value is not required, then a non-entry is OK.

if (!required & enteredDate.Equals(""))

return ""; // means data passed validation

System.DateTime d;

// this would give us today/now:

// System.DateTime d = DateTime.Today;

try {

d=Convert.ToDateTime(enteredDate);

return ""; // means data passed validation

}

catch (Exception ex) {

string s = ex.Message;

return "Please enter a valid date.";

}

}

public staticstring intValidationMsg(string enteredInt, Int32 maxVal,

bool required) {

// Returning empty string as message

// means entered integer was OK.

string message="";

// If value is not required, then a non-entry is OK.

if (!required & enteredInt.Equals(""))

return "";

System.Int32 inum;

try {

inum=Convert.ToInt32(enteredInt);

if (inum > maxVal)

message="Please enter value <= " + maxVal.ToString();

return message;

}

catch {

return "Please enter a valid integer.";

}

}

public staticstring currValidationMsg(string enteredCurr, bool required) {

// if value is not required then empty string is OK

if (!required & enteredCurr.Equals(""))

return "";

// if we return an empty string,

// means the entered integer was OK.

string message="";

try {

System.Decimal dec=Convert.ToDecimal(enteredCurr);

System.Decimal dec100 = Decimal.Multiply(dec,Convert.ToDecimal(100));

System.Int64 int100 = Convert.ToInt64(dec100);

if (!dec100.Equals(Convert.ToDecimal(int100)))

message = "Too many digits to the right of the decimal point.";

return message;

}

catch {

return "Please enter a valid currency value.";

}

}

}

Test the Data Validation Class

To test the validation class directly from your web form, you could put this code in your button click event. This code uses its dateValidation method, passing in whatever the user entered into the date field, and putting the resulting error message (or “” if no error) into the label for the date error message. Note we don’t have to declare and instantiate any ValidateUtils objects because the ValidateUtils class does not have any data members and all its methods are declared as static.

this.lblNextSaleDateMsg.Text = ValidateUtils.dateValidationMsg

(this.txtNextSaleDate.Text,true);

Add Record Validation Class and Test It

The code below shows how to tie together the Data Repository class (in my case, Stock) with the Validation Utility class to create a Stock Validation class. Note that class ValidateStock contains a Validation Utility object as a as data member so that all ValidateStock methods can call the Validation Utility methods. Also note that the ValidateStock constructor requires a Stock object as input, so it can immediately validate every field of the stock object, creating a complete set of error messages that the web form can then utilize.

/* ValidateStock objects:

* (1) hold a Stock object,

* (2) validate that Stock object, and

* (3) provide a detailed list of all the errors

* that it found during validation. For example,

* if the retail Price is not a valid decimal

* (currency) value, or of the nextSaleDate

* is not a valid date.

*/

publicclass ValidateStock {

// data members

private Stock stock; // the stock record we are validating

// one error message per field (that can be displayed on form)

privatestring stockIdMsg;

privatestring descMsg;

privatestring retailPrcMsg;

privatestring nextSaleDateMsg;

// tells if all fields are OK or not.

privatebool allOK;

// constructor

public ValidateStock(Stock stock){

this.stock = stock; // store input parameter to data member

// validate all fields

this.validateStockId();

this.validateDesc();

this.validateRetailPrc();

this.validateNextSaleDate();

// set boolean to indicate if all fields are OK or not

string allMsgs = this.stockIdMsg + this.descMsg +

this.retailPrcMsg + this.nextSaleDateMsg;

if (allMsgs.Equals(""))

this.allOK = true;

else

this.allOK = false;

}

publicvoid validateStockId() {

// required integer, max value is 99999

this.stockIdMsg = this.ValidateUtils.intValidationMsg(

this.stock.getStockId(),99999,true);

}

publicvoid validateDesc() {

// required string, max length is 20 characters

this.descMsg = this.ValidateUtils.stringValidationMsg(

this.stock.getDesc(), 20, true);

}

publicvoid validateRetailPrc() {

// required currency value

this.retailPrcMsg = this.ValidateUtils.currValidationMsg(

this.stock.getRetailPrc(), true);

}

publicvoid validateNextSaleDate() {

// optional date field

this.nextSaleDateMsg = this.ValidateUtils.dateValidationMsg(

this.stock.getNextSaleDate(),false); // not req'd

}

public Stock getStock() {

returnthis.stock;

}

publicstring getStockIdMsg() {

returnthis.stockIdMsg;

}

publicstring getDescMsg() {

returnthis.descMsg;

}

publicstring getRetailPrcMsg() {

returnthis.retailPrcMsg;