BTI420 Assignment 7

Build a data model. Implement security.

Read/skim all of this document before you begin work.

 

Due date

Wednesday, March 15, 2017, at 11:00pm ET

Grade value: 4% of your final course grade

If you wish to submit the assignment before the due date and time, you can do that.

 

Objective(s)

Build your own data model and persistent store. Implement a base for a secure app.

 

Introduction to the problem to be solved

The app serves the needs of companies in the music business. We need an app that will enable a record label to manage their artists, albums, and tracks.

For this app, it will be helpful to know that people who work at a record label have various responsibilities, roles, and job duties. We will focus on three job titles, and enable each to perform a selection of tasks in the app:

Executive – Also known as an “artists & repertoire” (A&R) executive, manages the talent acquisition and management process.

Coordinator – Oversees or coordinates the work on an album, all aspects and phases.

Clerk – Supports the coordinator and executive, during the time that the artist makes progress on an album.

 

Specifications overview and work plan

Here’s a brief list of specifications that you must implement:

  • Follows best practices
  • Implements the recommended system design guidance
  • Customized appearance, with an added menu item
  • Programmatic creation of initial data
  • Enable “get all” and “get one” use cases for all (most) entity collections
  • Implement a base for security that includes user account and role claim management

Here is a brief work plan sequence:

  1. Create the project, based on the project template
  2. Customize the app’s appearance
  3. Create view models and mappers that cover the use cases
  4. Configure the security settings for the app
  5. Add methods to the Manager class that handle the use cases, and load initial data
  6. Add the Artist controller, implement the use cases, including views
  7. Add the Album controller, implement the use cases, including views
  8. Add the Track controller, implement the use cases, including views

During the class/session, your professor will help you get started and make progress on this assignment.

Every week, in the computer-lab class/session, your teacher will record a grade when you complete a specific small portion of the assignment. We call this “in-class grading“.

The in-class grading will be announced in-class by your professor.

 

Getting started

Create a new web app, named Assignment7.

It MUST use the “Web app project v2 custom store” project template.

Build/compile, and run the app, to ensure that you are starting with a working error-free base. Then, as you write code, build/compile frequently.

 

Customize the app’s appearance

You will customize the appearance all of your web apps and assignments. Never submit an assignment that has the generic auto-generated text content. Make the time to customize the web app’s appearance.

For this assignment, you can defer this customization work until later. Come back to it at any time, and complete it before you submit your work. 

Follow the guidance from Assignment 1 to customize the app’s appearance.

 

Create the design model classes

In the Models folder, there is a mostly-empty DesignModelClasses.cs source code file.

Add design model classes to this source code file. You will need:

  • Artist
  • Album
  • Track
  • Genre

Follow the guidance about rules/conventions from the March 8 class notes, when writing design model classes:

  • To ease other coding tasks, the name of the integer identifier property should be “Id”
  • Collection properties (including navigation properties) must be of type ICollection<T>
  • Valid data annotations are pretty much limited to [Required] and [StringLength(n)]
  • Required to-one navigation properties must include the [Required] attribute
  • Do NOT configure scalar properties (e.g. int, double) with the [Required] attribute
  • Initialize DateTime and collection properties in a default constructor

Following these rules/conventions will ensure that the database is initialized and configured correctly, and will improve the quality of other coding tasks as you build the app.

Special note:

A few weeks ago, we wrote that you must NOT use the “virtual” keyword when defining navigation properties in your design model classes. This is a reminder.

 

Here’s an image of the completed data model, from the “class diagram” feature in Visual Studio:

DesignModelClassesAssign7v2

 

A few notes about the design model classes, and how they model the real world:

 

Associations

Artist has a to-many with Album, as you would expect. An artist can have many albums.

In our model, an Album has a to-many with Artist. This means that more than one artist can work on an album. This often happens with collaborations or duets.

Album has a to-many with Track, as you would expect. An album can have many tracks.

In our model, a Track has a to-many with Album. This means that a track can appear on more than one album. This often happens when an artist releases a “greatest hits” album.

Real world notice:

In the real world, an artist could be a group. For example, The Beatles. Every group will obviously have members. For example, John, Paul, George, and Ringo were in The Beatles. Therefore, for a really real-world implementation of the artist entity, we really should have a self-referencing to-one association (e.g. John is a member of The Beatles), and we really should have a self-referencing to-many association property (e.g. The Beatles have a collection of members, John, Paul, George, and Ringo).

However, we are not asking you to implement this design feature. We are deliberately limiting the scope of this assignment. Although it would be fun to do.

 

Artist

In the music business, an artist can be an individual person (e.g. Adele), or an artist can be a duo, group, band, orchestra, etc. (e.g. Florida Georgia Line).

The “Name” property is the artist’s name:

  • For a person, it can be their birth name (e.g. Ray LaMontagne), or a stage name (e.g. P!nk)
  • For all others, it will typically be a stage/performer name (e.g. The Beatles)

The “BirthName” property is used only for a person who uses a stage name. For example “Alecia Beth Moore” is the birth name of “P!nk”.

The “BirthOrStartDate” property is used this way:

  • For a individual person, it is their birth date
  • For all others, it is the date that the artist started working in the music business

The “UrlArtist” property will hold a URL to a photo of the artist. You can find a URL for an artist almost anywhere, including:

  • Google or Bing image search
  • Wikipedia
  • Amazon.ca
  • iTunes Preview

The “Genre” property holds a genre string/value. In the user interface, when creating a new artist object, the available genres will be shown in an item-selection element.

The “Executive” property holds the user name (e.g. amanda@example.com) of the authenticated user who is in the process of adding a new artist object.

Warning:

Do NOT make associations with the security classes, from your own design model classes.

Instead, use the security APIs.

For example, assume that you need to keep track of a user name in an entity (for whatever reason). Here’s how to approach this task:

  • Get the user name (i.e. email address) from the current execution context (User property in the controller, or HttpContext.Current.User property in the manager object)
  • Or use the security API to fetch/lookup the desired user and get its user name; we may learn a bit more about using the security API in the near future
  • Store that value as a non-associated string property, in your entity

The user name (email address) is GUARANTEED to be unique, so it can safely be used.

 

Album

The “UrlArtist” property will hold a URL to an image of the album. You can find a URL for an album almost anywhere, including:

  • Google or Bing image search
  • Wikipedia
  • Amazon.ca
  • iTunes Preview

The “Genre” property holds a genre string/value. In the user interface, when creating a new album object, the available genres will be shown in an item-selection element.

The “Coordinator” property holds the user name (e.g. amanda@example.com) of the authenticated user who is in the process of adding a new album object.

 

Track

The “Composers” property holds the names of the track’s composers. It is a simple string property. The browser user will simply use comma separators between the names of multiple composers.

The “Genre” property holds a genre string/value. In the user interface, when creating a new track object, the available genres will be shown in an item-selection element.

The “Clerk” property holds the user name (e.g. amanda@example.com) of the authenticated user who is in the process of adding a new track object.

 

Create view models and mappers that cover the initial use cases

It should be obvious by now that you will need view models for the “get all” and “get one” use cases, because these are always needed.

Yes, you will need some view model classes that include associated data for display purposes. Carefully plan this step. You can use a mix of techniques, including composed properties, or by including associated objects or collections. Don’t worry about getting this step perfect for the interim progress submission. You can modify these classes before the final submission.

Each entity has a “Genre” property. Therefore, you will need to support the “get all” use case for the Genre entity too. (We will not need to support “get one”, because the destination for the “get all” use case will be an item-selection element in the user interface. We will not need to support “add”, “edit”, or “delete”, because you will programmatically build and load the genre data.)

At this point in time, you will have written your design model classes, view model classes, and mappers. Make sure the project builds/compiles without errors.

 

Configure the security settings for the app

After writing the design model classes and the view model classes, you have a pretty good idea about the tasks that could be done with the data. Therefore, let’s think about, design, and configure the security settings for the app.

The most important task is to identify the “role claims” we will need in the app. Then, you can edit the Register() method in the account controller to match. We suggest that you will need these role claims:

  • Executive
  • Coordinator
  • Clerk
  • Staff

The next step is to register some new user accounts. The safest internet top-level domain name to use is “example.com”, because it is not processed by the internet’s DNS infrastructure. Please use the same password for all accounts (for example, Password123!), so that your teacher team can run and test the app with each account.

Role claims can be hierarchical in nature, or not. It depends upon the situation. For this app, we will pay attention to that.

For example, a user account for an executive (maybe named exec@example.com) should be configured with the Executive, Coordinator, and Staff role claims.

A user account for a coordinator (maybe named coord@example.com) should be configured with the Coordinator, Clerk, and Staff role claims.

A user account for a clerk (maybe named clerk@example.com) should be configured with the Clerk and Staff role claims.

Finally, a user account for a person who is NOT directly involved in the A&R chain (e.g. receptionist, payroll clerk, tech support, etc.) should be configured only with the Staff role claim.

 

Add methods to the Manager class that handle the use cases, and load initial data

Let’s begin by loading initial data. Real data, not crappy data (e.g. we NEVER want to see “aaaa” “1234” etc.).

