# Friday, August 01, 2008

Action Precondition Filter

From a previous article I explain that an "Action Precondition Filter" fulfills the following common need in many web applications:

'I often find the need to check for the existence of a parameter passed to a web page, such as an ID, and also often need to check if the ID is valid as well (e.g.: a valid primary key).

In the spirit of Design By Contract, I would consider this check to be a sort of "Request By Contract", at least insofar as the concept of a "precondition".'
Currently, there are two flavors of Action Precondition Filters: PredicatePreconditionFilter & RegExPreconditionFilter

For more detail, see my previous article: ASP.NET MVC Controller Action Precondition Filter v2.

What is HandleErrorAttribute?

System.Web.Mvc.HandleErrorAttribute, introduced in ASP.NET MVC Preview 4, is the default concrete implementation of IExceptionFilter. It is a FilterAttribute used to handle exceptions and to specify a view to render when the exception occurs.

You can also denote specific exception types you are interested in catching, and specific custom error views for them by specifying the "ExceptionType" and "View" properties on [HandleError] attributes. The string specified in the "View" property denotes a view located either in the same directory as your other controller specific views (for example: \Views\Home), or within the "global" \Views\Shared folder.

What is the point of this article?

To show an example of how to use Precondition Filters in conjunction with HandleErrorAttribute to provide user-friendly error pages when users (or you, yourself...doh!) try to link to your URLs with invalid route data, query strings, etc.

For example, in the Company() controller action below, if someone access the URL as "/Home/Company/" or "Home/Company/0", they will be shown the content of the "error" view file "/Home/Company/HackedUrlWarning.aspx", educating them on their faux pas.

Show Me the Code!

Example Controller (to illustrate usage):

using System;
using System.Web.Mvc;
 
namespace MvcApplication1.Controllers
{
    
    public class HomeController : Controller
    {
 
        public ViewResult Index()
        {
            return View("Index");
        }
 
        [HandleError(ExceptionType = typeof(ArgumentOutOfRangeException),
 View = "HackedUrlWarning")]
        [RegExPreconditionFilter("id", PreconditionFilter.ParamType.RouteData, "^[1-9][0-9]*$", 
typeof(ArgumentOutOfRangeException))]
        public ViewResult Company(int id)
        {
            return View("Company");
        }
 
        [HandleError(ExceptionType = typeof(ArgumentOutOfRangeException),
 View = "HackedUrlWarning")]
        [PredicatePreconditionFilter("id", PreconditionFilter.ParamType.RouteData, 
"IsGreaterThanZero", typeof(ArgumentOutOfRangeException))]
        public ViewResult Employee(int id)
        {
            return View("Employee");
        }
 
        protected bool IsGreaterThanZero(object value)
        {
            try
            {
                int id = Convert.ToInt32(value);
                return id > 0;
            }
            catch
            {
                return false;
            }
        }
 
    }
 
}

Direct links to Source Code

PreconditionFilter (Abstract Base Class)

PredicatePreconditionFilter

RegExPreconditionFilter
.NET | ASP.NET | C_Sharp | MVC