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 7 - Music Store part 1

The music store project utilizes all of the tools and concepts covered so far in MIS 324 and adds a few more. In addition to models, views, controllers, Sql Server database, layouts, and partial views it also uses Amazon's Product Advertising API to retrieve music products from Amazon's database. When you have completed this project you will have a realistic e-commerce front-end with a shopping cart, checkout process, order history, and confirmation.

Tip: The default routing includes an optional parameter named "id". We have not defined any additional routes so "id" is the only parameter that will be recognized unless the name of the parameter is given in the query string. For example, the URL "/music/Detail/B0068CEGT0" is passing ASIN but the controller retrieves "id."
public ActionResult Detail(string id)

  1. music/index - This page displays six random items selected from the music store database.
    Steps:
    1. Database: Create a new Sql Server database named MusicStore. Use "New Query" in Visual Studio to execute the SQL scripts tblStylesAmazon.txt and tblDescription147.txt (paste the sql into VS and click "Execute.")  These scripts will create the two database tables and populate them with data.  tblSytles contains Amazon's music style names and search nodes IDs. tblDescription contains descriptions for 147 Amazon music items. tblDescriptions is used to display random items on the index page. Other pages in the site will use Amazon web services.
    2. web.config - Add two more connection strings for the MusicStore database.
    3. Model - Create a new model "MusicModels". Add a class named MusicDescriptionModel with properties matching tblDescription. Add a second model named MusicStyleModel with properties matching tblStyles. 
    4. DataRepository - Copy CrudRepository and name it MusicRepository. Create a method named GetRandom() that selects six random records from tblDescription (similar to GetRandom() in BirdView).  The left menu also needs to be populated so copy GetColorCategories() from BirdView and name it GetMusicCategories. Modify the sql to query tblStyles (the join may be removed because all of Amazon's categories contain items).
    5. Controller - Copy BridViewController and name it MusicController. Use "replace all" to modify it to use MusicRepository. Comment out all the action methods except index() and _leftMenu(). The image below shows all of the action methods for the finished controller.
    6. Views - BirdView is a good template. Copy the entire BirdView folder and rename it Music. Edit _ViewStart to point to Music.
    7. Images - Amazon provides access to its product images in three sizes: thumb, medium, and large. The index page uses the thumb size. The URL has the product ASIN concatenated into it. The following link will get the image for product ASIN B00EDPFJA4.

      http://images.amazon.com/images/PB00EDPFJA4.01._SCTHUMBZZZ_V1115763748_.jpg

      The syntax to display the thumb size image in an anchor tags is:
      @{ 
        //Url.Action("myAction", "myController", "myRoute" as object) 
        string path = Url.Action("detail", "music", new { id = item.Asin });
      }                            
      <a href='@path'>
        <img src="http://images.amazon.com/images/P@(item.Asin).01._SCTHUMBZZZ_V1115763748_.jpg"
             class='productImage' alt="@item.Title" title="@item.Title" />
      </a>
                              
    8. index view - The following html & Razor code displays the music items. Replace the existing HTML and Razor in index view with:
      <div class="row">
          @foreach (var item in Model)
          {
              <div class="col-md-6 productContainerThumb">
                  @{ 
                      //Url.Action("myAction", "myController", "myRoute" as object) 
                      string path = Url.Action("details", "music", new { id = item.Asin });
                  }
                  <a href='@path'>
                      <div class="productTitle">@item.Title</div>
                  </a>
                   <div>by <span class="productArtist">@item.Artist</span></div>
      
                  <a href='@path'>
                      <img src="http://images.amazon.com/images/P@(item.Asin).01._SCTHUMBZZZ_V1115763748_.jpg"
                           class='productImage' alt="@item.Title" title="@item.Title" />
                  </a>
                  <div class="productDescription">
                      @Html.Raw(item.Review)
                      <a href='@path'>
                          more...
                      </a>
                  </div>
              </div>
          }
      </div>
      
    9. _leftMenu partial view - Modify it to use MusicStyleModel and modify the other field names as needed to match MusicStyleModel
    10. Test
  2. MusicController Styling - Upgrade the styling. 
    1. Create a new CSS file named music.css and paste in the CSS from the sample site (unless you prefer to write your own). Modify the CSS tag in _Layout to point to the new CSS file.
    2. Edit the HTML in _Layout to achieve the look that you desire. (Tip: The inspection feature in Chrome's developer tools is a convenient way to see the styles that have been used in the sample site.)
    3. Links: Change the header to include links to about, cart, and account. The logo should link to index. Links should use the tilde (~) to point to the application root. For instance a link with this format in the browser:
      /students/164/csandvig/content/images/music/logo55.png
      
      uses this format in the MVC View:
      ~/content/images/music/logo55.png
      
      The tilde points to the application root both in VS and on the server.
    4. Some of the reviews are quite long and push too much content below the fold. The solution is to truncate the reviews in the sql statement. Modify the sql statement in MusicRepository to use Sql Server's substring() function. The sample site truncates to 200 characters.
    5. The index view will also be used for search and browse and we want each to have the appropriate page title (which is displayed in the browser tab). The page title can be set in the controller. Remove ViewBag.Title from index view and add the following to the index action handler in the controller.

      ViewBag.Title = "MVC Music";

  3. music/browse - Search, browse, and details all utilize Amazon's Product Advertising API to retrieve product information. Using this API previously required hundreds of lines of C# code but thanks to a open source Nuget package developed by an Austrian developer Tino Hager it now requires only a few lines of code.  This page takes a browse node id as an input parameter and displays products obtained from Amazon's API.
    Steps:
    1. In VS open the Nuget package manager console and install the Nuget package Nager.AmazonProductAdvertising.
    2. DataRepository - In keeping with the MVC's separation of concerns design pattern we will put the code for accessing Amazon's data in a data repository class and access it via class methods. Add AmazonProductAPIRepository class to your solution. It has methods for search, browse, and details. The AccessKey and SecretKey are located in Canvas under files. Please do not share these keys (You can also get your own keys from Amazon. They are free but require a credit card. Make sure to use IAM (identity and access management) keys for your protection.)
    3. Controller - Add a using statement for "Nager.AmazonProductAdvertising.Model".  Create an instance of AmazonProductAPIRepository (similar to the one for MusicRepository.)  Add an action method for Browse:
              public ActionResult Browse(string id)
              {
                  var result = amazonAPI.Browse(id);
                  ViewBag.message = result.Items.TotalResults + " items in category";
                  return View(result);
              }
      
    4. View: The view for browse is similar to index. The data is coming from Amazon's API rather than a database so the field names are different. Copy index view and name it browse.  Make the following changes:
      1. Model: @model Nager.AmazonProductAdvertising.Model.ItemSearchResponse
      2. Add @ViewBag.message near the top for displaying item counts (note: the sample site includes an enhancement which adds commas to the item count).
      3. foreach: change Model to Model.Items.Item
      4. Title: Use Intellisense to find this property in item.ItemAttributes.
      5. Artist: An item may have several artists to Amazon returns an array of artists. Display them using a foreach loop:
        <div> by
             foreach (string artist in item.ItemAttributes.Artist)
             {
                 <span class="productArtist">@artist </span>
             }
        </div>
        
      6. Missing values: Amazon does not always populate the artist field. The solution is to wrap it with an if statement:
              @if (item.ItemAttributes.Artist != null)
              {
                   // display artist(s) code 
              }
        
      7. EditorialReview: this is the item description. An item may have several so they are returned in an array. For simplicity we display on the first one using the following code:
        @Html.Raw(item.EditorialReviews[0].Content)
         <a href='@path'>
             more...
         </a>
        
      8. Missing values: EditorialReviews are not always provided so wrap it with an if statement similar to artist.
      9. Truncation: Some of the editorial reviews are quite long and need to be truncated. Truncating descriptions is more complicated than you might expect for two reasons: some descriptions are less than the desired length and String.Substring() throws an exception if the desired length is less than the length of the target. Second, we do not want to cut words in half. The solution is a small utility function. Create a new class named SmartTruncation located in the Utilities folder (namespace) and add this code:
        using System;
        
        namespace Mis324Assignments.Utilities
        {
            public static class SmartTruncation
            {
                public static string Truncate(string target, int length) {
                    int len = Math.Min(target.Length, length);
                    target = target.Substring(0, len);
                    if (target.Contains(" ")) 
                           target = target.Substring(0, target.LastIndexOf(" "));
                    return target;
                }
            }
        }
        
        In browse view add: @using Mis324Assignments.Utilities then apply as follows:
         @Html.Raw(SmartTruncation.Truncate(item.EditorialReviews[0].Content, 200))
        
      10. Test!
  4.  music/search - This is very similar to Browse.  
    1. Copy the action method for browse and change as needed.
    2. Search uses the browse view. How to specify a specific view (first answer).
  5. music/details - This view is similar to browse but includes more fields. Although we display only one item it still uses a foreach loop (other parameter combinations could return multiple items). Copy the browse view and rename it details. Changes are as follows:
     
    1. Model: Is AmazonItemResponse instead of ItemSearchResponse.
    2. Image: When the user clicks on the image they should see the larger size image. See the working sample for syntax (note: the sample includes highslide with is an enhancement. You can remove the highslide code or leave it.)
    3. Prices: Not all items include a list price (discontinued items or items sold by 3rd parties) so we need to poke around the response and see what we can find. The code:
        @{
           decimal Price = 3333; //set an arbitrary default just in case no price can be found
           if (@item.ItemAttributes.ListPrice != null)
           {
               Price = Convert.ToDecimal(@item.ItemAttributes.ListPrice.Amount);
           }
           else if (item.OfferSummary.LowestNewPrice != null)
           {
               Price = Convert.ToDecimal(@item.OfferSummary.LowestNewPrice.Amount);
           }
           else if (item.OfferSummary.LowestUsedPrice != null)
           {
               Price = Convert.ToDecimal(item.OfferSummary.LowestUsedPrice.Amount);
           }
       }
       <div><b>List Price: </b><span class="priceList">@String.Format("{0:c}", Price / 100)</span></div>
       <div><b>Our Price: </b><span class="priceOurs">@String.Format("{0:c}", Price / 100 * Convert.ToDecimal(0.8))</span></div>
       <div><b>You Save: </b><span class="priceSave">@String.Format("{0:c}", Price / 100 * Convert.ToDecimal(0.2))</span></div>
      
      
    4. Format: this is listed under ItemAttributes.Binding
    5. DetailPageURL: Amazon's user agreement requires a link to the product on Amazon's site.
    6. Editorial reviews: The detail page includes all of the editorial reviews. The syntax:
        @if (item.EditorialReviews != null)
       {
           foreach (Nager.AmazonProductAdvertising.Model.EditorialReview review in item.EditorialReviews)
           {
               <div style="padding-bottom:20px;">
                   @Html.Raw(review.Content)  <span> Source: @review.Source</span>
               </div>
           }
       }
      
    7. Chrome inspect Test!
    8. Search, browse, and details all require input parameters and will throw exceptions if not provided. Handle this scenario by adding the following statement to the top of the three action methods:
      if (id == null) return RedirectToAction("index");
      


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
Top