We need initial data for all entities – genre, artist, album, and track.

Create one or more methods that load initial data for each entity.

What value should you enter for a user name/identifier? It does not matter much in this assignment, but enter the user names of the accounts you created in the previous section (when you created a number of user accounts).

A special-purpose or temporary throw-away controller can be used to call these methods. We suggest that you protect that controller/method, so that only the “admin@example.com” user can load the data. (If you use a temporary throw-away controller, leave it in your project when you submit it, so that it can be inspected and graded.)

 

Initial data – genres

Open up your iTunes app (or any other digital music app). Identify ten genres.

Add these ten genres to the data store (and save changes).

Note – When you are adding artists, albums, and tracks (below), you must enter a genre. To make your coding task easier, you can use simple strings. Make sure that you use the exact same string (upper/lower case etc.).

 

Initial data – artists

Identify three of your favourite artists in the music business. Try to choose a combination of individual artists and duo/group/band artists, so that you can uniquely configure some of the name / birth name / birth or start date properties.

If you need information, Wikipedia is often a pretty good source for data about an artist (or album or track).

Add these three artists to the data store (and save changes).

 

Initial data – albums

Select one of your just-added artists from above.

To add an album, you must specify its artist. Therefore, fetch the artist object from the data store. For example:

var john = ds.Artists.SingleOrDefault(a => a.Name == "John Legend");

Next, for the artist, identify two of their albums.

Add each of these two albums to the data store. Notice that an album has an Artists property, which is a collection of artist objects. Logically, when adding a new album, the collection is empty (duh), so that we do not have to worry about overwriting it and losing data. As a result, we can simply create a new artist collection, which has one artist object only, which is our selected artist. For example:

