• Save
.NET Project Manual
Upcoming SlideShare
Loading in...5
×
 

.NET Project Manual

on

  • 1,414 views

This was a multi-phase project in the various .NET technologies using C# and Visual Studio. This set of projects was created to support the principal functions of a lending library’s day-to-day ...

This was a multi-phase project in the various .NET technologies using C# and Visual Studio. This set of projects was created to support the principal functions of a lending library’s day-to-day operations. TECHNOLOGIES USED: .NET with C#; Windows Forms Programming; Regular Expressions; ADO.NET; SQL Server 2000; Transact SQL (Stored Procedures); ASP.NET; ASP.NET Security; Web Services; XML; SOAP; WSE 3.0.

Statistics

Views

Total Views
1,414
Views on SlideShare
1,406
Embed Views
8

Actions

Likes
0
Downloads
0
Comments
0

2 Embeds 8

http://www.linkedin.com 6
http://www.lmodules.com 2

Accessibility

Categories

Upload Details

Uploaded via as Microsoft Word

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

.NET Project Manual .NET Project Manual Document Transcript

  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe .NET Library Project Cormac Sharpe 1
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Table of Contents Library Project Overview.....................................................................................................................................3 Project Phase Overview.........................................................................................................................................4 Phase 1 - Windows Front-End Application.........................................................................................................5 Check In an Item:................................................................................................................................................5 Member Information............................................................................................................................................5 Check in an Item for a given member:................................................................................................................7 Juvenile Member Info..........................................................................................................................................9 Add New Adult...................................................................................................................................................10 Add New Juvenile..............................................................................................................................................11 Check Out an Item:............................................................................................................................................13 Phase 2 – Business & Data Access Tiers............................................................................................................15 Business Layer Code Samples...........................................................................................................................15 GetMyItems(MemberID)...............................................................................................................................15 AddMyMember(Member).............................................................................................................................16 Data Access Layer Code Samples.....................................................................................................................17 AddMember(AdultMember)..........................................................................................................................17 Stored Procedure usp_AddAdult...................................................................................................................18 GetItem(isbn, copyNumber)..........................................................................................................................19 Entities Code Samples.......................................................................................................................................20 Class Member................................................................................................................................................20 Class LibraryException..................................................................................................................................20 Phase 3 – Web Application..................................................................................................................................21 “Get Member Info” Page..................................................................................................................................22 “Member Info” Page.........................................................................................................................................22 “Get Book Info” Page.......................................................................................................................................26 “Book Info” Page..............................................................................................................................................28 Phase 4 – Web Services........................................................................................................................................29 Note: .................................................................................................................................................................29 A Web-based (ASP.NET) client was provided as the starting point for the front-end to communicate with the web service. This was another separate implemenation of what I produced in Phase 3.................................29 Server-side Code Samples - The Service Class.................................................................................................30 Client-side Code Samples - The AddAdult Page...............................................................................................31 2
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Library Project Overview Note: In Phase 3, a web- based front end is designed and implemented. Phase 4 goes further and provides the functionality as a Web Service. Note: Library Entities is a separate assembly containing the classes that define the various Entities involved in the Library Project, including Member, Adult Member, Juvenile Member, Item, Item Dataset, LibraryException. This was a multi-phase project in the various .NET technologies using C# and Visual Studio. This set of projects was created to support the principal functions of a lending library’s day-to-day operations. TECHNOLOGIES USED: .NET with C#; Windows Forms Programming; Regular Expressions; ADO.NET; SQL Server 2000; Transact SQL (Stored Procedures); ASP.NET; ASP.NET Security; Web Services; XML; SOAP; WSE 3.0. 3
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Project Phase Overview Phase Objective Technologies used Phase 1 In this phase, the Database, Data Access Layer, .NET with C#; and Library Entities were already provided. So this Windows Forms phase involved the development of the front-end Programming; Windows layer (tier) and a business logic layer. Regular Front-End • Design and develop an intuitive Windows Forms- Expressions. Application based front-end application that that will provide a librarian with a visual interface through which he or she may perform the desired functions. • Provide validation for all required fields, and adequate error handling. Phase 2 • Design and implement a Data Access tier using .NET with C#; ADO.NET to replace the assembly provided in ADO.NET; Phase 1. SQL Server Business • Provide Stored Procedures to be used by the new 2000; & Data Access tier. The Data Access tier should not Transact SQL Data Access contain any SQL statements. (Stored Tiers • Retool Business tier to use new Data Access tier. Procedures). • Design and implement a Library Entities assembly to replace the assembly provided in Phase 1. Phase 3 • Create a web application that supports all the .NET with C#; functionality required for Phase I and II of the ASP.NET; Library project. ASP.NET Web • Provide Authentication/Security using ASP.NET Security. Application Membership & Role Management. Phase 4 • Take the library system to the next level – allow .NET with C#; interoperability with other systems. ASP.NET; • Create a Web service that calls into the business Web Services; Web layer. XML; Services • Update the presentation (UI) layer to call the SOAP; Web Service, and support previous project WSE 3.0. functionality. • Employ WSE 3.0 security using Certificates. Signing, encryption and secure session are required. 4
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Phase 1 - Windows Front-End Application Overview: Objective: In this phase, the Database, Data Access Layer, and Library Entities were provided. So this phase involved the development of the front-end layer (tier) and a business logic layer. • Design and develop an intuitive Windows Forms-based front-end application that that will provide a librarian with a visual interface through which he or she may perform the desired functions. • Provide validation for all required fields, and adequate error handling. Technologies used: .NET & C# Windows Programming Regular Expressions Check In an Item: MDI Interface with Parent & child forms. Menu bar to Navigate through various functions Status Bar to communicate Status and/or input errors to the User. In the above case, we tried to check in a book that was not on loan, and received an error message. So we choose ISBN 100, Copy # 1 instead, and we can confirm or cancel the Check In. Member Information Note the additional “New Adult Member” & “New Juvenile Member” functions available in the Members Screen. 5
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe After we click on Members … … the default function “Find Member” is displayed, and a member is found by entering the Card #…. FIND MEMBER: Note: it could be an adult or a juvenile. We have 3 classes: Member, and then 2 derived classes AdultMember & JuvenileMember that inherit from Member. private void btnFindMember_Click(object sender, EventArgs e) { //Check txtMemberID: bool parseOK = Int16.TryParse(txtMemberID.Text, out intMemberID); if (!parseOK) { DisplayStatus("Bad Number! Please enter a Valid Card Number."); return; } Instantiate Business Layer // Business Layer //Get Member: does all relevant BusinessLayer bizLayer = new BusinessLayer(); error checking member = bizLayer.GetMyMember(intMemberID, out resultOK); and passes the if (!resultOK) result back { though variables DisplayStatus(bizLayer.ErrorMessage); resultOK and return; ErrorMessage. } The code then determines that Member ID 1 is an Adult Member and displays the member info with the line: ShowInterface(member, Action.ShowAdult); } … and the Member Info is displayed (in this case an Adult Member) with <Check In> and <Check Out> functions shown … 6
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe DataGridView control to manage book loan information. This Member has 2 books on Loan. Check in an Item for a given member: In the above example, the User has clicked on <Check In> without properly selecting a book to check in, so receives an error message. After correcting the error, the User tries again, and gets the option to confirm or back out of the CheckIn. 7
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe CHECK IN AN ITEM FROM THE MEMBERS SCREEN: private void btnCheckIn_Click(object sender, EventArgs e) { string msg; string msg2; Handle selected rows bool resultOK; in the DataGridView. // if (dgItems.SelectedRows.Count == 0) { DisplayStatus("Can't Check In - You need to Select an Item First!"); return; } foreach (DataGridViewRow dgvRow in dgItems.SelectedRows) { DataGridViewCellCollection coll = dgvRow.Cells; // //Handle nulls //(happens if user has highlighted the new row at the end) if (!(coll[0].Value == null)) { int isbn = int.Parse(coll[0].Value.ToString()); short copy = short.Parse(coll[1].Value.ToString()); string title = coll[2].Value.ToString(); // //Ask if User wants to Check it in: msg = "Do you want to Check In: "; msg += title + ", Copy # "; msg += copy.ToString() + "?"; if (MessageBox.Show(msg, "Confirm Check In:", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) { //Check it in: Instantiate BusinessLayer bizLayer = new BusinessLayer(); Business resultOK = bizLayer.CheckInMyItem(isbn, copy); Layer and use if (!resultOK) { it to check in DisplayStatus(bizLayer.ErrorMessage); the book. return; } } } } //Refresh the grid: if (!BindGrid(intMemberID, out msg2)) { DisplayStatus(msg2); return; } } 8
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Juvenile Member Info If we search for Member ID (card#) 10, we find that this is a juvenile Member … The only Member Info stored for a Juvenile is Name, Birthday, and the Parent’s Member ID. However this blue panel also displays the Parent’s member info. Notice that the Parents card is flagged as expired No books on loan for this Member. 9
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Add New Adult Combobox control loaded from XML file. Input Validation using an Error- When the Provider mouse control … hovers over the Error- Provider … and the control, it status bar. shows the error message, which is provided using REGEX (Regular Expressions) pattern matching. Set up Regular Expressions for Screen Validation, in the constructor of the MembersForm class - MembersForm: // set up validation regular expressions this.txtFirstName.Tag = new PatternAndMessage(@"^[A-Z][a-z]{0,14}$", "First Name must be all letters, first uppercase, " + "all others lowercase, maximum 15 letters."); PatternAndMessage is a helper object for associating a regular expression with an error message Load the “States” combobox from the XML file in MembersForm_Load(): DataSet statesInfo = StatesData.GetStates(); // bind the State table in the dataset to the combobox this.cbxState.DataSource = statesInfo.Tables["State"]; // tell the combobox to display the state Abbreviation this.cbxState.DisplayMember = "Abbreviation"; // tell the combobox to use the abbreviation as the value this.cbxState.ValueMember = "Abbreviation"; 10
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Add New Juvenile To add a new Juvenile member, first we need to specify an adult member who will be responsible … In the above case, the User entered ID 10, which is that of a juvenile, so the input is rejected with an error message. When an Adult ID is entered, we get the following screen … Click <Add Member>, and we are then ready to check out books for the new member … 11
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe ADD NEW JUVENILE MEMBER: private void btnAddNewMember_Click(object sender, EventArgs e) { …Validate input … Instantiate a try Business layer { // Instantiate a Business Layer: object. BusinessLayer bizLayer = new BusinessLayer(); // //If Adult: if (whatTypeOfMember == TypeOfMember.Adult) { … } Instantiate and //If Juvenile: populate a new else JuvenileMember { object. //Instantiate and Populate: //(Assumes Thorough Validation first in the form) JuvenileMember juv = new JuvenileMember(); juv.FirstName = this.txtFirstName.Text; juv.LastName = this.txtLastName.Text; juv.MiddleInitial = this.txtMiddleInitial.Text; juv.AdultMemberID = (short)Convert.ToInt16(this.txtMemberID.Text); juv.BirthDate = this.dateTimePicker1.Value; // //Add the Member: Add the Juvenile member if (!bizLayer.AddMyMember(juv)) to the Database using the { Business Layer. DisplayStatus(bizLayer.ErrorMessage); return; } // Display the new action = Action.ShowJuvenile; ShowInterface(juv, action); Juvenile member info. } } catch (OverflowException exc) { DisplayStatus(exc.Message); } catch (FormatException exc) { DisplayStatus(exc.Message); } //Possible Exceptions from LibraryEntities: catch (InvalidCastException exc) { DisplayStatus(exc.Message); } catch (ArgumentNullException exc) { DisplayStatus(exc.Message); } catch (ArgumentOutOfRangeException exc) { DisplayStatus(exc.Message); } catch (Exception exc) { StringBuilder sb = new StringBuilder(); sb.AppendLine("General Exception Error: " + exc.Message); if (!(exc.InnerException == null)) { sb.AppendLine("Inner Exception: " + exc.InnerException.Message); } sb.AppendLine("Source: " + exc.Source); DisplayStatus(sb.ToString()); Exception Handling } } 12
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe … And the new Juvenile Member Info is displayed Click <Check Out>, to check out Books for this Member. Check Out an Item: If we choose <Check Out> from the Member Screen, we get the following dialog … We choose a Book to check out for the current Member, and click <Check Out> … 13
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe … then we get to confirm or back out of the operation …. … or if the book is in the system as On Loan, the User is asked …. Again, we can confirm or cancel. private void btnCheckOut_Click(object sender, EventArgs e) { Instantiate a CheckOutForm frmCheckOut = new CheckOutForm(intMemberID); new frmCheckOut.ShowDialog(this); CheckOutForm // and open it string msg; modally. if (!BindGrid(intMemberID, out msg)) Refresh the grid { to show newly DisplayStatus(msg); checked out item. } } 14
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Phase 2 – Business & Data Access Tiers Overview: Objective: • Design and implement a Data Access tier using ADO.NET to replace the assembly provided in Phase 1. • Provide Stored Procedures to be used by the new Data Access tier, which should not contain any SQL statements. • Retool Business tier to use new Data Access tier. • Design and implement a Library Entities assembly to replace the assembly provided in Phase 1. Technologies used: .NET & C# ADO.NET SQL Server 2000, Transact SQL (Stored Procedures) Business Layer Code Samples /// <summary> /// The Business Layer is an intermediary layer between the Client and /// Data Access Layers. It’s function is to encapsulate Business Logic. /// </summary> public class BusinessLayer { GetMyItems(MemberID) /// <summary> /// Interrogates the Data Access Layer /// to return a Library ItemsDataSet object. /// </summary> public ItemsDataSet GetMyItems(short memberID, out bool resultOK) { // init: ItemsDataSet MyItems = null; ItemsDataSet is a strongly typed resultOK = false; Dataset object for populating the // DataGridView. It is defined in try separate assembly LibraryEntities. { // create a library data access object: LibraryDataAccess lda = new LibraryDataAccess(); // // Get Items object: Instantiate Data MyItems = lda.GetItems(memberID); Access Layer … resultOK = true; } catch … and use it to return … etc … a ItemsDataSet return MyItems; } 15
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe AddMyMember(Member) public bool AddMyMember(Member m) { AdultMember & // init: JuvenileMember are bool resultOK = false; derived from the Member bool isAdult; base class. All are AdultMember adultMember; defined in separate JuvenileMember juvenileMember; assembly LibraryEntities. // try { // //check for null member: if (m == null) { errorMessage = "Could not Add Member. " + "The Member object was null."; return resultOK; } // //Get What Kind Of Member: adultMember = m as AdultMember; if (!(adultMember == null)) { isAdult = true; } else { isAdult = false; } // Instantiate Data //Create a library data access object: Access Layer … LibraryDataAccess lda = new LibraryDataAccess(); Catch // any //Add the Member: … and use it to add errors if (isAdult) { lda.AddMember((AdultMember)m); } the member to the else { lda.AddMember((JuvenileMember)m); } database. // resultOK = true; } catch (LibraryException exc) LibraryException { is a custom Exception errorMessage = GetLibraryErrorMessage(exc); object defined in return resultOK; separate assembly } LibraryEntities. catch (Exception exc) { StringBuilder sb = new StringBuilder(); sb.AppendLine("General Exception Error: " + exc.Message); if (!(exc.InnerException == null)) { sb.AppendLine("Inner Exception: " + exc.InnerException.Message); } sb.AppendLine("Source: " + exc.Source); The Business Layer traps any errorMessage = sb.ToString(); errors and exposes the result return resultOK; back to the calling front end } though the variable resultOK return resultOK; and the ErrorMessage property. } 16
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Data Access Layer Code Samples AddMember(AdultMember) /// <summary> /// Adds specified Adult Member to the database. The AdultMember object that is /// passed as a parameter must have all properties initialized except MemberID /// & ExpirationDate which are populated with values returned by the database. /// </summary> public void AddMember(AdultMember adultMember) Instantiate a new { SqlConnection try { using (SqlConnection cnn = new SqlConnection( "Data Source=.;Initial Catalog=library;Integrated Security=True")) { using (SqlCommand cmd = Instantiate a new new SqlCommand("usp_AddAdult", cnn)) SqlCommand { based on the cnn.Open(); SqlConnection cmd.CommandType = CommandType.StoredProcedure; and a stored // procedure SqlParameter prmFirstname = new SqlParameter(); Add Input prmFirstname.ParameterName = "@firstname"; Parameters to prmFirstname.Direction = ParameterDirection.Input; prmFirstname.SqlDbType = SqlDbType.VarChar; the SqlCommand prmFirstname.Value = adultMember.FirstName; object. cmd.Parameters.Add(prmFirstname); // … Other Input Parameters are added… // SqlParameter prmMember_no = new SqlParameter(); Add Output prmMember_no.ParameterName = "@member_no"; Parameters to prmMember_no.Direction = ParameterDirection.Output; the SqlCommand prmMember_no.SqlDbType = SqlDbType.SmallInt; cmd.Parameters.Add(prmMember_no); object. // … Output Parameter @expr-date " is also added in like fashion … Execute the // command. int nrRowsAffected = cmd.ExecuteNonQuery(); ExecuteNonQuery // means that it will adultMember.MemberID = (short)cmd.Parameters["@member_no"].Value; be returning no adultMember.ExpirationDate = rows. Convert.ToDateTime(cmd.Parameters["@expr_date"].Value); } } The AdultMember object is updated with the info returned } from the stored proc through the 2 output parameters. catch (SqlException SqlEx) {throw GetLibraryException(SqlEx); } Note that the first type of exception we try to catch (Exception ex) catch is an SqlException. This will catch {throw GetLibraryException(ex); } any error invoked by the RAISERROR } statement in the stored procedure. 17
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Stored Procedure usp_AddAdult -- Object: StoredProcedure [dbo].[usp_AddAdult] Script Date: 07/13/2009 03:08:35 USE [library] SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON GO -- ============================================= 8 Input Parameters -- Author: Cormac Sharpe -- Create date: June 26, 2009 -- Description: Adds an Adult Member to the Library 2 Output Parameters -- ============================================= CREATE PROCEDURE [dbo].[usp_AddAdult] @firstname varchar(15), @lastname varchar(15), @middleinitial varchar(1), @street varchar(15), @city varchar(15), @state varchar(2), @zip varchar(10), @phone_no varchar(13), @member_no smallint output, @expr_date datetime output AS BEGIN SET NOCOUNT ON; RAISERROR raises an State 118 flags an --Validate Input; AddAdultFailed sqlException, which is ----------------------------- caught in the ADO.NET code ErrorCode to IF (@firstname is null) LibraryException. OR (@lastname is null) begin Validate RAISERROR('usp_AddAdult: Incomplete Name - either @firstname or Input @lastname was null.',16,118); -- State 118 flags a AddAdultFailed ErrorCode to LibraryException return -1 end Also validated: IF (@street is null) OR (@city is null) OR (@state is null) (@zip is null) then RAISERROR. -- set @expr_date = dateadd(year,1,getdate()) begin transaction insert into dbo.member(firstname, lastname, middleinitial) values (@firstname, @lastname, @middleinitial) if @@error <> 0 Insert begin Into rollback transaction member RAISERROR('usp_AddAdult: An error occurred while adding an Adult Table Member.',16,118); -- State 118 flags a AddAdultFailed ErrorCode to LibraryException return -1 Save the newly created MemberID end to the output parameter. set @member_no = SCOPE_IDENTITY() insert into dbo.adult(member_no, street, city, state, zip, expr_date) values (@member_no, @street, @city,@state,@zip,@expr_date) Insert if @@error <> 0 begin Into adult rollback transaction RAISERROR('usp_AddAdult: An error occurred while adding an Adult Table Member.',16,118); -- State 118 flags a AddAdultFailed ErrorCode to LibraryException return -1 end commit transaction END 18
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe GetItem(isbn, copyNumber) /// <summary> /// Returns an Item object that contains data about the item whose /// ISBN and copy number are provided as parameters. /// </summary> /// <param name="isbn"></param> /// <param name="copyNumber"></param> public Item GetItem(int isbn, short copyNumber) { … try { using (SqlConnection cnn = new SqlConnection( "Data Source=.;Initial Catalog=library;Integrated Security=True")) { using (SqlCommand cmd = new SqlCommand("usp_GetItem", cnn)) Add Input { Parameters to the cnn.Open(); SqlCommand object. cmd.CommandType = CommandType.StoredProcedure; THERE ARE NO // OUTPUT // PARAMETERS IN SqlParameter prmISBN = new SqlParameter(); THIS CASE. prmISBN.ParameterName = "@isbn"; prmISBN.Direction = ParameterDirection.Input; prmISBN.SqlDbType = SqlDbType.Int; prmISBN.Value = isbn; cmd.Parameters.Add(prmISBN); … Input Parameter @copy_no" is also added in like fashion … Execute the command. ExecuteReader() returns rows to the using (SqlDataReader reader = cmd.ExecuteReader()) SqlDataReader { object. //exactly 1 row should be returned 1 row is returned if (!(reader.Read())) (the Select is based { on a unique index). … } The Item object is created with the row info returned Item myItem = new Item(myISBN, myCopyNumber, myTitle, from the stored myAuthor, myMemberNumber, myCheckoutDate, myDueDate); proc, and returned. return myItem; } } } } 19
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Entities Code Samples LibraryEntities is a separate assembly containing the classes that define the Entities involved in the Library Project, including Member, AdultMember, JuvenileMember, Item, ItemDataset, LibraryException. Class Member /// <summary> /// Represents a member of the library. /// </summary> [Serializable] Base class from which AdultMember public class Member { & JuvenileMember are derived. //Fields: private string city; … etc … // Member Constructor. Initializes the Member object. public Member() { city = string.Empty; … etc … Properties to be exposed for the } Member class. All are read/write. //Properties: public string City { get { return city; } set { city = value; } … etc … } } Class LibraryException /// <summary> /// Custom exception for when a non-fatal error occurs in the Library App. /// </summary> [Serializable] public class LibraryException : Exception Inherits from Exception. { //Fields: private ErrorCode libraryErrorCode = ErrorCode.None; … etc … // // Constructors: public LibraryException(ErrorCode errorCode) {libraryErrorCode = errorCode; } … and a lot more constructor public LibraryException(string message): base(message) overloads … {//do nothing - its handled by base class Exception. } // //Properties: //Gets the value of the ErrorCode that was set when this exception was created. //This value indicates the reason for the exception being thrown. //If this value was not set explicitly, this property will return ErrorCode.None public ErrorCode LibraryErrorCode { get { return libraryErrorCode; } … and other Properties … } } 20
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Phase 3 – Web Application Overview: Objective: • Create a web application that supports all the functionality required for Phase I and II of the Library project. Technologies used: .NET & C#; ASP.NET; Forms-based authentication;Security using ASP.NET Membership & Role Management. All pages use a common theme and Master Page. Hypertext based Menu system Security using ASP.NET Membership & Role Management. Only Users belonging to the “Librarian” role can Log in. WEB.CONFIG <?xml version="1.0"?> <configuration> Note authorization in <appSettings/> Web.config - Anyone can <connectionStrings/> access the Website, but all important functionality is <system.web> restricted to “Librarian” <authorization> role members. <allow roles="Librarian" /> <deny users="*" /> </authorization> </system.web> </configuration> 21
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe “Get Member Info” Page If we enter card# 1 and click <Get Member Info>, the following code runs … Session["MemberObject"] = member; Response.Redirect(@"~/Operations/MemberInfo.aspx"); Save member object as session info and redirect to the MemberInfo page. “Member Info” Page public partial class Operations_MemberInfo : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { … if (!Page.IsPostBack) Only do these actions if this page is opening { fresh, i.e. not posting back from the server. … if ((Session["MemberObject"] != null)) { member = (Member)Session["MemberObject"]; } Retrieve member object // from session info. if (member is AdultMember) { ShowAdult(); } else // Member is a Juvenile: { juv = (JuvenileMember)member; //If Juvenile over 18: 22
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe if (juv.BirthDate.AddYears(18) <= DateTime.Today) { //Update Juvenile to Adult: BusinessLayer biz = new BusinessLayer(); resultOK = biz.UpdateToMyAdult(juv.MemberID); A Juvenile member who … Check Result with: if (!resultOK) etc … is over 18 is //Re-retrieve member - is now an adult: automatically BusinessLayer biz1 = new BusinessLayer(); updated to member = biz1.GetMyMember(juv.MemberID, out resultOK); being an Adult … Check Result with: if (!resultOK) etc … member. ShowAdult(); string msg = string.Empty; msg += "This member is over 18, but was in the system as a "; msg += "juvenile. The member was updated to an Adult. "; DisplayMessage(msg); } else { ShowJuvenile(); } } } … } In this case we had entered card# 1, and we find that this is an Adult Member … Its not shown on this screen, but if the card is over 1 year old, then the card is flagged with Card is Expired, and the user is given the opportunity to renew it with a <Renew Membership> button, which appears only in that case. Here’s the code: If (DateTime.Parse(this.lblExpirationDat e.Text) < DateTime.Today) { this.lblExpired.Visible = true; this.lblExpiredFlag.Visible = true; this.btnRenew.Visible = true; this.btnCheckOut.Enabled = false; } If we enter ISBN 1, Copy#1, and then click <Check Out>, we get an option to Confirm or Cancel … When we click on <OK> … 23
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe btnOK runs when the user protected void btnOK_Click(object sender, EventArgs e) confirms the Check out. { Item item; string msg; // //Retrieve the Item from Session: if (Session["ItemObject"] != null) Retrieve Item object from { item = (Item)Session["ItemObject"]; Session. } (Earlier when <Check Out> else was clicked, { btnCheckOut_Click ran, DisplayMessage("Error retrieving the Item."); populating an Item object, SetCheckOut(false); which it then saved to return; Session) } // //If Item is on Loan: if (!(item.MemberNumber == 0)) { // Check it In first: BusinessLayer biz = new BusinessLayer(); resultOK = biz.CheckInMyItem(item.ISBN, item.CopyNumber); if (!resultOK) { DisplayMessage(biz.ErrorMessage); SetCheckOut(false); return; } } // //Check it out: BusinessLayer biz2 = new BusinessLayer(); Check out the Item resultOK = biz2.CheckOutMyItem( (copy of a book). short.Parse(this.lblMemberID.Text), item.ISBN, item.CopyNumber); if (!resultOK) { if (biz2.ErrorMessage == "FourBooksAlreadyCheckedOut") { Enforce a msg = "Four Books are Already Checked Out. "; maximum of 4 msg += "n"; items on loan at msg += "Four is the maximum allowed."; a time. DisplayMessage(msg); } else { DisplayMessage(biz2.ErrorMessage); } SetCheckOut(false); return; } // //Refresh Grid: Refresh the grid to display the new item on 24 loan.
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe this.GridView1.DataBind(); // SetCheckOut(false); // DisplayMessage("Check Out Complete!"); } … the Item is added to the grid, and the Check Out is confirmed. protected void GridView1_SelectedIndexChanged(object sender, EventArgs e) { isbn = int.Parse(this.GridView1.SelectedRow.Cells[1].Text); Selecting a book in copy = short.Parse(this.GridView1.SelectedRow.Cells[2].Text); the grid checks it in. // BusinessLayer bizLayer = new BusinessLayer(); resultOK = bizLayer.CheckInMyItem(isbn, copy); if (!resultOK) { DisplayMessage(bizLayer.ErrorMessage); return; } //Refresh Grid: this.GridView1.DataBind(); } 25
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe “Get Book Info” Page User has the choice to just get the Book Info, or do so while also adding a new copy of the book. Click <Get Book> … 26
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe public partial class Operations_GetBook : System.Web.UI.Page { … protected void btnGetBook_Click(object sender, EventArgs e) { //Get Book: BusinessLayer bizLayer = new BusinessLayer(); book = bizLayer.GetMyBook( GetMyBook creates and int.Parse(this.txtISBN.Text), populates a Book object, based out resultOK); on the inputted ISBN. if (!resultOK) { if (bizLayer.ErrorMessage == "BookNotFound") { //give user option to add new Book or back out: DisplayStatus("This Book does not yet exist. Do you want to add it?";); //Show Ok & Cancel buttons SetNewBookOption(true); return; } else The Book was not found. User is { given the option to add it to the DisplayStatus(bizLayer.ErrorMessage); system. return; } } // Save Book object to Session. //if the code gets this far, then .... //Save the Book in Session: Session["BookObject"] = book; if (this.chkNewCopy.Checked) { Save the boolean Session["BookAddNewCopy"] = true; BookAddNewCopy to Session. } else { Session["BookAddNewCopy"] = false; } Response.Redirect(@"~/Operations/BookInfo.aspx"); Redirect to BookInfo } page. protected void btnOK_Click(object sender, EventArgs e) { Session["NewBookISBN"] = this.txtISBN.Text; Response.Redirect(@"~/Operations/AddNewBook.aspx"); Redirect to AddNewBook } page if User chose to add a book that was not } found. … and we are presented with the book info for ISBN #1 … 27
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe “Book Info” Page Since we chose in the previous screen to add a new copy, copy #20 has been added … protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { if ((Session["BookObject"] != null)) Retrieve Book object { book = (Book)Session["BookObject"]; from Session. } } this.lblAuthor.Text = book.Author; this.lblCover.Text = book.Cover; Populate the page. … etc … // Retrieve the boolean if ((bool)Session["BookAddNewCopy"]) BookAddNewCopy from Session. { newCopyNo = (short)(book.Max_copy_no + 1); This indicates whether the user // chose to also add a new copy of //Add New Copy: the book. BusinessLayer bizLayer = new BusinessLayer(); resultOK = bizLayer.AddMyCopy(book.ISBN, newCopyNo, book.Title_no); … Check Result with: if (!resultOK) etc … AddMyCopy, and flag this, if the // this.lblMaxCopyNo.Text = newCopyNo.ToString(); user chose to add a new copy. lblMaxCopyUpdated.Visible = true; // msg = "A New Copy "(Copy Nr " + newCopyNo.ToString() + ") has been added."; DisplayStatus(msg); }} 28
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Phase 4 – Web Services Overview: Objective: • Take the library system to the next level – allow interoperability with other systems. • Create a Web service that calls into the Business Layer. • Update the Client (UI) layer to call the Web Service, and support previous project functionality. • Employ WSE 3.0 security using Certificates. Signing, encryption and secure session are required. Technologies used: .NET; C#; ASP.NET; Web Services; XML; SOAP; WSE 3.0 Web Client Sample Page. Note: A Web-based (ASP.NET) client was provided as the starting point for the front-end to communicate with the web service. This was another separate implemenation of what I produced in Phase 3. 29
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Server-side Code Samples - The Service Class using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; using SFLibraryBusiness; using SFLibraryEntities; using System.Xml.Serialization; using System.Xml; The Web Service using Microsoft.Web.Services3; supports the Basic Profile. [WebService(Namespace = "http://setfocus.com/libraryphase4")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [Policy("CertificatesPolicy")] Use WSE 3.0 public class Service : System.Web.Services.WebService security with { Certificates. Derive Service class from System.Web.Services.WebService /// <summary> /// Gets the member object using a member number or id. /// </summary> /// <param name="memberNumber">Member number.</param> /// <returns>Populated member object with data.</returns> GetMember returns the base [WebMethod] class Member. To tell the [XmlInclude(typeof(AdultMember))] client and web service to [XmlInclude(typeof(JuvenileMember))] handle the sub-classes public Member GetMember(short memberNumber) correctly, we use the { XmlInclude attribute. try { Library lib = new Library(); Member m = lib.GetMember(memberNumber); The Web Service return m; simply instantiates } and calls into the Business Layer. catch (LibraryException libex) { throw new SoapException(libex.Message, SoapException.ClientFaultCode, libex); } } Re-throw any LibraryException as a SoapException. … and the other Web Methods are very similar … } 30
  • .NET Library Project Spring/Summer 2009 - Cormac Sharpe Client-side Code Samples - The AddAdult Page public partial class AddAdult : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!this.IsPostBack) If this is the page opening 1st time (not a { postback from the server), then load the this.LoadStates(); States dropdown box from the xml file. } } protected void addAdultButton_Click(object sender, EventArgs e) { if (!Page.IsValid) { return; } try { // Populate new adult object AdultMember newAdultMember = new AdultMember(); newAdultMember.FirstName = firstNameTextBox.Text; … etc … // Attempt to add new adult member Implement WSE 3.0 security ServiceWse lib = new ServiceWse(); using Certificates. lib.SetPolicy("CertificatesPolicy"); newAdultMember = lib.AddAdultMember(newAdultMember); short memberID = newAdultMember.MemberID; … and the service (ServiceWse) is invoked, which in turn calls into the Business Layer. // Redirect to the GetMemberInfo page and pass the new member id. // false is passed to surpress the internal call to the Response.End // Additional details at: http://support.microsoft.com/kb/312629/EN-US/ Response.Redirect(string.Format("GetMemberInfo.aspx?MemberID={0}", memberID.ToString()), false); } catch (Exception ex) {statusLabel.Text = "Error: <br> " + ex.Message;} Redirect to the GetMemberInfo page passing the new member id. In the GetMemberInfo class the MemberID will be retrieved as follows: //populate the textbox with the value this.memberNoTextBox.Text = Request.QueryString["MemberID"]; 31