Syllabus Schedule Project Labs Canvas Server Access CSS Tutorial Assignment 1 Assignment 2 Assignment 3 Assignment 4 Assignment 5 Assignment 6 Assignment 7 Assignment 8 Assignment 9

Assignment 4 - Web Forms and Database

  1. Snowboard - This is a two part exercise. The first part creates a form with validation. The second part processes the form data and displays an order confirmation. Steps:
    1. Model: The first part of this exercise builds upon BigWebForm from A03. The following instructions will focus on differences. Create a new model named SnowboardModel with the following properties:
      Property Type Validation
      Email string required
      ModelID string required
      Experience string required
      DiscountStudent bool
      DiscountSenior bool
      DiscountGoldClub bool
      State string required
    2. Email and Model should use the Display attribute to provide user-friendly display names. Email should be validated using the EmailAddress Attribute validator as described by Ehsan.
    3. ViewModel: The snowboard order form will contain two dropdownlists and a list of radiobuttons. The data for these options will be stored in the ViewModel.
    4. StateList: The state dropdown is similar to the one used in the BigWebForm exercise. Copy it and rename it SnowBoardViewModel.cs. The List is a convenient location to store other state data such as sales tax, which we will need later. Add a third property to State class named "StateTaxRate" of type double. Add the tax rates for each state: CA 0.085, ID 0.065, OR 0.0, and WA 0.087.
    5. BoardModelList: Add a second class to the view model named "BoardModel" with three properties: ModelName (string), modelId, and Price (double).
    6. Add a second static List to the class named BoardModelList with the following data:
      ModelName ModelId Price
      Screamer $200 scr 200
      Terrorizer $300 ter 300
      Cliff Hopper $400 cli 400
      Low IQ $500 low 500
    7. Experience: Add a third class named Experience with two properties: ExperienceLevel (string) and Surcharge (double).
    8. Add a third static List named ExperienceList with the following data:
      ExperienceLevel Surcharge
      Beginner (no surcharge) 0.0
      Intermediate (10% surcharge) 0.1 
      Knuckle-dragger (20% surcharge) 0.2
      Out-of-control (30% surcharge) 0.3
    9. Controller: Create a new controller, similar to BigWebFormController.  
    10. View: Create a view and add the form elements shown in the working sample. Similar to BigWebForm you will need to manually change the BoardModel and State from textboxes to dropdownlists. The radio buttonList can be generated from ExperienceList using the following Razor syntax:
                      @foreach (Experience exp in SnowBoardViewModel.ExperienceList)
                      { 
                          @Html.RadioButtonFor(m => m.Experience, exp.ExperienceLevel) @exp.ExperienceLevel 
                      }
      
    11. The snowboard company has a business rule that disallows both student and senior discounts. Add a ValidationMessage control  below the three discount checkboxes. Validate the business rule in the controller by adding the following code to your the HttpPost ActionMethod:
                  
      if (SbModel.DiscountSenior && SbModel.DiscountStudent)
      {
          ModelState.AddModelError("Discounts", "Dude, you cannot take both student and senior discounts.");
      }
      
      //return to view if any fields invalid
      if (!ModelState.IsValid) return View(SbModel);
      
      
    12. Test the page and check that the validation is working for all fields.
  2. Snowboard/OrderConfirmation - The second part of this exercise uses the data from the form to create an order confirmation.  Steps:
    1. The order confirmation displays the customer's order and calculates the total cost. Add a second model to SnowBoardModel.cs named CustomerOrderModel with the following properties:
              public string ModelName { get; set; }
              public double ModelPrice { get; set; }
              public double ExperienceSurchargePercent { get; set; }
              public double ExperienceSurchargeDollars { get; set; }
              public string DiscountsTaken { get; set; }
              public double DiscountsPercent { get; set; }
              public double DiscountDollars { get; set; }
              public double Subtotal { get; set; }
              public double TaxPercent { get; set; }
              public double TaxDollars { get; set; }
              public double TotalPrice { get; set; }
      
    2. Controller: The next step is to calculate the properties for the CustomerOrderModel. In the HttpPost ActionMethod instantiate an CustomerOrderModel object named custOrder.SnowBoardModel
    3. Model name and price: The order form returned ModelID (see image). To get the model name it is necessary to find the model in BoardModelList. This can be done using the Find method of List<> and Lambda syntax.  The syntax is:

       

       

       

      BoardModel boardModel = SnowBoardViewModel.BoardModelList.Find(m => m.ModelId == SbModel.ModelId);
      
    4. Assign the model name from boardModel to CustOrder with:
      custOrder.ModelName = boardModel.ModelName;
      
      Do the same for price.
    5. Experience: The ExperienceList needs to be searched to find the surcharge percent.  Use Lambda syntax to search ExperienceList and return an experience object, similar to what you did for boardModel (above).
    6. Calculate ExperienceSurchargeDollars by multiplying Surcharge by Price.
    7. Discounts: The discount radio buttons have no data associated with them so check them individually and calculate the total discount. The discounts are 10% for students, %5 for seniors, and 8% for Gold Club. The C# syntax is similar to this:
                   //discounts
                  if (SbModel.DiscountStudent)
                  {
                      custOrder.DiscountsTaken += "student, ";
                      custOrder.DiscountsPercent += 0.1;
                  }
      
    8. The list of discounts could end with a comma. Trim the final comma with:

      custOrder.DiscountsTaken = custOrder.DiscountsTaken.TrimEnd(',',' ');

    9. Calculate subtotal.  
    10. Tax: The StateList needs to be searched to find the tax rate. Use Lambda syntax to search StateList and return a state object, similar to what you did for boardModel (above).
    11. Calculate tax and total price. Double check that you have provided values for all of the properties in CustomerOrderModel.
    12. Return a view that calls an action method "OrderConfirmation" and passes custOrder model. Syntax:

      return View("OrderConfirmation", custOrder);

    13. In the Controller create a new action method named "OrderConfirmation" that takes CustomerOrderModel as an input parameter. It has only one statement:

      return View(custOrder);

    14. View: Create a view by right-clicking in the OrderConfirmation action method. Use template Details and model CustomerOrderModel.
    15. Test: Fill in the order form and submit it. You should see all the properties of the CustomerOrderModel and their values.
    16. Improve the appearance of the order confirmation by decorating the properties of CustomerOrderModel with user friendly names, currency formatting, and percentage formatting.  The following snippet shows how to format as currency and percent. Most of the properties will need formatting.
               [Display(Name = "Price")]
              [DataType(DataType.Currency)]
              public double ModelPrice { get; set; }
      
              [Display(Name = "Surcharge %")]
              [DisplayFormat(DataFormatString = "{0:P0}")]
              public double ExperienceSurchargePercent { get; set; }
      
      
    17. Finally, copy the snowboard image tag from the sample and put it in your view. The appearance of the confirmation is pretty basic but it does contain the necessary information.
    18. Done!
  3. PeopleCRUD - This exercise uses a Sql Server database and a web interface for full CRUD (create, read, update, delete) functionality.

    Steps:

    1. Model: This exercise uses the PersonModel from assignment 2. Add an additional property named Id (int). It now contains four properties: Id, Fname (string), Age (int), and IsSeahawkFan (bool). Is Identity
    2. Database: Create a Sql Server database named People with a table named PersonDetails. To create a database right-click on the App_Data folder -> Add -> new Item -> Sql Server Database. To add a table double click on the database in Solution Explorer and VS will open the database in Server Explorer. Right click on the "Tables" icon and select Add Table. Add fields for the four properties in the model. Id needs to be primary key and identity. To make Id a primary key right-click on it in the designer and select "Primary Key." To make it an autonumber select the Id filed and in properties set "Is Identity" to true.(see image). You should end up with a create statement like this:
      CREATE TABLE [dbo].PersonDetails
      (
          [Id] INT NOT NULL PRIMARY KEY IDENTITY, 
          [Fname] NVARCHAR(50) NOT NULL, 
          [Age] INT NOT NULL, 
          [IsSeahawkFan] BIT NULL
      )
      
    3. Save the database by clicking "Update" and "Update Database."
    4. Add a couple of records to the table by right-clicking on it in server explorer and selecting "Show Table Data."
    5. Dapper: Dapper is a ORM (object relations manager) that maps C# objects to the database. It reduces the amount of code needed to pass data to and from the database.  Dapper dot net explains how to add Dapper to your project. You only need to do this once.
    6. DataRepository - Best practice in MVC is to place code related to data access in a folder named DataRepository (or Repository). The objective is to separate data access implementation details from the rest of the application so that any changes in data access (different datasource, database, etc.) do not impact other parts of the application. Create a new folder "DataRepository". Create a new class named PeopleCrudRepository and paste in this code. It provides five methods for CRUD that you will call from the controller.
    7. Check that the sql statements in PeopleCrudRepositoiry match the four fields in PersonModel.
    8. Controller: The controller will need a total of eight action methods to handle CRUD functionality. Visual Studio will create a controller with all eight stubs. Right-click on the controller folder and select "Add", "Controller", "Controller with Read/Write actions", name it PeopleController. The action methods are as follows.

      Action Method Purpose Input Parameters Returns (to view) Repository Method View Template
      index  List of all people none List<PersonModel> GetAllPeople List
      Details List one person id person GetOnePerson Details
      Create (HttpGet) Displays empty create form none nothing -- Create
      Create (HttpPost) Adds form data to database and redirects to index PersonModel person nothing (redirects to index) AddPerson  
      Update (HttpGet) Gets person based upon ID and populates update form id person GetOnePerson Edit
      Update (HttpGet) Updates person in List<> and redirects to index PersonModel person nothing (redirects to index) UpdatePerson  
      Delete (HttpGet) Displays the person to be deleted id person GetOnePerson Delete
      Delete (HttpPost) Deletes person in List<> and redirects to index PersonModel person nothing (redirects to index) DeletePerson  

    9. The controller template includes three try/catch blocks that will hide errors and make debugging difficult.  Remove the three try/catch blocks, retaining the statements "return RedirectToAction("Index");" 
    10. The controller needs to access your PersonModel and PersonCrudRepository.  Add the following two directives:

      using Mis324Assignments.Models;
      using Mis324Assignments.DataRepository;

    11. The controller needs to access the CRUD methods provided in the PersonCrudRepository.  Add the following statement above the index action method
      //provides CRUD methods.
      PersonCrudRepository personCrudRepository = new PersonCrudRepository();
      
      
    12. Three of the ActionMethods have the placeholder parameters "FormCollection collection."  Replace these with "PersonModel personModel", which will hold the strongly-typed data from the form. ActionMethods
    13. Each of the eight action methods need to be coded. The image on the right shows the first four. The other four use similar logic.
    14. If the data is not valid the controller needs to return the user and the data to the view to correct it. Add "ModelState.IsValid" tests to the HttpPost Create and Update action methods. Syntax:

      if (!ModelState.IsValid) return View(person);

    15. Connection String: Add the following connection strings to the <connectionString> section of the web.config file. The LocalDB string is used with Visual Studio and SqlExpress is used on the server. Prior to publishing your project to the server you will need to switch the two strings by modifying the names.

      <add name="People" connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\People.mdf;Integrated Security=True" providerName="System.Data.SqlClient" />
      <add name="People" connectionString="Data Source=.\SQLEXPRESS2014;AttachDbFilename=|DataDirectory|\People.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient"/>

    16. Views: You will need views for listing, creating, updating, and deleting people.  It is often most efficient to test as you code so that you catch errors more quickly. Create the appropriate views after coding the relevant action methods.
    17. Test the CRUD functionality and validation.
    18. Publish to server and test. If you get the message "A network-related or instance-specific error occurred while establishing a connection to SQL Server."  There is a problem with your connection string. Remember to use the Sql Express string on the server.
    19. Done!


Submission instructions: Submit assignments via the Canvas course management system. Submit the full URL for each exercise in the assignment, listing the URLs in the same order that they are listed in the assignment. To minimize typos in URLs it is strongly recommended that you copy the URLs from the address bar of the browser rather than trying to type them. Incorrect URLs will not be graded and no credit will be given.

When pages are connected via navigation (as in your music store project) it is only necessary to submit the URL of the first page.

Regular Expressions HTML Color Names Color Picker ASCII Character Codes Unicode Character Codes