ds.Albums.Add(new Album
{
  Artists = new List<Artist> { john },
  Name = "Love in the Future",
  // etc.

Save changes.

 

Initial data – tracks

For both albums (above), identify five tracks on each album.

Add these ten tracks to the data store (and save changes).

Similar to the album-add task (above), you will need a reference to the album object as you add each track. Therefore, plan to fetch the album object from the data store before you add tracks.

 

Check your progress

If you have correctly-defined your design model classes, and correctly done the data loading, the database will exist, and have data.

If you’re careful, you can open the database, and check your progress. How?

First, in Solution Explorer, select/highlight the “Assignment7” project item.

On the toolbar, choose Show All Files.

Open (reveal) the contents of the App_Data folder. It will show “DBIdentityCustom.mdf”. This is the file that’s used to hold the contents of the database.

 

 

Double-click it, and it will open on the left-side “Server Explorer” panel.

Look for the item named “DefaultConnection (Assignment7)”. Open (reveal) the contents of the Tables folder.

vs-db-2

 

Notice several things:

  • There are several tables that begin with “AspNet…” – those hold the ASP.NET Identity security-related data
  • You can see tables for your design model entities – Artists, Albums, Tracks, Genres
  • To support many-to-many associations, there are also “bridge” tables, ArtistAlbums, and TrackAlbums

You can right-click any of these tables, and choose “Show Table Data”, to show the data in a grid in the Visual Studio editor area.

vs-db-3

 

Very important: When you’re done looking, right-click “DefaultConnection (Assignment7)”, and choose “Close connection”. If you do not do this, then some of your future coding and testing tasks will fail.

 

Uh oh – data loading problems

If your data did not load correctly, then you should remove the data, fix the coding problem, and attempt to load the data again.

How to remove the data?

Create another method in the Manager class for this purpose. (Later, you will call this method from a controller action/method.)

Remove ALL the objects in each entity collection. Here’s an example of how you would do this for the track entity collection; you would repeat this code for the other entity collections:

foreach (var e in ds.Tracks)
{
  ds.Entry(e).State = System.Data.Entity.EntityState.Deleted;
}
ds.SaveChanges();

Note: There are other ways to remove objects. This is the way that your teacher team recommends at this time.

 

Arg – the database is really messed up – I want to delete it and start again

Maybe your data items are messed up. Maybe the design model classes are wrong. Maybe there are just too many little problems, and they’re preventing progress.

You’re thinking “I want to delete the database and start fresh”. Here’s how:

The data context has a database Delete() method. Be careful. With great power, there is great responsibility.

From MSDN:

Deletes the database on the database server if it exists, otherwise does nothing.

Calling this method from outside of an initializer will mark the database as having not been initialized. This means that if an attempt is made to use the database again after it has been deleted, then any initializer set will run again and, usually, will try to create the database again automatically.

 

We suggest that you add another method to the Manager class (which can then be called from a controller action/method). Its code:

public bool RemoveDatabase()
{
  try
  {
    // Delete database
    return ds.Database.Delete();
  }
  catch (Exception)
  {
    return false;
  }
}

 

After the database delete task, run the data load task again.

 

Reminder, at this point, you’re still working in the Manager class. Now, let’s code the methods that support the app’s data service tasks:

  • Genre – get all
  • Artist – get all, get one (with detail)
  • Album – get all, get one (with detail)
  • Track – get all, get one (with detail)

 

Genre – get all

Easy. Get all, return as a sorted/ordered collection of GenreBase objects.

 

Artist – get all, get one (with detail)

The initial goal with “get all” is to simply return a sorted/ordered collection of ArtistBase objects.

Later you can modify that, to return artist objects that have some associated data, in the form of objects and/or composed properties.

The initial goal with “get one” is to return an artist object that does have some associated data. Study the associated album entity, and decide what would be good to return, and then make it happen.

 

Album – get all, get one (with detail)

The initial goal with “get all” is to simply return a sorted/ordered collection of AlbumBase objects.

Later you can modify that, to return album objects that have some associated data, in the form of objects and/or composed properties.

The initial goal with “get one” is to return an album object that does have some associated data. Study the associated album entity, and decide what would be good to return, and then make it happen. It’s in the “middle” of two associations (to artist, and to track), so seriously consider including data from both.

 

Track – get all, get one (with detail)

The initial goal with “get all” is to simply return a sorted/ordered collection of TrackBase objects.

Maybe later you can modify that, to return artist objects that have some associated data, in the form of objects and/or composed properties.

The initial goal with “get one” is to return a track object that does have some associated data. Study the associated album and artist entities, and decide what would be good to return, and then make it happen.

 

Add the Artist controller, implement the use cases, including views

Add the Artist controller. Protect it so that only authenticated users can use its actions/methods.

Get all

Handling the “get all” use case is familiar, and has no surprises.

For this Assignment 7, the appearance of the views can be reasonably bare and ugly, as generated by the scaffolder. Fix what needs to be fixed (e.g. title and so on). In the next Assignment 8, you will do something about that. If you’re interested in what’s expected, the specifications for that assignment will be posted reasonably soon (before the due date of this assignment).

Get one

Handling the “get one” use case is familiar, and has no surprises. However, the view needs to be edited, so that it renders the associated data from other objects.

As noted above, for this Assignment 7, the appearance of the views can be reasonably bare and ugly, as generated by the scaffolder. Fix what needs to be fixed (e.g. title and so on). In the next Assignment 8, you will do something about that. If you’re interested in what’s expected, the specifications for that assignment will be posted reasonably soon (before the due date of this assignment).

 

Add the Album controller, implement the use cases, including views

Add the Artist controller. Protect it so that only authenticated users can use its actions/methods.

Get all

Handling the “get all” use case is familiar, and has no surprises.

Same as above, the appearance of the views can be reasonably bare and ugly, as generated by the scaffolder. Fix what needs to be fixed (e.g. title and so on).

Get one

Handling the “get one” use case is familiar, and has no surprises.

Appearance – same as above…

 

Add the Track controller, implement the use cases, including views

Add the Track controller. Protect it so that only authenticated users can use its actions/methods.

Get all

Handling the “get all” use case is familiar, and has no surprises.

Appearance – same as above.

Get one

Handling the “get one” use case is familiar, and has no surprises.

Appearance – same as above.

 

 

Testing your work

In a browser, test your work, by doing tasks that fulfill the use cases in the specifications.

Remember to customize the app’s appearance (front/home page, menus, etc.) before you submit your work.

 

Reminder about academic honesty

You must comply with the College’s academic honesty policy. Although you may interact and collaborate with others, you must submit your own work.

 

Submitting your work

Here’s how to submit your work, before the due date and time:

1. Locate the folder that holds your solution files. In Solution Explorer, right-click the “Solution” item, and choose “Open Folder in File Explorer”. It has three  (or more) items: a Visual Studio Solution file, a folder that has your project’s source code, and a “packages” folder. Go UP one level.

2. Make a copy of the folder. This is the version that you will be uploading.

3. Remove the “packages” folder from the copied folder; also, remove the “bin” and “obj” folders.

4. Compress/zip the copied folder. The zip file SHOULD be about 2MB or less in size. If it isn’t, you haven’t followed the instructions properly.

5. Login to My.Seneca/Blackboard. Open the Web Programming on Windows course area. Click the “Assignments” link on the left-side navigator. Follow the link for this assignment. Submit/upload your zip file. The page will accept three submissions, so if you upload, then decide to fix something and upload again, you can do so.

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

Advertisements
%d bloggers like this: