MCAD/MCSD Training Guide (70-315): Developing and Implementing Web Applications
with Visual C# and Visual Studio .NET (First Edition) by Amit Kalani 

Errata 

(You can help! If you know an error not mentioned in this list, please report the error)

You may also like to check the frequently asked questions.

Last Update: June 30, 2004

Ch# Page Error Description Reported By
1 41 In Step By Step 1.1, Step 3, line 22 of code. Change <tr> to </tr> Eric Engler
1 72 In Step By Step 1.7, Step 3, In the last line of code, change <tr> to </tr> Eric Engler
1 72 In Step By Step 1.7, after step 3, access the Properties window for the TemperatureCB.cs file and change its Build Action property to None.  
1 74 In Step By Step 1.8, Step 2, change the command to the following:
csc /t:library /out:bin\TemperatureCB.dll TemperatureCB.cs
Stephen Krauklis
1 77 In Step By Step 1.9, Step 5, replace the following line of code:
<TD>&deg Celcius</TD>
with:
<TD>&deg Celsius</TD>
Jacques Lacerte
1 78 In Step By Step 1.9, Step 6, In the last line of code, change <tr> to </tr> Eric Engler
1 93 In Question 15, choice C, replace dl1 by dll ( digit one by letter l). Jacques Lacerte
1 95 In the answer to Question 9. replace the two instances of <%...%> with <%=...%> Jacques Lacerte
2 114 In Step By Step 2.3, Step 1, add the following sentence:
Change the id attribute of the HTML <form> element to StepByStep2_3.
Skip Sailors
2 124 In Table 2.5, in the description for the ImageAlign property, change Botton to Bottom Rick Sims
2 133 In Step By Step 2.5, Step 1, add the following sentence:
Change the id attribute of the HTML <form> element to StepByStep2_5.
GaneshKumar Sankararaman
2 140 In Step By Step 2.6, Step 4, add the following after the second sentence:
Select the CheckBoxList control, and, using the Properties window, select the Items property and click the ellipses button (...) to open the ListItem Collection Editor. Add the six checkbox items as shown in Figure 2.18. Repeat this procedure for the RadioButtonList control, adding the six radio buttons as shown in Figure 2.18.
Royce Fickling
2 149 In Step By Step 2.9, Step 3, change txtRows to txtRow and change txtColumns to txtCell Stephen Krauklis
2 170 In Step By Step 2.11, Step 2, change the third sentence to read:
Create a table of three rows and two columns of border size 0 in the form.

In Step 3, remove the following sentence:
Set the InitialValue property of the rfvCountry to <Select a Country>.
and place it to the end of Step 4.

Stephen Krauklis
2 170 In Step By Step 2.11, Step 2, change the last sentence to read as:
Place a Label control (lblMessage) and a Button control (btnSubmit) onto the Web form.
Tahir Nasir
2 177 In Step By Step 2.13, Step 5, change cuvTickets_ServerValidate to cuvPalindrome_ServerValidate. Stephen Krauklis
2 184 In Step By Step 2.15, add the following text to the Step 1:
Click on the Web Form, access its Property window and, change the pageLayout property of the DOCUMENT element from GridLayout to FlowLayout.
Royce Fickling
2 192 Exercise 2.1, Step 4, change ibDice_Click to ibLocate_Click Stephen Krauklis
2 195 Exercise 2.4, Step 2, Change the second sentence to read as:
Create a table of four rows and two columns of border size 0 in the form.
After Step 2, take an additional step and set  the TextMode property for all the three password text boxes to Password.
Gavin Ouckama
2 195 Exercise 2.4, Step 5, change txtPassword to txtOldPassword Stephen Krauklis
2 204 In the answer to question 13, in the first line, change RequiredFieldValidator to RegularExpressionValidator. Roman Makowski
3 217 Change the third line of code to the following:
<pages smartNavigation="true"/>
(Note that the tag names and attribute names in ASP.NET configuration files are camel-cased, which means that the first character is lowercase and the first letter of any subsequent concatenated words is uppercase.)
John R.Thrash
3 220 In Step By Step 3.3, Step 3, also add the following using directive: 
using System.Collections.Specialized;
This using directive is required because the NameValueCollection class, used in the code, belongs to this namespace.
Randall Woodman
3 239 In Step By Step 3.8, after Step 1, add a label control (lblName) to the form. Jason Frakes
3 242 In Step By Step 3.9, add the following text to Step 2. Right-click on the txtPosts control and set it to run as a server control. Set the value property of the txtPosts control to 0. Asad Parvez
3 253 In Step By Step 3.11, after Step 1, add a Label control (lblName) to the Web form. Gavin Ouckama
3 257 In Step By Step 3.12, after Step 1, add a Label control (lblInfo) to the Web form. Baljinder Sandhu
3 260 Paragraph 4 is only correct for the the .NET Framework 1.0. For the .NET Framework 1.1, paragraph 4 should read as:
The default use of the Server.Transfer() method passes the form data and the query string of the original page request to the page receiving the transfer. However, you can clear the form data and query string of the original page by passing a false value to the optional second argument. The second argument takes a Boolean value that indicates whether to preserve the form and query string collections.
David Vernest
3 262 In Step By Step 3.13, step 3, add the following using directive to your code:
using System.IO;
This using directive is required because the StringWriter class, used in the code, belongs to this namespace.
Randall Woodman
3 272 In Exercise 3.2, replace Step 6 with the following:

6. Drag three Label controls (name the first as lblCode), two TextBox controls (txtName and txtAddress), and a Button control (btnFinish to the Web form (see Figure 3.19).

Jacques Lacerte
3 279 Change the explanation for the answer to Question 14 to read as:

14. B. You get an error while executing the Server.Execute() method because the view state of the "ShowData.aspx" page is passed to the "GetData.aspx" page along with the form and query string collections, causing the ASP.NET machine authentication check to fail. You need to set the EnableViewStateMac attribute of the Page directive in the "GetData.aspx" page to false in order  to resolve this error. For more information, see the section "Navigation Between Pages" in this chapter.

Randall Woodman
4 303 In Guided Practice Exercise 4.1, Step 4 change the following line of code:
String[] line = txtText.Text.Split()
to
String[] line = txtText.Text.Split('\n')
Dave Owens
4 310 In Step By Step 4.6, Step 3, in the HTML code, change StepByStep4_1.aspx to StepByStep4_6.aspx. 

Also modify figure 4.12 to reflect this change.

Jacques Lacerte
4 314 In Step By Step 4.8, change step 2 to read as:

2. Add the following using directive to your code:
using System.Diagnostics;
Add the following code to the Application_Error() event handler:

protected void Application_Error(Object sender, EventArgs e)
{
    // Get the Exception object wrapped in the InnerException property
   Exception unhandledException =
              (Exception)Server.GetLastError().InnerException;
   // Create an EventLog instance and assign its source.
   EventLog eventLog = new EventLog("Application");
   eventLog.Source = "Application";

   // Write an informational entry to the event log.
   eventLog.WriteEntry(unhandledException.Message +
                 unhandledException.StackTrace);
    Response.Write("An exception occurred: Check Application event log for details");
    Server.ClearError();
}

Randall Woodman

Skip Sailor

4 318 In Guided Practice Exercise 4.2, append the following sentence to Step 7:

Make sure that you modify Web.Config file to set the mode attribute of the <customErrors> element to "on". 

Winson Woo
5. 380 Guided Practice Exercise 5.2 does not populate the datagrid with the order details of the initially selected item. To resolve this, change the Page_Load() method as follows:

private void Page_Load(object sender, System.EventArgs e)
{
      if (!IsPostBack)
      {
            // Load the dataset for the dropdownlist
            sqlDataAdapter1.Fill(dsOrders1, "Orders");
            // And bind it
            ddlOrders.DataSource = dsOrders1;
            ddlOrders.DataTextField = "OrderID";
            ddlOrders.DataValueField = "OrderID";
            ddlOrders.DataBind();
            ddlOrders_SelectedIndexChanged(sender, e);
      }
}

Dave Owens
5. 393 In Step By Step 5.22, Delete the words "and DeleteCommand" from step 11. There is no delete code in this Web Form.

 

Eric Engler
5. 398 Exercise 5.2. In the note, change the sentence:
"If you haven't yet done that, refer back to Step By Step 5.11, particularly steps 4 through 6 and the accompanying Exam Tip, for information on how to build a connection."

to read as:

"If you haven't yet done that, refer back to Step By Step 5.11, particularly steps 4 through 6 and the accompanying note, for information on how to build a connection."

Randall Woodman
5 400 In Exercise 5.3, Step 3, add the following using directives to the Computer.cs file:
using System.Data;
using System.Collections;
Tahir Nasir
5 400 In Exercise 5.3, The first time the page is displayed you don't see a value in the textbox. To fix this, find the following line of code:
ddlComputers.DataBind();

And add this new line right after it:
txtRAM.DataBind();
Eric Engler
5 400 In Exercise 5.3, Step 5 change txtOrderID to txtRAM. Hans De Schrijver
5 403 Exercise 5.6 does not automatically select the first record when the application starts. To fix this, set the SelectedIndex property of dlEmployees control to 0 at design time.
 
Eric Engler
5 406 Change the first sentence of Question 4 to the following:

Your application database includes a number of tables. One of these tables is named Courses and it contains a list of course numbers and course names.

Brian Andrews
5 409 In Question 10, change asp:Button to <asp:Button  Caroline Bogart
6 437 Change the following UPDATE query:

UPDATE Suppliers INNER JOIN Products
ON Suppliers.SupplierID = Products.SupplierID
SET Products.Discontinued = 1
WHERE Suppliers.Country = 'Italy'

to:

UPDATE Products
SET Products.Discontinued = 1
FROM Products, Suppliers
WHERE Suppliers.SupplierID = Products.SupplierID
AND Suppliers.Country = 'Italy'

Brian Andrews
6 441 Step By Step 6.6. In Step 6, change the name of method from StepByStep6_6_Load() to Page_Load() Randall Woodman
6 475 Table 6.7. In the description for the UpdateCommand member, change ows to rows. Randall Woodman
6 488 In the Warning box, change Step By Step 6.20 to Step By Step 6.19 Randall Woodman
6 505 In the code, change the following line:
dr[0] = txtCustomerID.Text;
to:
dr[0] = txtCustomerID.Text.Trim();
Jonathan Phillips
6 505 Second paragraph, third sentence, change database to dataset Jonathan Phillips
6 506 and 507 In Step By Step 6.25, btnDelete_Click() method, change the following lines of code:
// Find the specified row and delete it
foreach( DataRow dr in ds.Tables["Customers"].Rows)
{
    
if(dr[0].ToString() == txtCustomerID.Text)
   {
       dr.Delete();
       break;
    }
}
// Save the changes
da.Update(ds, "Customers");
lblResults.Text = "Row deleted!";

to:

lblResults.Text = "Cannot find a row for this customer";
// Find the specified row and delete it
foreach( DataRow dr in ds.Tables["Customers"].Rows)
{
    
if(dr[0].ToString().Trim() == txtCustomerID.Text.Trim())
   {
       dr.Delete();
       lblResults.Text = "Row deleted!";
       break;
   
}
}
// Save the changes
da.Update(ds, "Customers");

Use of Trim() method is needed because the primary key (CustomerID) is a fixed-width column (not a VarChar).

Jonathan Phillips
6 509 and 510 In Step By Step 6.26, the DataGrid control is not correctly refreshed when a new record is added. To fix this problem, please modify the LoadData() method as shown below:
private void LoadData()
{
      // Bind the data to the DataGrid
      ds = new DataSet();          //newly added
      da.Fill(ds, "Customers"); //newly added
      dgCustomers.DataSource = ds;
      dgCustomers.DataMember = "Customers";
      dgCustomers.DataBind();
}
Eric Engler
6 518 In Table 6.15, change the member PreviousSibling() to PreviousSibling. Also, change its type from Method to Property. Paolo Corti 
6 520 In Step By Step 6.27, add the following using directive on the top of the code:
using System.IO;

And replace the definition of the AddWithChildren() method with the following:
private void AddWithChildren(XmlNode xnod, Int32 intLevel)
{
   // Adds a node to the ListBox, together with its children. 
   // intLevel controls the depth of indenting
   XmlNode xnodWorking;
   string strIndent = "";
   for (int i=0; i< 2*intLevel; i++)
   strIndent += "&nbsp;";

   // Get the value of the node (if any)
   String strValue= (String) xnod.Value;
   if(strValue != null)
           strValue = "&nbsp;:&nbsp;" + strValue;

   // Add the node details to the ListBox
   string str = strIndent + xnod.Name + strValue;
   StringWriter writer = new StringWriter();
   Server.HtmlDecode(str, writer);
   lbNodes.Items.Add(writer.ToString());

   // For an element node, retrieve the attributes
   if(xnod.NodeType == XmlNodeType.Element)
   {
       XmlNamedNodeMap mapAttributes= xnod.Attributes;
       // Add the attributes to the ListBox
       foreach(XmlNode xnodAttribute in mapAttributes)
       {
             str = strIndent + "&nbsp;&nbsp;" + 
                     xnodAttribute.Name + "&nbsp;:&nbsp; " + 
                     xnodAttribute.Value;
              writer = new StringWriter();
              Server.HtmlDecode(str, writer);
              lbNodes.Items.Add(writer.ToString());
        }
        // If there are any child nodes, call this procedure recursively
        if(xnod.HasChildNodes)
        {
            xnodWorking = xnod.FirstChild;
            while (xnodWorking != null)
            {
                     AddWithChildren(xnodWorking, intLevel + 1);
                     xnodWorking = xnodWorking.NextSibling;
             }
         }
    }
}
Eric Engler
6 532 Step By Step 6.30, Step 4. Change all occurrences of MessageBox.Show to  lbErrors.Items.Add Randall Woodman
6 538 In Exercise 6.1, Step 7, in the Page_Load() method, remove the following two statements:
cnn.Open();
cnn.Close();
These statements are not needed because the DataSet.Fill() method automatically open and close the database connection.
Sergei Akopov
6 539 In Exercise 6.1, Step 8, replace the code for the btnLoad_Click() method with the following:
 private void btnLoad_Click(object sender, System.EventArgs e)
{
    // Create a new DataSet
    DataSet ds = new DataSet();

    // Load the orders for this customer
    SqlCommand cmdOrders = cnn.CreateCommand();
    cmdOrders.CommandType = CommandType.StoredProcedure;
    cmdOrders.CommandText = "procOrdersForCustomer";
    cmdOrders.Parameters.Add
       (new SqlParameter("@CustomerID",SqlDbType.Text, 5));
    cmdOrders.Parameters["@CustomerID"].Value=
       ddlCustomers.SelectedItem.Value;
    SqlDataAdapter daOrders = new SqlDataAdapter();
    daOrders.SelectCommand = cmdOrders;
    daOrders.Fill(ds, "Orders");

    // Bind the data to the user interface
    dgMain.DataSource = ds;
    dgMain.DataMember = "Orders";
    dgMain.DataBind();
}
Sergei Akopov
6 541 Exercise 6.3. "usestransactions" should be "uses transactions" Randall Woodman
7 557 Figure 7.2, the Field access value in the figure is public, It should actually be private. Paolo Corti 
7 560 Figure 7.4, the return type shown in the figure is void. It should actually be int. Randall Woodman
7 565 In Step By Step 7.3, add the following using directive to the code:
using StepByStep7_1;
Jonathan Phillips
7 569 In Step By Step 7.4, Step 5. btnGo_Click should be btnSearch_Click  
7 579 In the fourth paragraph, change the last sentence to the following:

This method first checks the current value of the ChildControlsCreated property. If this value is false, the CreateChildControls() method is called.
 

Adam Pemberton
7 583 In Step By Step 7.8, the custom control does not preserve grid positioning. To resolve this problem, change the definition of the Render() method to the following:

protected override void Render(HtmlTextWriter output)
{
    //Preserve grid positioning information
    System.Collections.IEnumerator enumerator =
               this.Style.Keys.GetEnumerator();
    while(enumerator.MoveNext())
             output.AddStyleAttribute((string)enumerator.Current,
                               this.Style[(string)enumerator.Current]);
     //Render the control
     output.RenderBeginTag(HtmlTextWriterTag.Div);
     if (bold)
     {
           output.RenderBeginTag(HtmlTextWriterTag.B);
           output.Write(Text);
           output.RenderEndTag();
      }
     else
     {
           output.Write(Text);
      }
      output.RenderEndTag();
}

Steve Heckler
7 594 In Step By Step 7.10, Take the following additional step:
10. In the Server Explorer window, right-click on the node for Solution 315C07 and select Properties from the shortcut menu. In the Solution '315C07' Property Pages dialog box, select Configuration Properties, Configuration node and uncheck the Build property for the project  StepByStep7_10.
Hsiu-Yu Yang
8 628 In the note, change the URL for airport code from www.house747.freeserve.co.uk/aptcodes.htm  
to
http://www.google.com/search?q=ICAO+codes  
 
8 629 In Step By Step 8.1, change Step 5 to read as:
5. Add a new Web form (StepByStep8_1.aspx) to the project and delete the default WebForm1.aspx form.
 
8 632 In Step By Step 8.2, after Step 3 take the following action:

Modify the name of the constructor from Service1 to Strings

 
8 636 In the Step 3 of the Guided Practice Exercise, replace the second and the final sentence with the following:

Change the name of the class to Customer and change all reference of Service1 to Customer. Enter the following code at the top of the file:
using System.Data.SqlClient;
Caroline Bogart
8 638 Replace the Step 13 of the Guided Practice Exercise with the following:

13. Set the Web Project as the starting project of the solution.

Caroline Bogart
8 642 In Step By Step 8.5, after Step 5 take the following action:

Select Project, Add Reference to add a reference to the System.Web.Services.dll library in your project

 
9 666 In Step By Step 9.2, the text box does not display the culture information for the initially select item in the drop down list, to resolve this problem, change the Page_Load() method as shown here:
private void Page_Load(object sender, System.EventArgs e)
{
     // Stock the Dropdownlist
    if (!IsPostBack)
   {
       foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
      {
           ddlSelectCulture.Items.Add(ci.Name);
       }
      ddlSelectCulture_SelectedIndexChanged(sender, e);
   }
}
 
9 669 In Step By Step 9.3, Step 2, set the GroupName property for the three RadioButton controls to a common value such as grpDestination.  
9 690 In Question 8, answer A, change Unicode.GetBytes() to UnicodeEncoding.GetBytes().

In Question 8, answer B, change Unicode.GetChars() to UnicodeEncoding.GetChars().

 
10 703 Change the fourth line of code from:
strConn =
to:
strConn = _ 
Dave Owens
11 744 In Step By Step 11.2, Step 2, remove the following line from the code:
</form>
Baljinder Sandhu
12 788 Change the third sentence in the second paragraph to read as:

On the other hand, when a program is compiled using the Release configuration, it does not include any calls to the Debug class.

Jonathan Phillips
12 791 In Step By Step 12.3, Step 9, change the third sentence to read as:

Enter the value 5 and click the Calculate button; you should find that factorial has been calculated, but there are no debug messages in the Output window.

Jonathan Phillips
12 804 In Guided Practice Exercise 12.1, Step 4, replace the first sentence with the following text:

Run the project by using the DEBUG configuration and enter a value for which to find the factorial.

Caroline Bogart
12 830 In Exercise 12.2, Step 6, change dataGrid1 to dgProducts. In Step 7, change the code to the following:

private void btnGetProducts_Click(
           object sender, System.EventArgs e)
{
       sqlDataAdapter1.Fill(this.dataSet11);
       dgProducts.DataBind();
}

Caroline Bogart
13 844 Second paragraph, second to the last line, change Ior to or. Dave Owens
13 856 Step By Step 13.2, Step 11. Change the fourth sentence to:

The WebSql application will be uninstalled from your computer.

 
13 873 In figure 13.21, the value of the Condition property should be MDACSUPPORT >= "2.7" instead of MDACSUPPORT >= 2.7. Herry Lesmana
13 880 Change all occurences of Step by Step 13.10 on this page to Step by Step 13.9 Roman Makowski
13 889 Step By Step 13.14, Step 4. The "My Custom Control" tab was not created in Chapter 7. However you can create one by right-clicking on the Toolbox and selecting Add Tab from the context menu. Dave Owens
14 952 In Step By Step 14.3, Step 6, change the text "Selected EventLog does not Exists" to "Selected EventLog does not Exist". Caroline Bogart
14 962 In Step By Step 14.5, add the following using directive to the code: 
using System.Diagnostics;
Dave Owens
15 991 and 992 In Step By Step 15.1, when you create a Web page named 404.aspx, Visual Studio .NET set the id attribute of the <form> element to "404". When an ASP.NET page executes, it is dynamically converted into a C# program (Refer to the "Understanding ASP.NET Execution" section  in chapter 1). The <form> element is converted into a variable of type HtmlControls.HtmlForm and the name of variable comes from its id attribute. The above setting of the <form> element will lead ASP.NET to generate the following invalid C# code:

protected System.Web.UI.HtmlControls.HtmlForm 404;

However, ASP.NET detects this and restricts the generation of this code by displaying the following error message: 

Parser Error Message: '404' is not a valid identifier. 


To see the above error message, take the following steps:
  1. Set the mode attribute of the <customError> element to either "Off" or "RemoteOnly" in the web.config file. 
  2. Set 404.aspx as the start page of the project and run the project.

To resolve this error, either change the id attribute of the <form> element to a valid identifier such as "f404" or change the form name from 404.aspx to Custom404.aspx in the steps 4 and 5.

Dave Owens
15 1018 In Step By Step 15.10, Step 5, change the first sentence to the following:

Switch to code view and add the following using directive:
using System.Data.SqlClient;

Dave Owens
15 1022 In Guided Practice Exercise 15.1, Step 5, change the first sentence to the following:

Switch to code view and add the following using directive:
using System.Data.SqlClient;

Caroline Bogart
15 1026 In Step By Step 15.11, replace Step 2 text with the following:

Place two Label controls (lblGenerateTime and lblMessage), a DropDownList control (ddlCountries), a Button control (btnGetCustomers), and a DataGrid control (dgCustomers) on the form.

In Step 4, change the first sentence to the following:

Switch to code view and add the following using directive:
using System.Data.SqlClient;

Caroline Bogart
15 1033 In Step 2, change mode="SqlServer" to mode="SQLServer" Caroline Bogart
App. B 1114 The paragraph after the MCAD Elective Exams bullet list should read as: 
You may also count as elective one of the four core exams 70-305, 70-306, 70-315, and 70-316. The elective exam must be from the opposite technology as the exam that you counted as core. For example, if you take the exam "Developing and Implementing Web Applications With Visual C# .NET and Visual Studio .NET" (Exam 70-315) as a core exam, you can take either the "Developing and Implementing Windows-based Applications With Visual C# .NET and Visual Studio .NET" (Exam 70-316) or the "Developing and Implementing Windows-based Applications With Visual Basic .NET and Visual Studio .NET" (Exam 70-306) as an elective.
Karen Zhu

(end of errata)