SlideShare a Scribd company logo
1 of 21
Download to read offline
Matt Willmer’s .NET
     Portfolio
        Matt Willmer
       October 28, 2008
Summary
This document contains a detailed explanation for the projects I worked on as part of the .NET Masters
program at SetFocus from August 3, 2009 to October 28, 2009. A full curriculum description for this
program can be found here: http://www.setfocus.com/MastersProgram/curriculum_dotnet.aspx All of
these projects were completed with .NET 3.5 using Visual Studio 2008, SQL Server 2008, IIS 6.0, and
Windows Server 2003.


Overall Requirements
SetFocus required that I use a multi-tiered programming model for all of the projects that I’ve
completed. This means that each assignment was divided into at least one Visual Studio project for each
tier. The following is an example of the tiers that I used:

        Data Access Tier – A class library consisting of all of the code needed to interact with the
        database server. Generally, no other layer should contain any database interface code.
        Business Tier – A class library serving as a link to process and pass data between the Data Access
        and Presentation layers.
        Presentation Tier – A Windows Forms application or ASP.NET web application containing all of
        the code to display information to the user, and receive and validate user input.
        Entities Tier – A class library consisting of classes that define objects used to pass data. This tier
        is used by all other tiers. Typically the Data Access Tier will retrieve data from a database and
        use it to populate properties in objects defined in the Entities Tier. Those objects are passed
        through the Business Tier to the Presentation Tier to be consumed. When using LINQ to SQL,
        this tier is automatically generated by Visual Studio based on the database design, so it’s not
        always clearly separated from the Data Access Tier.


Project 1

Overview
The purpose of this project was to get familiar with coding in C#, especially with some of the features
that make it unique from other languages like C++ or Java. This project was short and pretty simple--I
was given a very detailed textual description of all of the needed classes and interfaces for a plausible
business layer for a retail company. I put those specifications into code, and used a provided test dll to
ensure that the classes functioned properly. The best way to see how these interact with each other
would be to open the project in Visual Studio and use the Object Browser to look at their properties and
methods. But since I didn’t design the class structure (I only coded it), I’ll select code snippets from the
project to illustrate what I learned.

C# Properties
While instance variables (or fields) can be used to store data in a class in most programming languages,
C# also provides a feature called Properties to enhance this. A public property can be accessed from
outside of a class in the same way that a field would be accessed, but with a property the programmer
can specify code to run at the time the property is set or read through a set and get method. These
come in handy when validating data or when the data comes from some internal structure that must be
private. Additionally, the get and set methods for a public property can be set to private to make the
property read-only or write-only. The following code snippet illustrates this:

 protected decimal unitPrice;
 public decimal UnitPrice{
       get { return unitPrice; }
       set {
             if (value < 0.0m){
                   throw new ArgumentOutOfRangeException("UnitPrice",
 "UnitPrice cannot be less than 0.");
                   }
             unitPrice = value;
             }
       }
                        Code Snippet 1: AppTypesProduct.cs Lines 108 – 122

Working with System.Runtime.InteropServices.IEnumerator
Enumerators allow a programmer to retrieve a series of values in a given order, one by one, often with a
foreach loop. One way to produce an object of type IEnumerable is to inherit from it, and implement its
methods to return values, and adjust the current value index. Another way is to use the yield return
statement. The yield return statement defines the next value that will be returned by the iterator. This
code snippet shows the yield return statement used to produce an IEnumerable that returns each of the
properties stored in this class, one by one:

 public IEnumerable PropertyAndValuesCollection()
 {
       yield return String.Format("ID: {0}", ID);
       yield return String.Format("CompanyName: {0}", CompanyName);
       yield return String.Format("ContactName: {0}", ContactName);
       yield return String.Format("ContactTitle: {0}", ContactTitle);
       yield return String.Format("Address: {0}", Address);
       yield return String.Format("City: {0}", City);
       yield return String.Format("Region: {0}", Region);
       yield return String.Format("PostalCode: {0}", PostalCode);
       yield return String.Format("Country: {0}", Country);
       yield return String.Format("Phone: {0}", Phone);
       yield return String.Format("Fax: {0}", Fax);
       yield return String.Format("HomePage: {0}", HomePage);
       yield return String.Format("Type: {0}", Type);
 }
 //This allows a programmer to write
 foreach (string s in PropertyAndValuesCollection()
 {
     Console.WriteLine(s);
 }
                        Code Snippet 2: AppTypesSupplier.cs Lines 127 - 142
Enumerators also come in handy when using LINQ, which I’ll talk about in Project 3.

Comparing Objects
Like C++, C# allows for operator overloading to perform math and Boolean operations on objects. The
following code snippet shows the == operator overloaded:

         public static bool operator == (Supplier sup1, Supplier sup2){
             if (object.ReferenceEquals(sup1, null) &&
 object.ReferenceEquals(sup2, null))
             {
                 return true;
             }
             if (object.ReferenceEquals(sup1, null) ||
 object.ReferenceEquals(sup2, null))
             {
                 return false;
             }
             return sup1.Equals(sup2);
         }
                        Code Snippet 3: AppTypesSupplier.cs Lines 144 – 154

It’s important to note that some other.NET languages (Visual Basic, in particular) do not support
operator overloading. Therefore, it’s always best to override the object.Equals() method as well. As you
can see from the code snippet, the actual comparison of Supplier objects is being done by the Equals
method (Which has been overridden, but not shown). It’s best to only implement the actual comparison
code once in the Equals method.           Also note that when checking for null input references
object.ReferenceEquals() must be used so the operator function does not become recursive. The ==
method requires != to be overloaded as well (which isn’t shown in the snippet).

Delegates and Events
Events can be used to alert other objects that something has occurred without necessarily knowing what
those objects are. They’re most common in programming user interfaces, although Visual Studio writes
them automatically. There are some situations where a programmer may want to use his or her own
event. First, a delegate must be declared:

 public delegate void CollectionModifiedHandler(object sender,
 ModificationEventArgs args);
                    Code Snippet 4: AppTypesCollectionModifiedHandler.cs Line 8

An event was declared in the class that will broadcast the event, and the event was checked for a null
value before calling it. An event will be set to a null value before any other classes have registered to
receive it:
public event CollectionModifiedHandler CollectionModified;
 private void OnCollectionModified(ModificationEventArgs args){
       if (CollectionModified != null)
             CollectionModified(this, args);
 }
                           Code Snippet 5: AppTypesProducts.cs Lines 21 – 29

An object can register to receive the event like this:

 public void Register(Products pros)
 {
     pros.CollectionModified += new
 CollectionModifiedHandler(pros_CollectionModified);
 }
 public void pros_CollectionModified(object sender, ModificationEventArgs
 args)
 {
     lastEventDetails = "Modification Attempted " +
 args.ModificationEventStatus.ToString() + " " +
 args.ModifiedObjectReference.ToString();
 }
                         Code Snippet 6: AppTypesEventLogger.cs Lines 17 - 24

There are a lot of other small things I learned in this lab, like Attributes and Serialization. These are
rather straightforward, so I won’t go into them in detail.


Project 2

Overview
The purpose of the second project was to gain a solid understanding of Windows Forms programming,
and become familiar with as many controls from the Visual Studio Toolbox as possible. For this project,
I wrote the Business and Presentation Layers for a plausible public lending library application. I was
provided with a database structure, a script to populate the database with test data, and a dll containing
code to actually interact with the database (The Data Access Layer). In the next project, I’ll be writing
my own code to replace the dll’s code to connect to the database. (SetFocus choose to teach Windows
Forms before ADO.NET)

User Interface
The Library system was required to perform four functions: add an adult member, add a child member,
check out a book, and check in a book. Adult and Child members differ in the information that is
collected about each type. Because only these four simple functions were needed, I chose to put a
simple ListView on the main form, with the View property set to “LargeIcon.” The main form is shown
below:
Figure 1: Main Form for the Library Application

The following forms were created for the Add Adult and Add Child functions:




                                Figure 2: Add Adult and Add Child Forms
For this project, modal feedback was discouraged, that means that it was considered unacceptable to
alert the user of an error with a MessageBox that required them to click OK to continue. An error
provider control was added to all forms to provider user feedback. A method was registered to be
called for each textbox when that textbox’s Validating event occurred (when the user moves focus away
from it). Those methods validated the data in the textbox using a function in the Business Layer, and
used the error provider to give the user an explanation of the error. An error provider displays a red
icon near the fields in error, and provides an explanation in the tooltip that the user sees when hovering
over it, as shown below:




                      Figure 3: The Error Provider at work in the Add Adult Form
The project required checking out a book to be a three step process:
1. The Librarian enters the patron’s card number, confirms the name and address, and may view
        the books already checked out by the patron.
    2. If the Patron’s card is not expired, and he or she has less than four books checked out, the
        system allows the librarian to enter identifying info for the book (ISBN and copy number). The
        librarian confirms the book’s title and author.
    3. If the book is not checked out, the librarian may check it out to the patron. If the book is
        marked as checked out (which the project requirements state happens often when a book is
        returned and re-shelved without being checked in), the librarian has the opportunity to
        automatically have it checked in and then checked out to the patron.
The following shows the book checkout form in each of the three stages of the process:
Figure 4: Three Stages of the Checkout Process

Similarly, checking in a book was a two stage process: the librarian enters the books identifying info
(ISBN and copy number), the system confirms the title and author of the book, and shows who the book
is checked out to. The librarian can then choose to check the book in or cancel. This process is
illustrated below:




                                        Figure 5: Check in process


Project 3

Overview
The purpose of project 3 was gain a solid understanding of database interactivity by using LINQ to SQL.
In Project 2, I was given compiled dlls to define the Data Access and Entities tiers for the library project.
In this project, I wrote code to produce my own dlls to replace those. Although I was required to use
LINQ to SQL in this project, I was also taught the traditional ADO.NET way of sending actual SQL
statements to the database server using connection, command and data reader objects. In fact,
SetFocus spent just as much class time teaching ADO.NET and Microsoft transact-SQL as they did with
LINQ. I understand that there are arguments for and against using LINQ. Many programmers feel LINQ
produces inefficient SQL queries that can impair performance. While SetFocus acknowledges this, they
have encouraged me and my classmates to use it because Microsoft claims great improvements will be
made to LINQ in Visual Studio 2010. Having prior experience writing SQL queries by hand, I’m willing to
take the time to use ADO.NET to manually submit queries to the database server. But I’m also eager to
see what changes are in store for LINQ in Visual Studio 2010.

The Database Structure
I was given a database structure to use for this project. This same database structure was used in
Project 2. The following diagram illustrates the most important tables:




 Figure 6: Part of database structure. (More tables were used, but these are the most relevant to the
                                         following examples.)

Each work written by an author has an entry in the title table. Each ISBN has an entry in the item table.
(So a written work might be published under multiple ISBNs, one for each translation, or cover type.)
For each ISBN one or more copies may exist in the library. A copy represents a physical book that a
patron may check out. Each member in the library has one row in the member table, and one row in
either the juvenile or adult tables. Because a juvenile’s address information is required to be the same
as the juvenile’s parent, the juvenile table contains a pointer to the juvenile’s parent so the data is not
duplicated. The following query was written to select all of the members and their information:

 SELECT
       member.member_no, firstname, middleinitial, lastname, street, city,
       state, zip, phone_no, expr_date, NULL AS adult_member, NULL AS
       birth_date, 'ADULT' AS Type
 FROM
       adult INNER JOIN member ON adult.member_no = member.member_no
 UNION
 SELECT
       juvenile.member_no, firstname, middleinitial, lastname, street, city,
       state, zip, phone_no, expr_date, adult.member_no AS adult_member,
       birth_date, 'JUVENILE' AS Type
 FROM
       juvenile INNER JOIN member ON juvenile.member_no = member.member_no
       INNER JOIN adult ON juvenile.adult_member_no = adult.member_no

                             Code Snippet 7: Query to retrieve all members

Similarly, a query was written to select all of the items (books). These queries were put into views on
the database server, and the following entities diagram was created based on those views in Visual
Studio:




                                        Figure 7: Entities Diagram
This diagram shows that Visual Studio will automatically create Item, Member, JuvenileMember, and
AdultMember classes and will automatically store data from the database in those classes when
performing a query on the DataContext. JuvenileMember and AdultMember inherit from Member, and
the properties have been set such that either a JuvenileMember or AdultMember object will be created
for each row depending on the value in the Type column. Four procedures were created on the
database server, AddAdult, AddJuvenile, CheckOutItem, and CheckInItem. Those procedures were
added to the Entities Diagram (Visual Studio does not show this graphically). A class was created in the
Data Access Layer to provide methods for the Business Layer to call to interact with the database. This
function is an example from that class that uses a LINQ query:

 public Member GetMember(int isbn, short copyNumber)
   {
   Member result;
   try
     {
     LibraryEntitiesDataContext ledc = new LibraryEntitiesDataContext();
     var query = (from m in ledc.Members
                  join i in ledc.Items on m.MemberID equals i.MemberNumber
                  where i.ISBN == isbn && i.CopyNumber == copyNumber
                  select m).Single();

      result = (Member)query;
      }
    catch (Exception ex)
      {
      throw new LibraryException(ErrorCode.NoSuchMember, ex.Message, ex);
      }
    return result;
    }



                          Code Snippet 8: LibraryDataAccess.cs Lines 121-142

This function could’ve been written using ADO.NET like this:
public Member GetMember(short memberNumber, string connectionString){
   Member result;
   SqlConnection conn = new SqlConnection(connectionString);
   conn.Open();
   SqlCommand command = conn.CreateCommand();
   command.CommandText = "SELECT * FROM Member_View WHERE member_no = " +
 memberNumber.ToString();
   SqlDataReader reader = command.ExecuteReader();
     if (reader.Read()){
       if (reader.GetString(12) == "ADULT"){
         result = new AdultMember((short)reader.GetValue(0), reader.GetString(1),
 reader.GetString(2), reader.GetString(3), reader.GetString(4),
 reader.GetString(5), reader.GetString(6), reader.GetString(7),
 reader.GetString(8), (DateTime)reader.GetValue(9));
         }
       else{
         result = new JuvenileMember((short)reader.GetValue(0),
 reader.GetString(1), reader.GetString(2), reader.GetString(3),
 reader.GetString(4), reader.GetString(5), reader.GetString(6),
 reader.GetString(7), reader.GetString(8), (DateTime)reader.GetValue(9),
 (short)reader.GetValue(10), (DateTime)reader.GetValue(11));
         }
       }
     reader.Close();
     conn.Close();
     return result;
   }


                         Code Snippet 9: Returning a Member using ADO.NET


Project 4

Overview
The purpose of this project was to master ASP.NET and gain some familiarity with Microsoft IIS. In this
final stage of the library project, I created a web based presentation layer.

A Note on Cross-Browser Compatibility
I feel the issue of cross-browser compatibility is of such importance that every web programmer should
be aware of it even if he or she is not responsible for the web design. A web site that functions properly,
but displays incorrectly can turn away users just easily as one that doesn’t function at all. Different web
browsers and even different versions of the same web browser may display a page differently. The
ASP.NET server controls render correctly in virtually every browser. A programmer who works mostly
with ASP.NET controls and rarely writes any HTML by hand may not even be aware of cross browser
display issues. Users have formed strong bonds with their favorite web browser, so asking them to use a
particular browser is usually unacceptable. Currently, statistics show that Internet Explorer and Firefox
are the most popular browsers representing nearly 90% of all internet users. Although as many
browsers as possible should be tested, a page that displays correctly in these two browsers will typically
display correctly in most other browsers.

Setting Up the Master Page
The following illustration shows the master page that I created for this site:




                                      Figure 8: MainMaster.master

The following code snippet shows the relevant CSS for the master page:
body                                        .centerColumn
            {                                           {
                font-family: Sans-Serif;                    margin-left: auto;
                background-color:                           margin-right: auto;
            #669900;                                        margin-top: 0px;
                margin: 0px;                                width: 950px;
                padding: 0px;                           }
            }                                           .leftCenterColumn
            .header                                     {
            {                                               background-color:
                margin: 0px;                            #FFFFFF;
                margin-bottom: 10px;                        width: auto;
                padding: 0px;                               margin-top: 10px;
                width: 100%;                                margin-right: 10px;
                background-color:                           border: 1px solid
            #000005;                                    #000000;
                color: #FFFFFF;                         }
            }                                           .leftCenterColumnContent
            .headerContent                              {
            {                                               margin-top: 15px;
                margin-right: auto;                         margin-bottom: 15px;
                margin-left: auto;                      }
                width: 950px;                           .rightCenterColumnContent
            }                                           {
            .patronsServed                                  margin: 15px;
            {                                           }
                font-style: italic;                     .rightCenterColumn
                margin-left: 25px;                      {
                                                            background-color:
            }                                           #FFFFFF;
            .mainTitle                                      width: auto;
            {                                               margin-top: 10px;
                margin-left: 10%;                           margin-left: 10px;
                font-size: x-large;                         border: 1px solid
            }                                           #000000;
                                                        }



                            Code Snippet 10: CSS classes for the master page

As you can see, I applied a style to the body, setting the background color to green and the font to
whatever sans-serif font the browser chooses. I set the margin and padding to 0 to ensure that
elements can reach up to the edges of the page in all browsers. The header class is used to define the
black (actually very dark blue) stripe across the top of the page. The left column contains a TreeView
control with the data source set to a SiteMapDataSource, which loads the data from a sitemap file. This
allows the links in the site map to all be specified in one XML file. centerColumn defines the main
content area in the middle of the page below the dark stripe. I chose to set this to a fixed 950 pixels.
Generally this is the only thing I would set to a fixed pixel value. The left and right columns inside of the
center column are set to widths of 20% and 80% respectively (which is a percent of the center column,
not the entire page). The center column could be set to say 90% of the page instead of 950 pixels. But
this may cause problems. For example, the left column takes up 20% of the center area or about 190
pixels. The text inside of the column fills it well. If the center column were set to a percent, its width
could easily approach 2,000 pixels on a high resolution wide screen monitor. This could cause the left
column to almost double in width, but the font would likely stay the same size. The font would appear
to take only a small part of the left column. Although this would utilize all of the available space on the
page, it would look awkward. Setting the width of the center column to a fixed width will cause wasted
space on a high resolution display, but it will ensure a uniform look for all users. Up until now, the most
common display resolution for internet users was 768 x 1024. Although display resolutions are
constantly getting higher, planning for this resolution seems to produce the best results.

Typical Page Layout
The center of the master page contains a content place holder that will contain the main part of the
page. The following illustration shows the check out page:




                                    Figure 9: Library Check out page

On this page, Label controls were used to display the library patron’s personal information. The Enter
and Select Book buttons cause a postback of the page, and the Visible property of the appropriate labels
as well as the entire Book Information fieldset is set to true or false as needed. Setting the Visible
property of an ASP.NET server control to false prevents it from being rendered. (This should not be
confused with setting the style property to “visibility: none;”, in which case, the HTML for the control is
still rendered, but the browser will not display it.) The checked out books are displayed by a GridView
control which is bound to an ObjectDataSource control. While the ObjectDataSource control could’ve
been bound to the same ItemsDataSet that was used in the Windows Forms project, additional columns
were desired in this project. In order to not break the functionality in the Windows Forms project, a
new DataSet was created in the Entities Layer. Upon binding the dataset, each value in the Due Date
column is checked and the style property of that cell is changed if the book is overdue. A script manager
was added to the page and most of the page was put inside of an UpdatePanel control. The
UpdatePanel causes ASP.NET to automatically generate Javascript to submit AJAX request to the server
such that the entire page will not reload when a control that would cause a postback is triggered. This
provides a faster response for the users, and causes a small reduction in bandwidth use.

The Modal Dialog
This project required that a Librarian be able to check out a book by entering the patron’s card number.
I felt it would also be convenient for a Librarian to look up the patron’s card number by entering his or
her name. A ModalDialog was created which appears when a user clicks the “Lookup” LinkButton and
requires the user to take action within the dialog before being able to interact with the rest of the page -
- just like a MessageBox. The following ModalDialog was created:




                           Figure 10: The ModalDialog on the check out page
The Dialog box in the center of the page was initially created as a Panel control at the bottom of the
existing page. The functionality shown above was created by simply adding a ModalPopupExtender
control to the page from the AJAX control toolkit. The properties of the ModalPopupExtender were set
to indicate which Panel control to use, which CSS classes to use for the dialog, as well as making the
outside of the dialog opaque, and to indicate which buttons on the panel are to be used for accept and
cancel. The style property of the Panel was set to “display: none;” so that the Panel’s HTML would be
rendered, but not displayed by the browser until the ModalPopupExtender’s Javascript changed it.

Within the Panel, AJAX requests were used to update the search results in the ListBox. Every time a key
is pressed in the first or last name TextBoxes, the name is sent to the server, and the server returns a list
of name/card number pairs to display in the list box. This allows the user to find a member even if he or
she only partially knows how to spell the name. The following Javascript submits the name to the
server:

  function updateResults() {
      var firstName = document.getElementById(searchFirstNameTextBox).value;
      var lastName = document.getElementById(searchLastNameTextBox).value;
      var name = firstName + "~" + lastName;
      PageMethods.GetSearchResults(name, OnSucceeded, OnFailed);
      }


                         Code Snippet 11: JavaScript function to submit names

Note that the actual ID of the text boxes is retrieved from variables. It is not possible to predict the ID
that will be used in the HTML that ASP.NET renders for the server controls. Therefore, it is necessary for
the server to generate Javascript which stores the names of the needed controls in variables for use by
the browser at runtime. The following code is contained in the server-side page markup to produce this
code:

    <script type="text/javascript" language="javascript">
        var cardNumberTextBox = '<%=cardNumberTextBox.ClientID%>';
        var searchFirstNameTextBox = '<%=searchFirstNameTextBox.ClientID%>';
        var searchLastNameTextBox = '<%=searchLastNameTextBox.ClientID%>';
        var enterButton = '<%=enterButton.ClientID%>';
    </script>


                     Code Snippet 12: Javascript to store the control IDs in variables

When the updateResults function calls the GetSearchResults function, the ScriptManager submits an
AJAX request to the server.       In order to enable this functionality, the ScriptManager’s
EnablePageMethods property must be set to true, and the method being called must be public and
static, and contain the [WebMethod] attribute which requires the System.Web.Services namespace.
The following web method was created:
[WebMethod]
   public static string GetSearchResults(string name){
       string firstName = name.Substring(0, name.IndexOf("~"));
       string lastName = name.Substring(name.IndexOf("~") + 1);
       SearchMemberDataSet sm = DataManipulator.FindMember(firstName,
   lastName);
       string output = "";
       foreach (DataRow row in sm.Tables[0].Rows){
           if (output == ""){
               output += row[0].ToString() + "~" + row[1].ToString();
               }
           else{
               output += "~" + row[0].ToString() + "~" + row[1].ToString();
               }
           }
           return output;
       }


                Code Snippet 13: Server-Side web method to return possible patrons

This method calls into the Business layer, which uses the Data Access layer to retrieve possible users.
The actual logic to choose users is contained in a new database procedure. Upon selecting a name and
clicking select, the corresponding card number will be inserted into the card number TextBox, the modal
dialog will disappear, and the Enter Button will be triggered.

Validation
Although ASP.NET offers very versatile validation controls, like the RangeValidator or
RegularExpressionValidator, the best choice for this project was the CustomValidator because the actual
validation logic was already written in the Business layer earlier. The main drawback to using the
CustomValidator is that it cannot automatically generate Javascript for client-side validation—so the
validation logic would need to be rewritten in Javascript. However, client-side validation was not
needed for this project, so this was not done. The following illustration shows how the validation
controls will appear to the user:
Figure 11: The validation controls

Each of the CustomValidators calls a validation function in the business layer to check the input. It sets
the IsValid property of the event arguments to true or false. If the input is invalid, it then sets the
validator’s error message to the value returned by the business layer.

 protected void firstNameCustomValidator_ServerValidate(object source,
 ServerValidateEventArgs args){
         string error = MW.LibraryBusiness.Validate.ValidateName(args.Value);
         if (error != ""){
             error = "First Name " + error;
         }
         firstNameCustomValidator.ErrorMessage = error;
         args.IsValid = (error == "");
     }


                              Code Snippet 14: A validation event handler
Project 5
The purpose of project 5 was to gain an understanding of the Windows Communication Foundation.
WCF allows for the creation of service projects. A service project can then be hosted in a Windows
Service or it can be hosted on a web server running IIS. Remember that in my Library project there is a
clear separation between presentation code and the logic / database interaction code. The goal of this
project was to expose the business layer code to an outside party by creating a service project that calls
into the business layer and emits the results through the service. The service was then hosted in IIS, and
the existing ASP.NET presentation layer was modified to retrieve data from the service hosted on IIS
rather than from the business directly. A service must have a defined ServiceContract that contains
DataContracts and OperationContracts to define how the service will work. These are defined by
creating an interface with abstract methods and applying the appropriate attributes as shown below:

           [ServiceContract]
           public interface ILibraryService
           {
               [FaultContract(typeof(LibraryFault))]
               [OperationContract]
               Member GetMember(short id);

                              Code Snippet 15: ServiceContract definition

Note that OperationContracts were defined for all methods in the Business Layer (not shown above).
Because a service runs in a process by itself, it cannot throw exceptions to the consuming process.
When an uncaught exception occurs in a service, a fault message is generated and sent to the
consuming process. Every method that throws a fault exception must have a FaultContract attribute as
shown above. The following class defined a custom FaultContract that was used to preserve the error
code from any LibraryExceptions that were thrown:

           [DataContract]
           public class LibraryFault{
               [DataMember]
               public string ErrorCode;

                [DataMember]
                public string Message;

                [DataMember]
                public string OtherID;
           }


                               Code Snippet 16: The custom LibraryFault

The following class was defined to implement the ILibraryService interface:
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
     public class LibraryService : ILibraryService{

     [PrincipalPermission(SecurityAction.Demand, Role = "LibraryPartner")]
     public MW.LibraryEntities.Member GetMember(short id){
         MW.LibraryEntities.Member result = null;
         try{
             result = DataManipulator.GetMember(id);
             }
         catch (LibraryException le){
             var fault = new LibraryFault();
             fault.ErrorCode = le.LibraryErrorCode.ToString();
             fault.Message = le.Message;
             fault.OtherID = le.OtherMemberID.ToString();
             throw new FaultException<LibraryFault>(fault);
             }
         catch (Exception e){
             var fault = new LibraryFault();
             fault.ErrorCode = ErrorCode.GenericException.ToString();
             fault.Message = e.Message;
             fault.OtherID = "-1";
             throw new FaultException<LibraryFault>(fault);
             }
         return result;
         }


                           Code Snippet 17: LibraryService implementation

As you can see, the implementation of the GetMember method calls into the business layer, catches any
exceptions that are thrown, and re-throws them as FaultExceptions. The service was hosted in IIS, and a
service reference was added to the ASP.NET website so that it can call into it by creating a
LibraryServiceClient object. The following code from the MainMaster.master.cs file shows a label being
populated with the total number of users in the Library:

    LibraryServiceClient proxy = new LibraryServiceClient();
    patronsServed.Text = string.Format("{0:0,0} " + patronsServed.Text,
        proxy.GetTotalMembers());
    proxy.Close();


                              Snippet 18: Using the LibraryServiceClient

More Related Content

What's hot

Jeff Huber Portfoilio
Jeff Huber PortfoilioJeff Huber Portfoilio
Jeff Huber PortfoilioJeffHuber
 
Il 09 T3 William Spreitzer
Il 09 T3 William SpreitzerIl 09 T3 William Spreitzer
Il 09 T3 William Spreitzerwspreitzer
 
Application package
Application packageApplication package
Application packageJAYAARC
 
C# .NET Developer Portfolio
C# .NET Developer PortfolioC# .NET Developer Portfolio
C# .NET Developer Portfoliocummings49
 
Microsoft� .NET and Microsoft� Office 2003
Microsoft� .NET and Microsoft� Office 2003Microsoft� .NET and Microsoft� Office 2003
Microsoft� .NET and Microsoft� Office 2003Rishi Kothari
 
Mark Jackson\'s Portfoilo
Mark Jackson\'s PortfoiloMark Jackson\'s Portfoilo
Mark Jackson\'s PortfoiloMark_Jackson
 
Developing an ASP.NET Web Application
Developing an ASP.NET Web ApplicationDeveloping an ASP.NET Web Application
Developing an ASP.NET Web ApplicationRishi Kothari
 
AD301: Introducing the Composite Application Container Framework - Lotusphere...
AD301: Introducing the Composite Application Container Framework - Lotusphere...AD301: Introducing the Composite Application Container Framework - Lotusphere...
AD301: Introducing the Composite Application Container Framework - Lotusphere...Brian O'Gorman
 
Anypointconnectordevkit 160816041722
Anypointconnectordevkit 160816041722Anypointconnectordevkit 160816041722
Anypointconnectordevkit 160816041722ppts123456
 
Silverlight 2 for Developers - TechEd New Zealand 2008
Silverlight 2 for Developers - TechEd New Zealand 2008Silverlight 2 for Developers - TechEd New Zealand 2008
Silverlight 2 for Developers - TechEd New Zealand 2008Jonas Follesø
 
Murach : How to work with session state and cookies
Murach : How to work with session state and cookiesMurach : How to work with session state and cookies
Murach : How to work with session state and cookiesMahmoudOHassouna
 
Siebel Open UI Debugging (Siebel Open UI Training, Part 7)
Siebel Open UI Debugging (Siebel Open UI Training, Part 7)Siebel Open UI Debugging (Siebel Open UI Training, Part 7)
Siebel Open UI Debugging (Siebel Open UI Training, Part 7)Tech OneStop
 
Customizing the Presentation Model and Physical Renderer in Siebel Open UI
Customizing the Presentation Model and Physical Renderer in Siebel Open UICustomizing the Presentation Model and Physical Renderer in Siebel Open UI
Customizing the Presentation Model and Physical Renderer in Siebel Open UITech OneStop
 
Asp.net architecture
Asp.net architectureAsp.net architecture
Asp.net architectureIblesoft
 

What's hot (20)

Jeff Huber Portfoilio
Jeff Huber PortfoilioJeff Huber Portfoilio
Jeff Huber Portfoilio
 
As pnet
As pnetAs pnet
As pnet
 
Mvc by asp.net development company in india - part 2
Mvc by asp.net development company in india  - part 2Mvc by asp.net development company in india  - part 2
Mvc by asp.net development company in india - part 2
 
Il 09 T3 William Spreitzer
Il 09 T3 William SpreitzerIl 09 T3 William Spreitzer
Il 09 T3 William Spreitzer
 
Application package
Application packageApplication package
Application package
 
jQuery plugins & JSON
jQuery plugins & JSONjQuery plugins & JSON
jQuery plugins & JSON
 
C# .NET Developer Portfolio
C# .NET Developer PortfolioC# .NET Developer Portfolio
C# .NET Developer Portfolio
 
Microsoft� .NET and Microsoft� Office 2003
Microsoft� .NET and Microsoft� Office 2003Microsoft� .NET and Microsoft� Office 2003
Microsoft� .NET and Microsoft� Office 2003
 
Mark Jackson\'s Portfoilo
Mark Jackson\'s PortfoiloMark Jackson\'s Portfoilo
Mark Jackson\'s Portfoilo
 
Asp.net
Asp.netAsp.net
Asp.net
 
Developing an ASP.NET Web Application
Developing an ASP.NET Web ApplicationDeveloping an ASP.NET Web Application
Developing an ASP.NET Web Application
 
AD301: Introducing the Composite Application Container Framework - Lotusphere...
AD301: Introducing the Composite Application Container Framework - Lotusphere...AD301: Introducing the Composite Application Container Framework - Lotusphere...
AD301: Introducing the Composite Application Container Framework - Lotusphere...
 
Anypointconnectordevkit 160816041722
Anypointconnectordevkit 160816041722Anypointconnectordevkit 160816041722
Anypointconnectordevkit 160816041722
 
Silverlight 2 for Developers - TechEd New Zealand 2008
Silverlight 2 for Developers - TechEd New Zealand 2008Silverlight 2 for Developers - TechEd New Zealand 2008
Silverlight 2 for Developers - TechEd New Zealand 2008
 
Asp net
Asp netAsp net
Asp net
 
Murach : How to work with session state and cookies
Murach : How to work with session state and cookiesMurach : How to work with session state and cookies
Murach : How to work with session state and cookies
 
Siebel Open UI Debugging (Siebel Open UI Training, Part 7)
Siebel Open UI Debugging (Siebel Open UI Training, Part 7)Siebel Open UI Debugging (Siebel Open UI Training, Part 7)
Siebel Open UI Debugging (Siebel Open UI Training, Part 7)
 
Customizing the Presentation Model and Physical Renderer in Siebel Open UI
Customizing the Presentation Model and Physical Renderer in Siebel Open UICustomizing the Presentation Model and Physical Renderer in Siebel Open UI
Customizing the Presentation Model and Physical Renderer in Siebel Open UI
 
Intro To C++ - Class 14 - Midterm Review
Intro To C++ - Class 14 - Midterm ReviewIntro To C++ - Class 14 - Midterm Review
Intro To C++ - Class 14 - Midterm Review
 
Asp.net architecture
Asp.net architectureAsp.net architecture
Asp.net architecture
 

Similar to .NET Portfolio

MCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISP
MCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISPMCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISP
MCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISPAli Shah
 
Overview of CSharp MVC3 and EF4
Overview of CSharp MVC3 and EF4Overview of CSharp MVC3 and EF4
Overview of CSharp MVC3 and EF4Rich Helton
 
Object-oriented programming (OOP) with Complete understanding modules
Object-oriented programming (OOP) with Complete understanding modulesObject-oriented programming (OOP) with Complete understanding modules
Object-oriented programming (OOP) with Complete understanding modulesDurgesh Singh
 
Dot Net Fundamentals
Dot Net FundamentalsDot Net Fundamentals
Dot Net FundamentalsLiquidHub
 
Patterns (contd)Software Development ProcessDesign patte.docx
Patterns (contd)Software Development ProcessDesign patte.docxPatterns (contd)Software Development ProcessDesign patte.docx
Patterns (contd)Software Development ProcessDesign patte.docxdanhaley45372
 
Redux and context api with react native app introduction, use cases, implemen...
Redux and context api with react native app introduction, use cases, implemen...Redux and context api with react native app introduction, use cases, implemen...
Redux and context api with react native app introduction, use cases, implemen...Katy Slemon
 
Android application architecture
Android application architectureAndroid application architecture
Android application architectureRomain Rochegude
 
Introduction to the INTEGRAL FRAMEWORK
Introduction to the INTEGRAL FRAMEWORKIntroduction to the INTEGRAL FRAMEWORK
Introduction to the INTEGRAL FRAMEWORKKarthik Subramanian
 
Introduction to the integral framework
Introduction to the integral frameworkIntroduction to the integral framework
Introduction to the integral frameworkKarthik Subramanian
 
Learning MVC Part 3 Creating MVC Application with EntityFramework
Learning MVC Part 3 Creating MVC Application with EntityFrameworkLearning MVC Part 3 Creating MVC Application with EntityFramework
Learning MVC Part 3 Creating MVC Application with EntityFrameworkAkhil Mittal
 
Typescript language extension of java script
Typescript language extension of java scriptTypescript language extension of java script
Typescript language extension of java scriptmichaelaaron25322
 
ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010
ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010
ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010vchircu
 
Use Eclipse technologies to build a modern embedded IDE
Use Eclipse technologies to build a modern embedded IDEUse Eclipse technologies to build a modern embedded IDE
Use Eclipse technologies to build a modern embedded IDEBenjamin Cabé
 

Similar to .NET Portfolio (20)

MCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISP
MCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISPMCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISP
MCS,BCS-7(A,B) Visual programming Syllabus for Final exams @ ISP
 
Csharp
CsharpCsharp
Csharp
 
Overview of CSharp MVC3 and EF4
Overview of CSharp MVC3 and EF4Overview of CSharp MVC3 and EF4
Overview of CSharp MVC3 and EF4
 
Object-oriented programming (OOP) with Complete understanding modules
Object-oriented programming (OOP) with Complete understanding modulesObject-oriented programming (OOP) with Complete understanding modules
Object-oriented programming (OOP) with Complete understanding modules
 
Dot Net Fundamentals
Dot Net FundamentalsDot Net Fundamentals
Dot Net Fundamentals
 
C++ Lab Maual.pdf
C++ Lab Maual.pdfC++ Lab Maual.pdf
C++ Lab Maual.pdf
 
C++ Lab Maual.pdf
C++ Lab Maual.pdfC++ Lab Maual.pdf
C++ Lab Maual.pdf
 
Patterns (contd)Software Development ProcessDesign patte.docx
Patterns (contd)Software Development ProcessDesign patte.docxPatterns (contd)Software Development ProcessDesign patte.docx
Patterns (contd)Software Development ProcessDesign patte.docx
 
Redux and context api with react native app introduction, use cases, implemen...
Redux and context api with react native app introduction, use cases, implemen...Redux and context api with react native app introduction, use cases, implemen...
Redux and context api with react native app introduction, use cases, implemen...
 
Oopp Lab Work
Oopp Lab WorkOopp Lab Work
Oopp Lab Work
 
Android application architecture
Android application architectureAndroid application architecture
Android application architecture
 
Cognos Software Development Kit
Cognos Software Development KitCognos Software Development Kit
Cognos Software Development Kit
 
Introduction to the INTEGRAL FRAMEWORK
Introduction to the INTEGRAL FRAMEWORKIntroduction to the INTEGRAL FRAMEWORK
Introduction to the INTEGRAL FRAMEWORK
 
Introduction to the integral framework
Introduction to the integral frameworkIntroduction to the integral framework
Introduction to the integral framework
 
Learning MVC Part 3 Creating MVC Application with EntityFramework
Learning MVC Part 3 Creating MVC Application with EntityFrameworkLearning MVC Part 3 Creating MVC Application with EntityFramework
Learning MVC Part 3 Creating MVC Application with EntityFramework
 
Typescript language extension of java script
Typescript language extension of java scriptTypescript language extension of java script
Typescript language extension of java script
 
T2
T2T2
T2
 
ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010
ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010
ChircuVictor StefircaMadalin rad_aspmvc3_wcf_vs2010
 
Use Eclipse technologies to build a modern embedded IDE
Use Eclipse technologies to build a modern embedded IDEUse Eclipse technologies to build a modern embedded IDE
Use Eclipse technologies to build a modern embedded IDE
 
Tdd,Ioc
Tdd,IocTdd,Ioc
Tdd,Ioc
 

.NET Portfolio

  • 1. Matt Willmer’s .NET Portfolio Matt Willmer October 28, 2008
  • 2. Summary This document contains a detailed explanation for the projects I worked on as part of the .NET Masters program at SetFocus from August 3, 2009 to October 28, 2009. A full curriculum description for this program can be found here: http://www.setfocus.com/MastersProgram/curriculum_dotnet.aspx All of these projects were completed with .NET 3.5 using Visual Studio 2008, SQL Server 2008, IIS 6.0, and Windows Server 2003. Overall Requirements SetFocus required that I use a multi-tiered programming model for all of the projects that I’ve completed. This means that each assignment was divided into at least one Visual Studio project for each tier. The following is an example of the tiers that I used: Data Access Tier – A class library consisting of all of the code needed to interact with the database server. Generally, no other layer should contain any database interface code. Business Tier – A class library serving as a link to process and pass data between the Data Access and Presentation layers. Presentation Tier – A Windows Forms application or ASP.NET web application containing all of the code to display information to the user, and receive and validate user input. Entities Tier – A class library consisting of classes that define objects used to pass data. This tier is used by all other tiers. Typically the Data Access Tier will retrieve data from a database and use it to populate properties in objects defined in the Entities Tier. Those objects are passed through the Business Tier to the Presentation Tier to be consumed. When using LINQ to SQL, this tier is automatically generated by Visual Studio based on the database design, so it’s not always clearly separated from the Data Access Tier. Project 1 Overview The purpose of this project was to get familiar with coding in C#, especially with some of the features that make it unique from other languages like C++ or Java. This project was short and pretty simple--I was given a very detailed textual description of all of the needed classes and interfaces for a plausible business layer for a retail company. I put those specifications into code, and used a provided test dll to ensure that the classes functioned properly. The best way to see how these interact with each other would be to open the project in Visual Studio and use the Object Browser to look at their properties and methods. But since I didn’t design the class structure (I only coded it), I’ll select code snippets from the project to illustrate what I learned. C# Properties While instance variables (or fields) can be used to store data in a class in most programming languages, C# also provides a feature called Properties to enhance this. A public property can be accessed from
  • 3. outside of a class in the same way that a field would be accessed, but with a property the programmer can specify code to run at the time the property is set or read through a set and get method. These come in handy when validating data or when the data comes from some internal structure that must be private. Additionally, the get and set methods for a public property can be set to private to make the property read-only or write-only. The following code snippet illustrates this: protected decimal unitPrice; public decimal UnitPrice{ get { return unitPrice; } set { if (value < 0.0m){ throw new ArgumentOutOfRangeException("UnitPrice", "UnitPrice cannot be less than 0."); } unitPrice = value; } } Code Snippet 1: AppTypesProduct.cs Lines 108 – 122 Working with System.Runtime.InteropServices.IEnumerator Enumerators allow a programmer to retrieve a series of values in a given order, one by one, often with a foreach loop. One way to produce an object of type IEnumerable is to inherit from it, and implement its methods to return values, and adjust the current value index. Another way is to use the yield return statement. The yield return statement defines the next value that will be returned by the iterator. This code snippet shows the yield return statement used to produce an IEnumerable that returns each of the properties stored in this class, one by one: public IEnumerable PropertyAndValuesCollection() { yield return String.Format("ID: {0}", ID); yield return String.Format("CompanyName: {0}", CompanyName); yield return String.Format("ContactName: {0}", ContactName); yield return String.Format("ContactTitle: {0}", ContactTitle); yield return String.Format("Address: {0}", Address); yield return String.Format("City: {0}", City); yield return String.Format("Region: {0}", Region); yield return String.Format("PostalCode: {0}", PostalCode); yield return String.Format("Country: {0}", Country); yield return String.Format("Phone: {0}", Phone); yield return String.Format("Fax: {0}", Fax); yield return String.Format("HomePage: {0}", HomePage); yield return String.Format("Type: {0}", Type); } //This allows a programmer to write foreach (string s in PropertyAndValuesCollection() { Console.WriteLine(s); } Code Snippet 2: AppTypesSupplier.cs Lines 127 - 142
  • 4. Enumerators also come in handy when using LINQ, which I’ll talk about in Project 3. Comparing Objects Like C++, C# allows for operator overloading to perform math and Boolean operations on objects. The following code snippet shows the == operator overloaded: public static bool operator == (Supplier sup1, Supplier sup2){ if (object.ReferenceEquals(sup1, null) && object.ReferenceEquals(sup2, null)) { return true; } if (object.ReferenceEquals(sup1, null) || object.ReferenceEquals(sup2, null)) { return false; } return sup1.Equals(sup2); } Code Snippet 3: AppTypesSupplier.cs Lines 144 – 154 It’s important to note that some other.NET languages (Visual Basic, in particular) do not support operator overloading. Therefore, it’s always best to override the object.Equals() method as well. As you can see from the code snippet, the actual comparison of Supplier objects is being done by the Equals method (Which has been overridden, but not shown). It’s best to only implement the actual comparison code once in the Equals method. Also note that when checking for null input references object.ReferenceEquals() must be used so the operator function does not become recursive. The == method requires != to be overloaded as well (which isn’t shown in the snippet). Delegates and Events Events can be used to alert other objects that something has occurred without necessarily knowing what those objects are. They’re most common in programming user interfaces, although Visual Studio writes them automatically. There are some situations where a programmer may want to use his or her own event. First, a delegate must be declared: public delegate void CollectionModifiedHandler(object sender, ModificationEventArgs args); Code Snippet 4: AppTypesCollectionModifiedHandler.cs Line 8 An event was declared in the class that will broadcast the event, and the event was checked for a null value before calling it. An event will be set to a null value before any other classes have registered to receive it:
  • 5. public event CollectionModifiedHandler CollectionModified; private void OnCollectionModified(ModificationEventArgs args){ if (CollectionModified != null) CollectionModified(this, args); } Code Snippet 5: AppTypesProducts.cs Lines 21 – 29 An object can register to receive the event like this: public void Register(Products pros) { pros.CollectionModified += new CollectionModifiedHandler(pros_CollectionModified); } public void pros_CollectionModified(object sender, ModificationEventArgs args) { lastEventDetails = "Modification Attempted " + args.ModificationEventStatus.ToString() + " " + args.ModifiedObjectReference.ToString(); } Code Snippet 6: AppTypesEventLogger.cs Lines 17 - 24 There are a lot of other small things I learned in this lab, like Attributes and Serialization. These are rather straightforward, so I won’t go into them in detail. Project 2 Overview The purpose of the second project was to gain a solid understanding of Windows Forms programming, and become familiar with as many controls from the Visual Studio Toolbox as possible. For this project, I wrote the Business and Presentation Layers for a plausible public lending library application. I was provided with a database structure, a script to populate the database with test data, and a dll containing code to actually interact with the database (The Data Access Layer). In the next project, I’ll be writing my own code to replace the dll’s code to connect to the database. (SetFocus choose to teach Windows Forms before ADO.NET) User Interface The Library system was required to perform four functions: add an adult member, add a child member, check out a book, and check in a book. Adult and Child members differ in the information that is collected about each type. Because only these four simple functions were needed, I chose to put a simple ListView on the main form, with the View property set to “LargeIcon.” The main form is shown below:
  • 6. Figure 1: Main Form for the Library Application The following forms were created for the Add Adult and Add Child functions: Figure 2: Add Adult and Add Child Forms For this project, modal feedback was discouraged, that means that it was considered unacceptable to alert the user of an error with a MessageBox that required them to click OK to continue. An error provider control was added to all forms to provider user feedback. A method was registered to be called for each textbox when that textbox’s Validating event occurred (when the user moves focus away from it). Those methods validated the data in the textbox using a function in the Business Layer, and used the error provider to give the user an explanation of the error. An error provider displays a red icon near the fields in error, and provides an explanation in the tooltip that the user sees when hovering over it, as shown below: Figure 3: The Error Provider at work in the Add Adult Form The project required checking out a book to be a three step process:
  • 7. 1. The Librarian enters the patron’s card number, confirms the name and address, and may view the books already checked out by the patron. 2. If the Patron’s card is not expired, and he or she has less than four books checked out, the system allows the librarian to enter identifying info for the book (ISBN and copy number). The librarian confirms the book’s title and author. 3. If the book is not checked out, the librarian may check it out to the patron. If the book is marked as checked out (which the project requirements state happens often when a book is returned and re-shelved without being checked in), the librarian has the opportunity to automatically have it checked in and then checked out to the patron. The following shows the book checkout form in each of the three stages of the process:
  • 8. Figure 4: Three Stages of the Checkout Process Similarly, checking in a book was a two stage process: the librarian enters the books identifying info (ISBN and copy number), the system confirms the title and author of the book, and shows who the book is checked out to. The librarian can then choose to check the book in or cancel. This process is illustrated below: Figure 5: Check in process Project 3 Overview The purpose of project 3 was gain a solid understanding of database interactivity by using LINQ to SQL. In Project 2, I was given compiled dlls to define the Data Access and Entities tiers for the library project. In this project, I wrote code to produce my own dlls to replace those. Although I was required to use LINQ to SQL in this project, I was also taught the traditional ADO.NET way of sending actual SQL statements to the database server using connection, command and data reader objects. In fact,
  • 9. SetFocus spent just as much class time teaching ADO.NET and Microsoft transact-SQL as they did with LINQ. I understand that there are arguments for and against using LINQ. Many programmers feel LINQ produces inefficient SQL queries that can impair performance. While SetFocus acknowledges this, they have encouraged me and my classmates to use it because Microsoft claims great improvements will be made to LINQ in Visual Studio 2010. Having prior experience writing SQL queries by hand, I’m willing to take the time to use ADO.NET to manually submit queries to the database server. But I’m also eager to see what changes are in store for LINQ in Visual Studio 2010. The Database Structure I was given a database structure to use for this project. This same database structure was used in Project 2. The following diagram illustrates the most important tables: Figure 6: Part of database structure. (More tables were used, but these are the most relevant to the following examples.) Each work written by an author has an entry in the title table. Each ISBN has an entry in the item table. (So a written work might be published under multiple ISBNs, one for each translation, or cover type.) For each ISBN one or more copies may exist in the library. A copy represents a physical book that a patron may check out. Each member in the library has one row in the member table, and one row in either the juvenile or adult tables. Because a juvenile’s address information is required to be the same
  • 10. as the juvenile’s parent, the juvenile table contains a pointer to the juvenile’s parent so the data is not duplicated. The following query was written to select all of the members and their information: SELECT member.member_no, firstname, middleinitial, lastname, street, city, state, zip, phone_no, expr_date, NULL AS adult_member, NULL AS birth_date, 'ADULT' AS Type FROM adult INNER JOIN member ON adult.member_no = member.member_no UNION SELECT juvenile.member_no, firstname, middleinitial, lastname, street, city, state, zip, phone_no, expr_date, adult.member_no AS adult_member, birth_date, 'JUVENILE' AS Type FROM juvenile INNER JOIN member ON juvenile.member_no = member.member_no INNER JOIN adult ON juvenile.adult_member_no = adult.member_no Code Snippet 7: Query to retrieve all members Similarly, a query was written to select all of the items (books). These queries were put into views on the database server, and the following entities diagram was created based on those views in Visual Studio: Figure 7: Entities Diagram
  • 11. This diagram shows that Visual Studio will automatically create Item, Member, JuvenileMember, and AdultMember classes and will automatically store data from the database in those classes when performing a query on the DataContext. JuvenileMember and AdultMember inherit from Member, and the properties have been set such that either a JuvenileMember or AdultMember object will be created for each row depending on the value in the Type column. Four procedures were created on the database server, AddAdult, AddJuvenile, CheckOutItem, and CheckInItem. Those procedures were added to the Entities Diagram (Visual Studio does not show this graphically). A class was created in the Data Access Layer to provide methods for the Business Layer to call to interact with the database. This function is an example from that class that uses a LINQ query: public Member GetMember(int isbn, short copyNumber) { Member result; try { LibraryEntitiesDataContext ledc = new LibraryEntitiesDataContext(); var query = (from m in ledc.Members join i in ledc.Items on m.MemberID equals i.MemberNumber where i.ISBN == isbn && i.CopyNumber == copyNumber select m).Single(); result = (Member)query; } catch (Exception ex) { throw new LibraryException(ErrorCode.NoSuchMember, ex.Message, ex); } return result; } Code Snippet 8: LibraryDataAccess.cs Lines 121-142 This function could’ve been written using ADO.NET like this:
  • 12. public Member GetMember(short memberNumber, string connectionString){ Member result; SqlConnection conn = new SqlConnection(connectionString); conn.Open(); SqlCommand command = conn.CreateCommand(); command.CommandText = "SELECT * FROM Member_View WHERE member_no = " + memberNumber.ToString(); SqlDataReader reader = command.ExecuteReader(); if (reader.Read()){ if (reader.GetString(12) == "ADULT"){ result = new AdultMember((short)reader.GetValue(0), reader.GetString(1), reader.GetString(2), reader.GetString(3), reader.GetString(4), reader.GetString(5), reader.GetString(6), reader.GetString(7), reader.GetString(8), (DateTime)reader.GetValue(9)); } else{ result = new JuvenileMember((short)reader.GetValue(0), reader.GetString(1), reader.GetString(2), reader.GetString(3), reader.GetString(4), reader.GetString(5), reader.GetString(6), reader.GetString(7), reader.GetString(8), (DateTime)reader.GetValue(9), (short)reader.GetValue(10), (DateTime)reader.GetValue(11)); } } reader.Close(); conn.Close(); return result; } Code Snippet 9: Returning a Member using ADO.NET Project 4 Overview The purpose of this project was to master ASP.NET and gain some familiarity with Microsoft IIS. In this final stage of the library project, I created a web based presentation layer. A Note on Cross-Browser Compatibility I feel the issue of cross-browser compatibility is of such importance that every web programmer should be aware of it even if he or she is not responsible for the web design. A web site that functions properly, but displays incorrectly can turn away users just easily as one that doesn’t function at all. Different web browsers and even different versions of the same web browser may display a page differently. The ASP.NET server controls render correctly in virtually every browser. A programmer who works mostly with ASP.NET controls and rarely writes any HTML by hand may not even be aware of cross browser display issues. Users have formed strong bonds with their favorite web browser, so asking them to use a particular browser is usually unacceptable. Currently, statistics show that Internet Explorer and Firefox are the most popular browsers representing nearly 90% of all internet users. Although as many
  • 13. browsers as possible should be tested, a page that displays correctly in these two browsers will typically display correctly in most other browsers. Setting Up the Master Page The following illustration shows the master page that I created for this site: Figure 8: MainMaster.master The following code snippet shows the relevant CSS for the master page:
  • 14. body .centerColumn { { font-family: Sans-Serif; margin-left: auto; background-color: margin-right: auto; #669900; margin-top: 0px; margin: 0px; width: 950px; padding: 0px; } } .leftCenterColumn .header { { background-color: margin: 0px; #FFFFFF; margin-bottom: 10px; width: auto; padding: 0px; margin-top: 10px; width: 100%; margin-right: 10px; background-color: border: 1px solid #000005; #000000; color: #FFFFFF; } } .leftCenterColumnContent .headerContent { { margin-top: 15px; margin-right: auto; margin-bottom: 15px; margin-left: auto; } width: 950px; .rightCenterColumnContent } { .patronsServed margin: 15px; { } font-style: italic; .rightCenterColumn margin-left: 25px; { background-color: } #FFFFFF; .mainTitle width: auto; { margin-top: 10px; margin-left: 10%; margin-left: 10px; font-size: x-large; border: 1px solid } #000000; } Code Snippet 10: CSS classes for the master page As you can see, I applied a style to the body, setting the background color to green and the font to whatever sans-serif font the browser chooses. I set the margin and padding to 0 to ensure that elements can reach up to the edges of the page in all browsers. The header class is used to define the black (actually very dark blue) stripe across the top of the page. The left column contains a TreeView control with the data source set to a SiteMapDataSource, which loads the data from a sitemap file. This allows the links in the site map to all be specified in one XML file. centerColumn defines the main content area in the middle of the page below the dark stripe. I chose to set this to a fixed 950 pixels. Generally this is the only thing I would set to a fixed pixel value. The left and right columns inside of the center column are set to widths of 20% and 80% respectively (which is a percent of the center column, not the entire page). The center column could be set to say 90% of the page instead of 950 pixels. But this may cause problems. For example, the left column takes up 20% of the center area or about 190
  • 15. pixels. The text inside of the column fills it well. If the center column were set to a percent, its width could easily approach 2,000 pixels on a high resolution wide screen monitor. This could cause the left column to almost double in width, but the font would likely stay the same size. The font would appear to take only a small part of the left column. Although this would utilize all of the available space on the page, it would look awkward. Setting the width of the center column to a fixed width will cause wasted space on a high resolution display, but it will ensure a uniform look for all users. Up until now, the most common display resolution for internet users was 768 x 1024. Although display resolutions are constantly getting higher, planning for this resolution seems to produce the best results. Typical Page Layout The center of the master page contains a content place holder that will contain the main part of the page. The following illustration shows the check out page: Figure 9: Library Check out page On this page, Label controls were used to display the library patron’s personal information. The Enter and Select Book buttons cause a postback of the page, and the Visible property of the appropriate labels as well as the entire Book Information fieldset is set to true or false as needed. Setting the Visible property of an ASP.NET server control to false prevents it from being rendered. (This should not be confused with setting the style property to “visibility: none;”, in which case, the HTML for the control is
  • 16. still rendered, but the browser will not display it.) The checked out books are displayed by a GridView control which is bound to an ObjectDataSource control. While the ObjectDataSource control could’ve been bound to the same ItemsDataSet that was used in the Windows Forms project, additional columns were desired in this project. In order to not break the functionality in the Windows Forms project, a new DataSet was created in the Entities Layer. Upon binding the dataset, each value in the Due Date column is checked and the style property of that cell is changed if the book is overdue. A script manager was added to the page and most of the page was put inside of an UpdatePanel control. The UpdatePanel causes ASP.NET to automatically generate Javascript to submit AJAX request to the server such that the entire page will not reload when a control that would cause a postback is triggered. This provides a faster response for the users, and causes a small reduction in bandwidth use. The Modal Dialog This project required that a Librarian be able to check out a book by entering the patron’s card number. I felt it would also be convenient for a Librarian to look up the patron’s card number by entering his or her name. A ModalDialog was created which appears when a user clicks the “Lookup” LinkButton and requires the user to take action within the dialog before being able to interact with the rest of the page - - just like a MessageBox. The following ModalDialog was created: Figure 10: The ModalDialog on the check out page
  • 17. The Dialog box in the center of the page was initially created as a Panel control at the bottom of the existing page. The functionality shown above was created by simply adding a ModalPopupExtender control to the page from the AJAX control toolkit. The properties of the ModalPopupExtender were set to indicate which Panel control to use, which CSS classes to use for the dialog, as well as making the outside of the dialog opaque, and to indicate which buttons on the panel are to be used for accept and cancel. The style property of the Panel was set to “display: none;” so that the Panel’s HTML would be rendered, but not displayed by the browser until the ModalPopupExtender’s Javascript changed it. Within the Panel, AJAX requests were used to update the search results in the ListBox. Every time a key is pressed in the first or last name TextBoxes, the name is sent to the server, and the server returns a list of name/card number pairs to display in the list box. This allows the user to find a member even if he or she only partially knows how to spell the name. The following Javascript submits the name to the server: function updateResults() { var firstName = document.getElementById(searchFirstNameTextBox).value; var lastName = document.getElementById(searchLastNameTextBox).value; var name = firstName + "~" + lastName; PageMethods.GetSearchResults(name, OnSucceeded, OnFailed); } Code Snippet 11: JavaScript function to submit names Note that the actual ID of the text boxes is retrieved from variables. It is not possible to predict the ID that will be used in the HTML that ASP.NET renders for the server controls. Therefore, it is necessary for the server to generate Javascript which stores the names of the needed controls in variables for use by the browser at runtime. The following code is contained in the server-side page markup to produce this code: <script type="text/javascript" language="javascript"> var cardNumberTextBox = '<%=cardNumberTextBox.ClientID%>'; var searchFirstNameTextBox = '<%=searchFirstNameTextBox.ClientID%>'; var searchLastNameTextBox = '<%=searchLastNameTextBox.ClientID%>'; var enterButton = '<%=enterButton.ClientID%>'; </script> Code Snippet 12: Javascript to store the control IDs in variables When the updateResults function calls the GetSearchResults function, the ScriptManager submits an AJAX request to the server. In order to enable this functionality, the ScriptManager’s EnablePageMethods property must be set to true, and the method being called must be public and static, and contain the [WebMethod] attribute which requires the System.Web.Services namespace. The following web method was created:
  • 18. [WebMethod] public static string GetSearchResults(string name){ string firstName = name.Substring(0, name.IndexOf("~")); string lastName = name.Substring(name.IndexOf("~") + 1); SearchMemberDataSet sm = DataManipulator.FindMember(firstName, lastName); string output = ""; foreach (DataRow row in sm.Tables[0].Rows){ if (output == ""){ output += row[0].ToString() + "~" + row[1].ToString(); } else{ output += "~" + row[0].ToString() + "~" + row[1].ToString(); } } return output; } Code Snippet 13: Server-Side web method to return possible patrons This method calls into the Business layer, which uses the Data Access layer to retrieve possible users. The actual logic to choose users is contained in a new database procedure. Upon selecting a name and clicking select, the corresponding card number will be inserted into the card number TextBox, the modal dialog will disappear, and the Enter Button will be triggered. Validation Although ASP.NET offers very versatile validation controls, like the RangeValidator or RegularExpressionValidator, the best choice for this project was the CustomValidator because the actual validation logic was already written in the Business layer earlier. The main drawback to using the CustomValidator is that it cannot automatically generate Javascript for client-side validation—so the validation logic would need to be rewritten in Javascript. However, client-side validation was not needed for this project, so this was not done. The following illustration shows how the validation controls will appear to the user:
  • 19. Figure 11: The validation controls Each of the CustomValidators calls a validation function in the business layer to check the input. It sets the IsValid property of the event arguments to true or false. If the input is invalid, it then sets the validator’s error message to the value returned by the business layer. protected void firstNameCustomValidator_ServerValidate(object source, ServerValidateEventArgs args){ string error = MW.LibraryBusiness.Validate.ValidateName(args.Value); if (error != ""){ error = "First Name " + error; } firstNameCustomValidator.ErrorMessage = error; args.IsValid = (error == ""); } Code Snippet 14: A validation event handler
  • 20. Project 5 The purpose of project 5 was to gain an understanding of the Windows Communication Foundation. WCF allows for the creation of service projects. A service project can then be hosted in a Windows Service or it can be hosted on a web server running IIS. Remember that in my Library project there is a clear separation between presentation code and the logic / database interaction code. The goal of this project was to expose the business layer code to an outside party by creating a service project that calls into the business layer and emits the results through the service. The service was then hosted in IIS, and the existing ASP.NET presentation layer was modified to retrieve data from the service hosted on IIS rather than from the business directly. A service must have a defined ServiceContract that contains DataContracts and OperationContracts to define how the service will work. These are defined by creating an interface with abstract methods and applying the appropriate attributes as shown below: [ServiceContract] public interface ILibraryService { [FaultContract(typeof(LibraryFault))] [OperationContract] Member GetMember(short id); Code Snippet 15: ServiceContract definition Note that OperationContracts were defined for all methods in the Business Layer (not shown above). Because a service runs in a process by itself, it cannot throw exceptions to the consuming process. When an uncaught exception occurs in a service, a fault message is generated and sent to the consuming process. Every method that throws a fault exception must have a FaultContract attribute as shown above. The following class defined a custom FaultContract that was used to preserve the error code from any LibraryExceptions that were thrown: [DataContract] public class LibraryFault{ [DataMember] public string ErrorCode; [DataMember] public string Message; [DataMember] public string OtherID; } Code Snippet 16: The custom LibraryFault The following class was defined to implement the ILibraryService interface:
  • 21. [ServiceBehavior(IncludeExceptionDetailInFaults = true)] public class LibraryService : ILibraryService{ [PrincipalPermission(SecurityAction.Demand, Role = "LibraryPartner")] public MW.LibraryEntities.Member GetMember(short id){ MW.LibraryEntities.Member result = null; try{ result = DataManipulator.GetMember(id); } catch (LibraryException le){ var fault = new LibraryFault(); fault.ErrorCode = le.LibraryErrorCode.ToString(); fault.Message = le.Message; fault.OtherID = le.OtherMemberID.ToString(); throw new FaultException<LibraryFault>(fault); } catch (Exception e){ var fault = new LibraryFault(); fault.ErrorCode = ErrorCode.GenericException.ToString(); fault.Message = e.Message; fault.OtherID = "-1"; throw new FaultException<LibraryFault>(fault); } return result; } Code Snippet 17: LibraryService implementation As you can see, the implementation of the GetMember method calls into the business layer, catches any exceptions that are thrown, and re-throws them as FaultExceptions. The service was hosted in IIS, and a service reference was added to the ASP.NET website so that it can call into it by creating a LibraryServiceClient object. The following code from the MainMaster.master.cs file shows a label being populated with the total number of users in the Library: LibraryServiceClient proxy = new LibraryServiceClient(); patronsServed.Text = string.Format("{0:0,0} " + patronsServed.Text, proxy.GetTotalMembers()); proxy.Close(); Snippet 18: Using the LibraryServiceClient