BTI420 notes – Fri Mar 18 and Mon Mar 21

Handle request errors in an ASP.NET MVC web app

This section suggests an approach for gracefully handling request errors in an ASP.NET MVC web app. Inspiration for some of this was suggested by this StackOverflow answer.

What is the problem?

For new ASP.NET MVC programmers, two request errors are often seen:

HTTP 404

Server Error – An unhandled exception…

The first error – HTTP 404 – happens when a requested resource does not exist. Click the image to open it full-size in a new tab/window.

The other happens when there’s a logic error in your code. For example, if you make a request that does not include a required argument (e.g. /products/details, without the /123 argument), you will see the following:

In both situations – and in any error situation – you must NOT show this error screen to users.

What should you do?

Add code to your project, so that a “not found” response looks similar to this:

And a ‘server error’ response looks similar to this, for browser users on the web:

For you – the programmer – a bit more information can be added, to help you locate the error:

It is enough for new ASP.NET MVC programmers, but it may not be enough for a production web app at scale.

There are third-party (via NuGet) error logging frameworks that can be added to a project, which offer more features and functionality.

Adding error-handling to a project

This solution will be added to a future project template. Here’s how it works.

We will add code to the project. We’ll add an ‘errors’ controller (and some views), and another (event handling) method in the MvcApplication class.

Add an ‘errors’ controller

Add an errors controller; you can use the ’empty’ template.

Change its class declaration to include the ‘sealed’ modifier:

public sealed class ErrorsController : Controller

Our solution will handle two types of errors:

not found, and

server error

Here’s some suggested code. We will use the ViewBag property to easily pass simple data to the view, and avoid the need to create view model classes.

Add views for ‘not found’ and ‘server error’

Add views for the two methods. You can use the ’empty’ template.

Add your own content to make a useful page. You can implement the suggestions seen above.

Add methods to the MvcApplication class

We will write two methods in this class:

an event-handler, for “end request”

a private method, to initialize the errors controller, and call one of its methods

In an ASP.NET MVC 5 web app, the an instance of the MvcApplication class is created (by the ASP.NET runtime) when the first request is received. The app’s lifetime is twenty (20) minutes after receiving a request (and this timer is reset with each new request). At the end of the app’s lifetime, the ASP.NET runtime gracefully terminates the app.

The purpose of the MvcApplication class is to handle events that happen during the app’s lifetime. As a web app, all events are triggered during the handling of an HTTP request.

The Global.asax.cs source code file holds the definition of the MvcApplication class. It includes code for the Application_Start() method, which is called by the ASP.NET runtime to handle the Start event, and thereby begins the app’s lifetime.

We can write methods to handle other events. Which other events? A few are interesting now, and perhaps in the near future:

BeginRequest

EndRequest

Error

AuthenticateRequest

AuthorizeRequest

For this situation, we will write a method to handle the EndRequest event. How?

By convention, event-handling methods in the MvcApplication class return void, and have a composite name:

Application underscore event-name

Look at the Application_Start() method name as an example. To handle the EndRequest event, the declaration of its event-handling method will be:

The ASP.NET runtime will create additional instances of MvcApplication, to enable the app to handle multiple requests (in parallel) at the same time. How many? That number is set by default at the web server, and can be changed by an agreement between the app programmer(s) and the web site manager(s).

While there many be multiple instances of MvcApplication running, the Application_Start()method runs only once at the beginning of the app’s lifetime.

If you are using the MvcApplication class to initialize global (to the app) state (e.g. data, resources), be careful. Do the research. Make sure that you use the different kinds of app state storage appropriately. Recognize what kind of app state storage is global to the app (e.g.application state), and what kind of app state storage is local to a specific instance of an MvcApplication class (e.g. class-level properties and fields).

Rich text editing

CKEditor is a JavaScript app that replaces an HTML <textarea> element with a nice-looking and highly-functional rich text editor.

As you read this section, open and study the RichTextNotesApp code example.

Here’s what you need to know to use CKEditor:

The editor works with string properties in a view model class.

For best results, add the [DataType(DataType.MultiLineText)] to a string property (in a “…Form” view model class), and at runtime, the Razor view engine will render it as an HTML <textarea> element in a Create or Edit view.

Near the top of the view – maybe below the @ { } code block – add a reference to CKEditor. For best results, get it from its content delivery network:

<script src="//cdn.ckeditor.com/4.5.7/standard/ckeditor.js"></script>

Then, just below the code that renders the text area, convert the HTML <textarea> element into an editor:

<script>CKEDITOR.replace('Content', { startupFocus: true });</script>

The code above assumes that the HTML <textarea> element has a name attribute with a value of “Content”. If you do not need the startupFocus attribute, then remove it.

Controller method to handle the HTML Form post

Normally, the ASP.NET runtime prevents HTML markup or script code from being posted to a controller method, for obvious security reasons.

In this situation, we know that the rich text editor will include HTML code, and yes, we do want it. Therefore, we have to add this attribute to the controller method that handles the HTML Form post:

[ValidateInput(false)]

Render rich text string properties in the user interface

Normally, string content is HTML encoded when it is displayed in a view (e.g. List, Details, Delete).

In this situation, we want rich text string content to be displayed as-is. Therefore, we must render it with a different HTML Helper. Assuming that the “Content” property is a rich text string, write this code:

@Html.Raw(item.Content)

Work on Assignment 8

Your professor will guide students as we get started on Assignment 8.

This assignment has a two-week lifetime. It is due on March 31 for sections B and C, and on April 3 for section A.

Today, before you leave the room at the end of the time slot, ensure that you give the Work Report to your professor, for the in-class grading part of the assignment.