DPS907 notes – Tue Sep 12

Coding practices. Debug a web service. New project template. Work on the assignment.

 

Today and Thursday

Today, the in-class coverage and discussion is intended to get you comfortable with the basic or foundational features of a web service project.

You now have some experience with “get all”, “get one”, and “add new” requests. We’ll build on that knowledge. Then, we’ll look at the other basic requests, “edit existing”, and “delete item”.

Next, we’ll learn about, and begin using, a new project template that includes a database with lots of data.

That enables us to set the stage for working with data, associated data, and so on. Each topic builds upon previous topics.

 

Code examples

Code examples are published on a public GitHub repository.

GitHub is a hosting service for source code. It offers a web interface to enable easy browsing. It also offers a set of tools and capabilities that enable software developers to publish code, collaborate with others, and improve their productivity and effectiveness.

On this web site, a link to the repository is on the right side of this page, near the top. (For best results, open the link in a new tab or window.)

Beginners can use a web browser to view the source code. You can also click the “Download ZIP” button to get a full and complete copy of all code examples in the repository.

For this course, the code examples will be published weekly, in logically-named folders (e.g. “Week_02”).

During the course’s lifetime, about twenty or more code examples will be published.

As you have observed, each ASP.NET web app or web service project includes a sizable “packages” folder. In the GitHub code repository, each distinct code example does not include the “packages” folder, as a time- and space-saving measure. Each “packages” folder is about 50MB in size, so twenty code examples would require about 1GB storage. The contents of the “packages” folder does not compress much.

Therefore, if you have downloaded and opened a project in Visual Studio, you must do a build/compile before you begin working with it. The build/compile action will fetch the packages it needs from the web.

All code examples are designed to be usable immediately and error-free. Each should compile and execute correctly. 

If you have any problems with a code example, please contact your professor. 

 

Reminders about coding in ASP.NET web apps

After completing your work on Assignment 1, you probably were reminded about coding practices and principles, and you had to refresh your knowledge and skills somewhat. At this point, we’ll summarize some of the common coding tips, in an effort to increase your productivity and confidence.

 

Design model classes

The class name must be singular.

The database-generated unique identifier, and key, should be named “Id”.

Use data annotations. Typically, we can use only Required and StringLength, and only on string properties (with one exception; see below).

Always add a default constructor. Use the “ctor tab tab” practice to easily generate that code block. In the default constructor, initialize the value of:

  • DateTime properties
  • Collections (can usually be of type List<T>)
  • Other property values that you believe must be initialized for safety or data integrity purposes

A navigation property for an associated collection will always be of type ICollection<T>.

A navigation property for an associated object will have the same type as the associated object. Almost always will this navigation property have a Required data annotation. (In other words, it depends upon the existence of an associated object.)

 

Data context

The data context is the “gateway” from your app to your database. The Entity Framework infrastructure provides runtime mapping between your data model (as defined in the design model classes) and database tables.

For each design model class, create a DbSet<T> property. It is then exposed as an entity collection.

 

View (resource) model classes

The properties needed for a resource model class MUST exactly match, or meet the needs of, the use case.

The class name ought to be in the format EntityPurpose, where “Entity” is the name of the entity collection we’re working on (e.g. Customer, Product, etc.), and “Purpose” is the name of the purpose or usage of an object or collection of this type.

Often, for typical data CRUD tasks, we can use a hierarchy of classes. For example:

CustomerAdd – all the properties needed to fulfill an “add new customer” use case

CustomerBase – often inheriting from CustomerAdd, also includes the object identifier property, and maybe other manager or store generated properties

CustomerEditAddress – the object identifier, and the properties needed to fulfill an “edit customer’s address” use case

Do not force inheritance to be used. If it’s right, do it. If not, don’t.

Use data annotations. We can use a wider range of annotations in resource model classes.

Add a default constructor if you have DateTime properties and/or collections (of any kind). And, if you want initial values for any other properties, do that work here too.

Collection types – whether they are collections of simple types, or as navigation properties, must be of type IEnumerable<T>.

 

AutoMapper 

Add the AutoMapper package. (Later versions of the new project template will already have AutoMapper.)

Configure it, as you have learned, in the manager class.

 

Manager methods

The manager defines and creates a reference to the data context class.

Manager method names ought to be in the format EntityTask, where “Entity” is the name of the entity collection we’re working on (e.g. Customer, Product, etc.), and “Task” is the name of the task we’re performing (e.g. GetAll, GetOne, Add, etc.).

Manager methods will accept, as parameters, nothing, or one or more standard types or custom types. Most often, the custom type will be a view (resource) model type.

When working with the data context, we use LINQ to filter and sort the results.

If you need an associated object or collection, the Include() extension method is used.

Manager methods that are used by controllers NEVER accept or deliver design model objects or collections. Instead, they must ALWAYS accept or deliver view model objects or collections.

Manager methods can also return void, or bool, or other types as appropriate for the use case.

 

Controller and methods

Each controller defines and creates a reference to the manager class.

Controller methods NEVER have direct access to the data store infrastructure.

Almost all controller methods will use the IHttpActionResult return type.

Controller method parameter types are simple, or of a view (resource) model type.

Do as little work as possible in the controller method. Rely on the manager methods to do the bulk of the work. However, you can still do your own local filtering and sorting if you wish, before returning the result to the requestor.

 

Filtering

Within a manager method, before returning the results, we often need to perform other tasks on a collection, such as filtering or sorting. For example, assume that we wish to select only those Program objects that have a Credential property value of “Diploma”:

var programs = ds.Programs.Where(c => c.Credential == "Diploma");

 

In the following example, assume that we wish to select only those academic Program objects that include an academic Course object with a specific identifier. Let’s build the statement in two steps.

By default, when we fetch an object that is related/associated with another object and/or collection, the object that is fetched does not include the related/associated objects. That is the default behaviour of the way we have configured the data object.

Therefore, to build the statement, we first must use the Include method, as shown next:

var programs = ds.Programs.Include("Courses");

 

Its return type is DbQuery<TEntity>. (It’s a collection.)

The second task is to add the filtering to the statement, as shown next:

// Assume that "id" has been passed into the method
var programs = ds.Programs.Include("Courses")
    .Where(p => p.Courses.Any(s => s.Id == id));

 

The return type of this statement is IQueryable<TEntity>.

As noted above, return the results as an enumerable. Typically, an AutoMapper mapper does that work.

 

Sorting 

In this example, assume that we wish to sort the Program collection by a property named Code:

var programs = ds.Programs.OrderBy(s => s.Code);

 

The OrderBy() extension method is defined in the Queryable class (look at the inheritance and implementation list above). This method can be used on any object of type IQueryable<TEntity>. Its return type is IOrderedQueryable<T>.

As noted above, return the results AsEnumerable().

 

Filtering and sorting

You can combine tasks by chaining the filtering and sorting tasks above. The statement below has been wrapped for clarity:

var programs = ds.Programs
    .Include("Courses")
    .Where(prog => prog.Courses.Any(crs => crs.Id == id))
    .OrderBy(sort => sort.Code);

 

The Any method returns a boolean, so it’s ideal for use in a lambda expression. It determines whether any element of a sequence satisfies a condition. Therefore it needs a lambda expression of its own.

Here’s how to read, in English, this statement:

Fetch the Program collection…
and for each Program object…
include the related Course object(s)…
but only where a Program object’s Course collection…
contains any Course objects that have an Id property that matches a passed-in “id” value…
then sort the result by the Program object’s Code property value.

As noted above, return the results as an enumerable.

 

Other information

Please – please – take advantage of the existing web apps course content:

petermcintyre.com/bti420/notes

It is (can be, will be) your reference for all the topics for which you need reminders or refreshers. Don’t use unapproved Google search results, use the content linked above instead.

That web site has a search feature. Depending on what you’re looking for, the search feature may not yield very good results.

So, you can use Google to search the web site. For example, to search only the web app course note for “automapper”, enter this in a browser’s address or Google search bar:

automapper site:petermcintyre.com/bti420/notes/

In the list of results, you can ignore the content from past years. The most current results do not include the year number in the URL.

 

Debugging ASP.NET projects

Many students will be familiar with the Visual Studio debug tools as a result of their work in C++, and the debug process in ASP.NET projects. If you started your web apps course in the Winter 2017 academic term, then you learned how to debug ASP.NET MVC web apps in early February.

In the computer-lab session on February 3 or 6, you had an in-class guided exercise on debugging. Skim those notes to refresh your memory and remind you of the process.

Note: If you’re not comfortable with the debug process, then stop now, and carefully go through those notes, and the code example. The time you spend getting comfortable debugging will be returned to you many times over in the future. Debugging is an essential and important skill.

 

In this week’s code example repository, there is a DebugIntro project. Get it, and run it in debug mode. Interact with it using Fiddler. In the past, you used a browser to send a request. Now, you use Fiddler.

As delivered, it will fail with “get all customers” request.

Also, as delivered, it will fail with the “edit customer” request.

 

Introducing a new project template

Recently, you learned that we plan to use custom-configured Visual Studio new project template that will help you learn web services. It includes a sample database with hundreds (thousands?) of data rows. (You may have used custom new project templates in your web apps course too.)

The sample database holds data for a music business. It has artists, albums and tracks. It has customers, who have purchased music, so there are invoices and invoice details.

The new project template is in the “Templates_and_solutions” folder in the repository. Here’s how to use it:

  1. Download (or clone) the repository.
  2. Open the Templates_and_solutions folder, and select the file named “Web service project v1.zip”. (Do NOT unzip the file.)
  3. Copy it to this folder on your system:
    %userprofile% > Documents > Visual Studio 2017 > Templates > Project Templates > Visual C# > Web

Then, when you create a new project in Visual Studio, it will be available for selection.

 

Reminder about the identifier

Almost all entity classes have an identifier property, usually an integer. Its name is almost always “Id” or “<entity>Id”.

For example, a Product class could have an identifier named “Id”, or “ProductId”.

For new entity classes that we write, we recommend using the simple “Id” name. In our opinion, including the name of the entity class in the identity-property name is redundant; it adds no value.

The sample database does not follow that recommendation. (We did not create the sample database. Luis Rocha probably did.) Instead, its design model class identifier properties have names like this:

  • ArtistId
  • AlbumId
  • TrackId

Problem? Yes, in resource model classes, when working with the Visual Studio web app view generator/scaffolder, and the Web API framework JSON and XML media formatters (i.e. the serializers). Let us explain:

A resource model class for the Artist entity might be named “ArtistBase”. The generator / scaffolder / media formatter will assume that the identifier is “ArtistBaseId” – in other words, the class name, plus the “Id” suffix. However, the identifier is simply “ArtistId” (without the word “Base” inside).

How can we fix this? Use the [Key] data annotation, in resource model classes, for identifier properties.

 

Class diagram

Here is a class diagram, in PNG image format. Click to open it full size in a new tab/window:

chinookmodel2016fall

 

Get started on the assignment

Assignment 2 is now available.

Before leaving the classroom at the end of the timeslot, hand in your work report.

 

 

 

 

 

 

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

Advertisements
%d bloggers like this: