DPS907 notes – Thu Sep 17

ASP.NET MVC refresher. Web API project structure and architecture guidance. Supporting all HTTP methods. Request routing. Exception handling. Data annotations.

.

Test (quiz) today

The course’s tests begin today. (You can also think of them as quizzes.)

Tests are written. Pen or pencil. Answer styles will vary, but we’re mostly looking for short- to medium-length answers, and/or diagrams, and so on.

No references or resources are permitted – “closed book, open brain”.

We’ll do the test at the beginning of the time period, at 9:50am. Today’s test will run about 12 minutes. (Future tests will range in length from 10 to 20 minutes, with a grade value that tracks the length of the test.)

The tested topics are mostly forward-looking. You are tested on your comprehension, understanding, and application of the current week’s topics. For this week, it’s mostly the notes below, and the posted code example. Also, you may be tested on a recently-covered topic, which enables you to show that you have the foundational knowledge needed for current and future tasks.

.

Refresh your memory, ASP.NET MVC

If you have been away from ASP.NET MVC web app programming for a semester or more, and need a refresher, continue reading.

If you have never done ASP.NET MVC programming – because your ASP.NET training used the Web Forms technology – you have a different kind of problem. Continue reading below, in the next section.

Your professor teaches the web apps course in the Software Development degree program, BTI420. The class notes page has full coverage of all the topics, and the resources page will be useful.

Here are some recommended highlights (green-headed sections) from the class notes.

January 13, 2015

  • Introduction to ASP.NET
  • Writing code, writing classes

January 20

  • Object initializers
  • Collections
  • Data relations/associations
  • LINQ (language-integrated query)

January 22 & 26

  • The “data manager” concept

January 27

  • The role of a view model class
  • What about design model classes, which describe our real-world entities?
  • What is AutoMapper? What problem does it solve?

February 3

  • Working with your classes in an Entity Framework environment
  • AutoMapper and associated entities

.

The web app code examples are also available, on the BTI420 GitHub repository. You can use a browser to view the code, or you can download the entire collection of projects in a single zip file.

.

Did you complete your ASP.NET web apps course in 2012 or earlier?

If yes, then you learned the “web forms” version of ASP.NET.

This course uses the ASP.NET Web API framework, which is based on ASP.NET MVC. As someone who learned “web forms”, the “MVC” technology is very different. In fact, it’s different enough that your previous “web forms” knowledge is obsolete and not useful.

Is it possible to adapt? Yes. Should you stay in the course? Well, it is possible to pass. What happened last year? Six students were in this situation. Three stayed in the course and passed. One stayed and failed. Two dropped the course.

How can you get help? Read, study, and practice the resources above in the “Refresh…” section.

Is there any other help available? Maybe. Send me email. It may be possible to schedule an extra dedicated session to cover the topics that will help you transition your past experience to the new frameworks.

.

The MVC design pattern

Modern web apps and web services are often based on the MVC design pattern.

MVC – model – view – controller – enables the programmer to clearly separate code modules into different roles:

  • Model code describes the app’s data, also known as persistent state
  • View code presents the app’s data to the user or requestor
  • Controller code interacts with the user and therefore manages the app’s workflow

The important idea is that the controller is the most important role. User input is handled by the controller, which then works with the app’s data, and then prepares the view that’s returned to the user.

How does this map to a web service?

  • Model code does the same job as it does in a web app
  • View code – for an HTML page – is not present; instead, your controller methods return an object (or a collection), and the response is prepared by the default built-in serializers, or in custom code
  • Controller code handles the HTTP requests, and implements the web service’s application logic

Read an overview of MVC in this Wikipedia article.

.

Inside a Web API project

An ASP.NET MVC web app or web service uses the front controller pattern (Wikipedia overview article). Every request is inspected by a single module, and then dispatched to the code module that can handle the request.

The dispatch destination is defined by routes. By default, web service request URIs include an “/api/” segment, although we can change that default in the future. Then, by default, the next segment of the route designates the controller that will handle the request. The HTTP request method, along with the presence of a query string, and/or an entity body, will then determine the method in the controller that handles the request. Routing basics are covered in this ASP.NET Web API article. Study the other articles in the “Routing” collection of articles.

Data in-and-out of  the web service is handled by serializers. By default, the Web API project template can handle three internet media types:

  • XML
  • JSON
  • Multipart form data (i.e. data from HTML Forms)

Serialization is introduced in this ASP.NET Web API article.

Which media type gets returned? It depends, on several factors. Read this ASP.NET Web API article on content negotiation (often abbreviated as “conneg”), and think about the different use cases.

.

System design guidance and how-to

During this course, you will learn to create a web service that has some level of sophistication. Therefore, you will need some guidance on how to design the system.

In your second-year web app programming and systems analysis courses, you used a “system design guidance” diagram to help you learn a set of topics. We will use a version of that diagram that’s customized for a web service. Click to open the PDF in a new tab/window:

System Design Guidance V7 for ASP.NET Web API web service

.

Code examples for this semester

Code examples will be 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 the 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 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-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.

However, a single “packages” folder has been placed at the root of the repository. After you download-and-unzip the repository, simply copy-paste the “packages” folder into any distinct code example’s folder to make it ready for use and learning.

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

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

.

Assembling a web service project

For the next week or so, please use the following technique to create a web service project.

  1. Make sure that you are using Visual Studio 2013, with update 3 or above (check HELP > About Microsoft Visual Studio for details)
  2. File > New > Project, in the “New Project dialog, select the “ASP.NET Web Application” project template
  3. Select a storage location, and name your project; un-check (clear) “Add to source control”
  4. On the next dialog “New ASP.NET Project”, select the “Web API” template item; un-check (clear) Web Forms and unit tests
  5. Authentication must be set to “Individual User Accounts”
  6. Un-check (clear) the “Host in the cloud” setting
  7. After the project is created, use the NuGet package manager to update all packages, and then build/compile the project

.

What is in the project?

It includes a web app and a web service.

The project includes the familiar “home” controller, enabling a browser to open the root of the web app. It also includes a “help” controller that will dynamically build a human-readable documentation set for your web service.

The project includes a web service controller (named “ValuesController”).

It also includes a persistence stack, based on the Entity Framework, connected to a local file-system-based database instance that runs in an on-demand SQL Server engine.

Finally, it includes an authentication and authorization framework, based on the emerging web standards for these tasks, OAuth2 and OpenID Connect (and it also includes connectors to third-party services, such as Google and Facebook). Later in the course, we will begin to use the security framework.

.

Prepare for class on Thu Sep 17

Create a new project, using the guidance from above. Use it to experiment while you work through the following notes.

.

Supporting all relevant HTTP methods

Our code example today will help you learn to support all relevant HTTP methods.

In addition, you will learn to create the correct response, which will be an error (as noted in a later section), or one of the results in the following table.

Request Return type Status code Comment
GET collection Collection 200
GET collection Empty collection 200 “Empty” is not an error condition
GET one One 200
GET one No item 404 Truly is ‘not found’
POST add item The added item 201 Added item typically includes an identity property
PUT item updated The updated item 200
DELETE item (no content) 204 The response body for DELETE requests have not been defined

.

Coding principles

In the later section (“HTTP status codes for errors), you will learn that our manager methods will return data, or null.

In our controller methods, the return types will be as follows:

  • Get all – return an entity collection, typically in an IHttpActionResult (second-choice alternative, an IEnumerable<T>)
  • Get one, add new, update existing – return IHttpActionResult
  • Delete one – return void, which automatically returns HTTP status code 204

The “get all” case will always be successful. That’s why we can set the method’s return type as IHttpActionResult (preferred), or to an entity collection type.

The “delete one” case may succeed, or fail. We don’t care at the controller level. By convention, a void return type returns 204.

For the others, the method’s return type will be IHttpActionResult. Always.

.

Review the section “Controller method return type” in the September 14 class notes.

.

For the following explanations, the week 2 code example named “AllHttpMethods” will be used. It has an entity named “Human”.

.

“Get one” explained 

In the manager, “get one” uses the object’s identifier. If found, return the appropriate resource model type. Otherwise, null.

In the controller, call the manager method.

If the return value is null, return HTTP 404, “not found”.

Otherwise, return an Ok() result, along with the object.

.

“Add new” explained 

In the manager, “add new” attempts to add a new object. The object’s data passed input data validation in the controller, so the attempt should succeed. In the future, you can add business logic here if you need additional validation to be done.

Return the appropriate resource model type.

In the controller, you must first check the model state (i.e. input data validation). If the data is bad, return BadRequest().

If you have a well-designed resource model class, and use data annotations, the quality of the input data rises.

In addition, this step guards against under-posting (missing data), and over-posting (too much data).

If successful, call the manager method. Then, return a Created() result, along with the new object.

The Created() result requires you to supply a URI for the new object. The runtime will use that URI as the value of the Location header. To construct a URI, use the “new Uri” constructor. The Url.Link method is a helper method (System.Web.Http.Routing.UrlHelper). The method takes two arguments:

  1. A route name, which can be seen in App_Start/WebApiConfig.cs, and
  2. A route value, which we get from the new object’s “Id” (identifier) property

The “route name” will resolve to a URI that effectively is the base URI to this controller’s actions. The “route value” is then appended.

.

“Update existing” explained

In the repository, “update existing” first attempts to fetch the existing object. If the existing object does not exist, null is returned.

Alternatively, if successful, it has a reference to the object, and will proceed to update the object, and then return the updated object:

  1. ds.Entry(p) is the reference to an object “p”
  2. .CurrentValues is the object’s collection of current values
  3. .SetValues(updatedP) will update/change those values with the new supplied values

The SetValues method ignores missing properties, as well as navigation properties to associated objects.

In the controller, you must first check the model state. At the same time, for “update existing” scenarios, you must ensure that the identifier on the URI matches the identifier in the request entity body. If the data is bad, return BadRequest()..

This step guards against some kinds of attacks.

Alternatively, if successful, call the manager method. If successful, return an Ok() result and the updated object.

.

“Delete existing” explained

In the manager, “delete existing” first attempts to fetch the existing object. If the existing object does not exist, do nothing (but in the future, we’ll fix that).

Alternatively, if successful, it attempts to remove the existing object from the collection. This attempt is guarded by a try-catch block. The attempt may fail, because the existing object may be associated with other objects.

In the controller, we simply call the manager method. We don’t care if the object exists, because we don’t want to reveal too much information (to the requestor) about our entity collection.

.

Which controller method executes?

You have learned that an ASP.NET Web API web service uses the front controller pattern to determine which method in which controller to run when a request is received.

How does the algorithm work?

Before we cover the steps, think about the data that could be part of a request. A request could include simple data types, and/or complex data types.

Simple data types – in the URI and/or query string – include:

  • int, single, double, decimal
  • string, byte, char, bool, guid
  • datetime, timespan

Complex data types – in the message body – include:

  • anything else; typically any instance of a class
  • your own classes, or .NET Framework classes
  • one-of, or collections-of

Here’s the algorithm:

1. The URI is inspected, looking for a controller name match

2. The HTTP method is inspected

3. The request’s data is inspected – data could be part of the URI and/or query string, or in the message body

Interestingly, these two URIs are the same, for a ‘get-one’ request:

http://example.com/api/foo/3

http://example.com/api/foo?id=3

Then:

4. Identify all controller methods that match the HTTP method name (e.g. ‘GetSomething‘)

5. Match the simple parameter data types – that should be enough to uniquely identify the controller method

If step 5 above yields more than one match, the runtime throws an exception, with a useful message that tells you how to improve your code to avoid the problem in the future.

.

Documentation

Mike Wasson has two articles that provide more detail, on the official asp.net/webapi web site:

Routing in ASP.NET Web API

Routing and Action Selection

.

Exception handling, version 1

This is an initial entry-level treatment of exception-handling. Later in the course, we will learn more about this topic, and improve our treatment.

