Software Development

Setting up a website that uses multiple projects

I’m looking at the possibility of restructuring some of our applications to unify them under one brand and one site. Currently our applications are on different sub-domains of our main domain and we’d like to bring all that under one roof so our application can be something like https://app.example.com and that’s it.

To that end I’m looking at setting up a central project (a portal, if you like) that the user enters and logs into and from there they can move off into the various applications depending on what they want to do. Each of the application would sit in a virtual directory off the main application.

Basic Setup

Each of the projects needs to have the project properties in the web tab synchronised so that they are in agreement with each other. I decided on a port number to use and duplicated that across each of the projects.

Root Project

To start with the root project (that’s the one that appears at the root of the domain) should be set to use IIS Express.

  • In the solution explorer right click the project and then select “Properties” from the menu, alternatively click the project then press Alt+Enter.
  • Once the properties appear go to the “Web” tab and scroll down to the “Server” section.
  • Ensure that “Use Local IIS Web Server” is selected
  • Check “Use IIS Express” if it isn’t already.
  • In the project URL choose a port number that you want to use across each of the projects. (You can leave the default for this project if you wish, but take a note of it for the others)
  • Press “Create Virtual Directory” to set up IIS Express.
Setting up the root application
Setting up the root application

Remember the port number that was used for the root project as it will be needed for the other projects.

Set up the first application

In the first application project put similar details in Project Properties.

The only difference is that the Project URL has a virtual directory added to it.

Setting up the first application
Setting up the first application

Set up the second application

This is similar to the first application, except that the Project URL has a different virtual directory added to it.

Setting up the second application
Setting up the second application
Software Development

ASP.NET MVC 3 – Introduction to validation

In my previous post on MVC 3 I started a project to calculate a calorific intake required to maintain a stable weight. In this post I’ll extent that to add some validation to the inputs.

At the moment, since there is no validation, the use can just submit the input as it is with the default values. This produces this not so useful result:

1 - Result without validation

ASP.NET MVC 3 introduces unobtrusive client validation. It uses the data attributes available in HTML5 to store bits of data about the validation so that it can work more effectively and cleanly. If you want to enable unobtrusive client validation you need to add the following to the appSettings section in the web.config file:

<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>

Since our project is brand new (not being upgraded from a previous version of ASP.NET) then the appSettings is already there. It is also possible to enable or disable this for individual views.

You also need to add the following to the <head> section of the _Layout.chhtml file:

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

At this point we need to attribute the view model so that it knows what validation rules to put in place. The view model class file needs an additional using statement:

using System.ComponentModel.DataAnnotations;

Then each property can be attributed appropriately. The model is updated to look like this:

public class HarrisBenedictViewModel
{
    public HarrisBenedictViewModel()
    {
        LifestyleRates = new List<KeyValuePair<string, int>>();
    }

    public bool IsMale { get; set; }

    [Required(ErrorMessage = "Weight is required.")]
    [Range(50, 500, ErrorMessage = "Weight must be between {1}kg and {2}kg.")]
    public double Weight { get; set; }

    [Required(ErrorMessage = "Height is required.")]
    [Range(100, 250, ErrorMessage = "Height must be between {1}cm and {2}cm.")]
    public double Height { get; set; }

    [Required(ErrorMessage = "Age is required.")]
    [Range(18, 100, ErrorMessage = "Age must be between {1} and {2} years old.")]
    public int Age { get; set; }

    public double BasalMetabolicRate { get; set; }
    public IList<KeyValuePair<string, int>> LifestyleRates { get; set; }
}

As can be seen Validators can take string formatting placeholders so that if the data for the validation the message automatically updates to match, helping with the DRY principle.

The view also needs to be updated in order that the error messages are output when the user puts in incorrect data.

In the previous post, the fields in the input view looked like this:

<div class="editor-label">Height (in centimetres) </div>
<div class="editor-field">
    <input type="text" name="Height" value="@Model.Height" />
</div>

However, now we have to start using Html.EditorFor and Html.ValidationMessageFor as the validation feature adds a lot of data-* attributes to the elements in order to work.

If we change the .cshtml file to use the HTML Helper methods it looks like this:

<div class="editor-label">Height (in centimetres)</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Height)
    @Html.ValidationMessageFor(model => model.Height)
</div>

And the rendered output looks a little like this (modified slightly to word-wrap on to this blog):

<div class="editor-label">Height (in centimetres)</div>
<div class="editor-field">
    <input class="text-box single-line" data-val="true"
        data-val-number="The field Height must be a number."
        data-val-range="Height must be between 100cm and 250cm." data-val-range-max="250"
        data-val-range-min="100"
        data-val-required="Height is required." id="Height" name="Height"
        type="text" value="0" />
    <span class="field-validation-valid" data-valmsg-for="Height"
        data-valmsg-replace="true"></span>
</div>

Now if the application is run up then the validation kicks in when the submit button is pressed and the user is presented with messages telling them what needs fixed in order to submit the form

2 - Result with validation

Summary

In this post I’ve introduced the concept of unobtrusive client side validation. It should be stressed that if JavaScript is disabled on the browser then validation does not take place. By the same token, if a user crafts an HTTP Post request to the server, the validation will not have taken place either.

You can download the source code if you want to have a play with it.

Software Development

Starting an ASP.NET MVC 3 application

In this post, I’m going to show the basics of starting an application with ASP.NET MVC 3. The demo application will be a simple calorie counter that takes in a number of values from the user that is then used to calculate the calorific intake. The original calculation can be found here here: How many calories should I be eating?

First, if you don’t have it already, you’ll need to download ASP.NET MVC 3. Remember to shut down Visual Studio 2010 for the installation. And if you don’t have it already, I’d also recommend downloading Visual Studio 2010 SP1 and upgrading to it.

Creating the project

In Visual Studio 2010, from the New Project Dialog, go to the Visual C#/Web templates section and select ASP.NET MVC 3 Web Application from the list in the middle. If you don’t see it, ensure that the drop down says .NET Framework 4.

For this project, the Name will be set to “HarrisBenedictCalculator” as that is the type of calculation that the application will be performing.

1 - Visual Studio 2010 New Project dialog

Once the appropriate details are entered the OK button takes you to a more specific dialog for ASP.NET MVC 3 projects.

Since I want to show everything rather than rely on existing templates where some of the ground work is already done, I’m selecting the Empty template. I’m also going to select the “Use HTML5 semantic markup” and set the view engine to Razor.

Because we are selecting the empty template, unit tests project creation is not available. We can do that later.

2 - New ASP.NET MVC 3 Project dialog

When the second dialog is OK’ed the project will be created. For all that I selected “Empty” Visual Studio has created an awful lot of files already.

What’s already in this “empty” project?

3 - What's in the empty ASP.NET MVC 3 project

The project contains a set of predefined folders, some of which are already populated with files.

  • Content: Contains static content files such as CSS, graphics and javascript files.
  • Scripts: Contains a profusion of javascript files.
  • Views:  This contains some files that act like Master files for the Razor engine, an error page Razor template and a web.config.

The top level folder also contains a global.asax file which defines a set of default routes and filters, a packages.config file which is used by NuGet and a set of web.config files.

If you attempt to run the application as is then it will compile, but you go directly to a error message that says “The resource cannot be found” because there are not controllers as yet, so the routing engine cannot find a route for the default resource.

4 - Resource Not Found

For the moment, we are going to have a simple static HTML page for the error. To that end the web.config will have the following added to it:

<customErrors mode="RemoteOnly" defaultRedirect="Error.htm" />

We will see error messages, but once deployed the end users won’t. If you want to learn more about error handling see this other post on custom error handling in ASP.NET MVC 3.

Creating the initial view and controller

First up we are going to create the model of the view, the ViewModel if you like. This will contains all the variables needed to generate the request and receive data back in the response.

public class HarrisBenedictViewModel
{
    public HarrisBenedictViewModel()
    {
        LifestyleRates = new List<KeyValuePair>();
    }

    public bool IsMale { get; set; }
    public double Weight { get; set; }
    public double Height { get; set; }
    public int Age { get; set; }
    public double BasalMetabolicRate { get; set; }
    public IList<KeyValuePair<string, int>> LifestyleRates { get; set; }
}

Incidentally, I always initialise lists so that I don’t have to do a null check. Normally most code will loop over the list, an empty list will loop the same number of times as a list that isn’t there.

Now, we are ready to create the controller. When you right click on the Controllers folder in the project structure, you get an “Controller…” option in the "Add” sub-menu.

5 - Add Controller

For this, I’m going to create a controller called Main and leave it empty. That gives us a class called MainController that is derived from Controller.

The controller is going to have two actions (this is a very simple application), one called CalculatorInput which will simply return a view for accepting the values, and the other called CalculatorResult which will display the results of the calculation. Both views use the view model we created earlier.

The CalculatorInput method looks like this:

public ActionResult CalculatorInput()
{
    HarrisBenedictViewModel viewModel = new HarrisBenedictViewModel();
    return View(viewModel);
}

The empty view model will be populated by the user. If we want to pre-populate values on the view then we can do so by setting the appropriate values in the view model.

ASP.NET MVC uses naming conventions to find things. So, by default, the view will be in a folder named after the controller (in this case “Main”) and the view will be named after the controller action (in this case “CalculatorInput”).

To create the View, create the appropriate folder in the Views folder (if it doesn’t already exist) and then right click the folder you’ve just created and select Add->View…

A dialog appears that looks like this:

6 - Add View

@model HarrisBenedictCalculator.Models.HarrisBenedictViewModel

@{
    ViewBag.Title = "Harris Benedict Calculator";
}

<h2>Harris Benedict Calculator</h2>

@using(Html.BeginForm("CalculatorResult", "Main", FormMethod.Post)){
    <fieldset>
        <legend>Information about you</legend>

        <div class="editor-label">Are you male?</div>
        <div class="editor-field">@Html.CheckBox("IsMale", Model.IsMale)</div>


        <div class="editor-label">Weight (in kilos)</div>
        <div class="editor-field"><input name="Weight" value="@Model.Weight" /></div>

        <div class="editor-label">Height (in centimetres)</div>
        <div class="editor-field"><input name="Height" value="@Model.Height" /></div>

        <div class="editor-label">Age (in years)</div>
        <div class="editor-field"><input name="Age" value="@Model.Age" /></div>

        <div class="submit"><input type="submit" value="Calculate!" /></div>
    </fieldset>
}

The view sets up the form for getting the user inputs.

The Html.BeginForm defines where the form will be sent to once it is complete and how it will be sent. In this case, the form will be sent by and HTTP POST to the CalculatorResult method on the MainController class. I’ll talk more about what that does in the next section.

The form consists of a number of inputs which, by convention, have the same name as properties on the Model. If the model is pre-populated then the initial values will be used to populate the values in each of the input elements.

The CheckBox is a special case. Because of the way HTML works, if the checkbox is unchecked then nothing is returned. The MVC application then does not know if the checkbox was not ticked, or if the checkbox simply didn’t exist at all. This may be an important distinction. Therefore an Html helper method is available that outputs the checkbox and an hidden field to go with it.

At this point we can run the application and get the initial view being displayed to us:

7 - Rendering first view

Submitting the answers

As I mentioned above, the Html.BeginForm helper method tells ASP.NET MVC what controller and method to return the result to when the user presses the submit button. So, we have to create a method to process that on the specified controller (in this case Main)

The Main.CalculatorResult method looks like this:

[HttpPost]
public ActionResult CalculatorResult(HarrisBenedictViewModel viewModel)
{
    double bmr = 0; // Base Metabolic Rate
    if (viewModel.IsMale)
    {
        bmr =
            66 +
            (13.7 * viewModel.Weight) +
            (5 * viewModel.Height) -
            (6.76 * viewModel.Age);
    }
    else
    {
        bmr =
            655 +
            (9.6 * viewModel.Weight) +
            (1.8 * viewModel.Height) -
            (4.7 * viewModel.Age);
    }

    viewModel.LifestyleRates.Clear();
    viewModel.LifestyleRates.Add(
        new KeyValuePair<string, int>("Sedentry", (int)(bmr * 1.2)));
    viewModel.LifestyleRates.Add(
        new KeyValuePair<string, int>("Lightly Active", (int)(bmr * 1.375)));
    viewModel.LifestyleRates.Add(
        new KeyValuePair<string, int>("Moderately Active", (int)(bmr * 1.55)));
    viewModel.LifestyleRates.Add(
        new KeyValuePair<string, int>("Very Active", (int)(bmr * 1.725)));
    viewModel.LifestyleRates.Add(
        new KeyValuePair<string, int>("Extra Active", (int)(bmr * 1.9)));

    return View(viewModel);
}

The above performs the calculation. The code may look a bit long, but the calculation is relatively simple. In a full business application this code would be separated out elsewhere.

The method is decorated with the HttpPost attribute which tells MVC that the method may only be called in response to an HTTP POST verb. The method also takes the view model class as a parameter. MVC will may the form inputs to the view model class as best it can. You can also specify a list of more primitive types (like int, string, double, etc.) that map to the input elements on the form.

The method itself performs the calculation then updates some items in the view model with the results of the calculation. The View is then returned with the view model.

The convention is that, unless specified otherwise, the view returned will be named after the controller method in a folder named after the controller class. So the view is in the ~ViewsMain folder in a file called CalculatorResult.cshtml

@model HarrisBenedictCalculator.Models.HarrisBenedictViewModel

@{
    ViewBag.Title = "Harris Benedict Calculator Result";
}

<h2>Result</h2>

<p>For a <em>@(Model.IsMale ? "man" : "woman")</em> aged <em>@Model.Age</em> years old,
weighing <em>@Model.Weight.ToString("0.0")</em> kg, and <em>@Model.Height</em> cm tall
should be taking in the following calories per day:
</p>

<div class="result">
@foreach (var lifestyle in Model.LifestyleRates)
{
    <div class="result-line">
        <span class="result-label">@lifestyle.Key</span>@lifestyle.Value Calories
    </div>
}
</div>

<p>@Html.ActionLink("Calculate another?", "CalculatorInput", "Main")</p>

This view extracts the data from the view model and renders it to the browser.

So, the answer I get looks like this:

8 - Final Result

The Razor syntax is quite easy to follow for the most part. Anything starting with an @ sign indicates the start of some C# code. The rendering engine is clever enough to detect HTML code and revert back when needed.

At the bottom of the page the HTML helper method ActionLink generates the URL to take the user back round to the start of the process again in case they want to calculate another set of calorie intakes.

Summary

In this post I’ve demonstrated some very basic initial steps to get going with ASP.NET MVC 3.

You can also download the sample code in order to have a play yourself.

Software Development

Custom error pages and error handling in ASP.NET MVC 3

In ASP.NET MVC 3 a new bit of code appeared in the global.asax.cs file:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
}

The above method is called from the Application_Start() method.

Out of the box, what this does is set up a global filter for handling errors. You can still attribute controller methods or classes as before, but now, if you don’t have a specific HandleErrorAttribute attached to the controller method or class then the global one will take over and be processed.

However, you are not going to get custom errors just yet. If you have a bit of code that causes an exception to be thrown that is not caught then you will just end up with the Yellow Screen of Death as before. For example, this code:

public class HomeController : Controller
{
    // ...

    public ActionResult About()
    {
        throw new Exception("This is not good. Something bad happened.");
    }
}

Will produce this error

Error Handling - Without Custom Error

The missing part of the puzzle is to turn on Custom Errors. This happens in the web.config file. There are three basic options for the mode: “Off” which will show the YSOD to everyone, “RemoteOnly” which shows the YSOD on the local machine (the web server) and the custom error to everyone else, and “On” which shows the custom error to everyone including the local machine.

For development purposes I tend to leave it set to “RemoteOnly” so that I get the YSOD and I get to see what the error is, yet everyone else gets the custom error. However, for developing the actual custom errors themselves we’ll need to set the mode to “On” so we, as developers, get to see the error.

<system.web>
  <customErrors mode="On" defaultRedirect=”~/BadError.htm"/>
</system.web>

The defaultRedirect does not go to a controller action, it is set to a static HTML page that will be displayed if all else goes wrong. This is a final backstop to ensure that the user at least will see something nice event if the error page itself has some issues.

Normally, the error will show the ~/Views/Shared/Error.cshtml view. However, since the view can throw an exception itself there ought to be a backstop custom error page.

The HandleErrorAttribute defaults to using the view "Error" which will display shared view ~/Views/Shared/Error.cshtml.

You can change that by setting the view property on the HandleErrorAttrubute, like this:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute {View = "MyCustomError"});
}

I’ve set my error view to display the details of the exception for the purposes of this demo.

@model System.Web.Mvc.HandleErrorInfo

@{
    ViewBag.Title = "Error";
}

<h2>
    Sorry, an error occurred while processing your request.
</h2>
<p>Controller = @Model.ControllerName</p>
<p>Action = @Model.ActionName</p>
<p>Message = @Model.Exception.Message</p>
<p>StackTrace :</p>
<pre>@Model.Exception.StackTrace</pre>

NOTE: In normal production code you would never expose the details of the exception like this. It represents a considerable security risk and a potential attacker could use the information to gain valuable information about your system in order to construct an attack against it.

Now, if we re-run the same application and go to the About page (handled by the HomeController’s About action) then we will get our custom error page.

Performing additional actions on an exception

Overriding OnException in a Controller

If you want to perform additional actions, rather than just simply show a custom error page, then you can override the OnException method from the Controller class on your own controller derived class. If you want to do this for all controllers then  you may want to create a common base controller that all your controllers inherit from. For example:

public class CommonController : Controller
{
    protected override void OnException(ExceptionContext filterContext)
    {
        // Do additional things like logging here.
        base.OnException(filterContext);
    }
}

Then in each of your controllers, inherit from this common controller like this:

public class HomeController : CommonController
{ ...

That will ensure that all your controller have the same functionality.

Creating a FilterAttribute

You could alternatively create a FilterAttribute. This can provide benefits of providing global functionality if you add it to the global filter collection, or very fine grained functionality if you need it on a few sparse controller actions by adding it as an attribute on the controller action.

The filter may look like this:

public class LogExceptionFilterAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        // Log the exception here with your logging framework of choice.
    }
}

If you want to have the filter applied to all controller actions, you can set it up in the RegisterGlobalFilters method in the Global.asax.cs file like this:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new LogExceptionFilterAttribute());
    filters.Add(new HandleErrorAttribute());
}

Or, if you prefer to have finer grained control you can decorate individual controller classes or controller actions with it, like this:

[LogExceptionFilter()]
public ActionResult About()
{
    throw new Exception("This is not good. Something bad happened.");
}