Our code example today will help you learn how to handle errors and exceptions in your web service.

.

HTTP status codes for errors

In our web APIs, if there is an error, we must return an HTTP error code.

Study the list of HTTP status codes. We may use a number of ‘client’ error codes, and maybe a few ‘server’ error codes:

Code Title Description
400 Bad request Request syntax is not correct
401 Unauthorized Authentication required; the response includes how-to-authenticate info
403 Forbidden Authentication was successful, but the request fails authorization
404 Not found
405 Method not allowed Method not allowed for the resource; response MUST include an Allow header containing a list of valid methods for the requested resource
415 Unsupported media type Request entity body format is not supported
500 Internal server error Default generic message, limit its use please
501 Not implemented Request method not implemented; cannot fulfill the request

Looking for documentation? This Wikipedia article is readable. However, the official source is RFC 7231.

.

Coding principles

Our ‘version 1’ strategy is to handle request errors in a simple yet informative manner.

In this version, our manager methods will return data, or null. The null value will indicate that there’s no data, or an error.

In our controller methods, we will interpret null as ‘no data’ or an error. Its meaning will depend on the method’s context.

Later, our ‘version 2’ strategy will be extended to handle additional kinds of errors, in a way that covers the entire application, with less code to write and maintain.

.

Data annotations overview

Most students in the course are familiar with data annotations. This section will refresh your memory, but with a web service focus. If you need to learn about data annotations, continue reading and studying.

Data annotations are descriptive text attributes that we add to properties in a class. A data annotation is located just before/above the property declaration.

Data annotations can help with:

  • property constraint and limits
  • input data validation
  • property display and formatting in views
  • communicating error messages to users

Some data annotations are intended only for design model classes, while others are for use with resource model classes. And, some work with both.

Their overall benefit is to reduce the amount of code that has to be written to handle typical data management scenarios.

Please note that data annotations DO NOT replace the need to validate data against business rules and/or application logic. You still need to do that. Data annotations help most by improving the quality of input data, so that it can then be inspected for its integrity and appropriateness.

.

Data annotations for design model classes

In your design model classes source code file, add a ‘using’ directive for this namespace:

System.ComponentModel.DataAnnotations

Useful data annotations for design model classes include:

[Required] (implemented as ‘not null’ in the database)

[StringLength(n)] (implemented as a specific ‘varchar’ value in the database)

You can comma-separate multiple data annotations.

Value types (e.g. int, double) CANNOT use the [Required] attribute.

There are a few others that you may use occasionally; we may discuss them later in the course.

Do you need a ‘default value’ for a property? A data annotation will not help.

Instead, as you have learned, simply create a class constructor, and set the property’s default value there.

.

Data annotations for resource model classes

In your resource model classes source code files, add a ‘using’ directive for this namespace:

System.ComponentModel.DataAnnotations

Useful data annotations for resource model classes include:

[Required]

[StringLength(n)] or [StringLength(n, MinimumLength = m)]

[Range(min, max)] (int or double types) 

[DataType(DataType.Password)] (others include EmailAddress, Url, Currency, Date, Time, and MultilineText)

[RegularExpression(“regex“)] (a regular expression; omit the ^ and $ delimiters, because they’re assumed)

In a regular expression, sometimes you need the backslash character (e.g. \d). In a .NET Framework string, the backslash is a quote character. So, you either precede the entire string with an at sign (@), or use a double backslash (\\d).

Common situations:

[0-9]+ – digits only
[a-zA-Z]+ – letters only
[0-9a-zA-Z]+ – digits and letters only

.

As before, you can comma-separate multiple data annotations, and value types (e.g. int, double) CANNOT use the [Required] attribute (but the [Range(min, max)] attribute effectively solves that problem).

.

Custom error messages

All attributes accept a parameter named “ErrorMessage”. The value is a custom error message for the user. For example:

[Range(2, 6, ErrorMessage=”Selected gizmos must range from 2 to 6″)]

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

Advertisements
%d bloggers like this: