ASP.NET MVC Authentication using AccountController

The AccountController class is a controller for user authentication which is included in a default MVC project created with Visual Studio. Prior to using this controller, you will need to modify it so that it no longer refers to the HomeController which you most likely will remove. To do this, replace each of these instances:

return RedirectToAction("Index", "Home");

so they are as below:

return RedirectToAction("Index", "Products");

This will cause the authentication controller to redirect a user to the products controller once an authentication action ends. The default ASP.NET MVC master page has links for a  user to log in/out and register. The MVC Authorize filter facilitates control over which users may access the controller methods. Below is an example of the Authorize filter being  applied to the Delete method in the products controller class:

[Authorize]
public ActionResult Delete(int id) {
NorthwindEntities dbObj = new NorthwindEntities();
var data = dbObj.Products.Where(e => e.ProductID == id).Select(e => e).Single();
return View(data);
}

If a user clicks a delete link to delete a record of a product, the MVC framework is then checked. If the user is currently logged in, the action will proceed.. If the user has not logged in they will then be requested to provide their username and password credentials or else to create a new account. This can be made even more restrictive by specifying user names as part of the filter. Below is an example of the Authorize filter applied so the Delete method is only available to Mike Smith:

[Authorize(Users="Mike Smith")]
public ActionResult Delete(int id) {

Now only Mike Smith can perform the delete actions, all other users will be asked for their credentials. The MVC Authorize filter can even be applied to the whole controller class. Below is an example of the Authorize filter being applied to the ProductsController class, so that only authenticated users can access controller actions:

[HandleError(Order=2)]
[Authorize]
public class ProductsController : Controller {

The Authorize filter has an Order property which works just as the HandleError Order property. If the  Authorize filter is applied for the whole controller level and for a specific action method, the controller-wide setting will always have precedence unless the Order property is used.

ASP.NET MVC Error Handling using the HandleError Filter

ASP.NET Errors can be effectively handled using the HandleError filter, which specifies how exceptions which are thrown in a controller method are to be dealt with (note that ASP.NET MVC supports method filters, which allow for annotating controller methods to change their behavior).
Prior to using the HandleError filter, you will need to enable custom error handling for your ASP.NET MVC app in the web.config file by adding the below line in the system.web section:

<customErrors mode="On" />

The below code snippet show the HandleError filter being applied to the controller class. Thus, any exception which is thrown by an action method in the controller will be handled using the custom error policy.

namespace MVCApplicationDemo.Controllers {
[HandleError]
public class ProductController : Controller {

When the HandleError filter is applied without arguments, any exception thrown by the methods covered by the filter will result in the Views/Shared/Error.aspx view being used which just shows the message “Sorry, an error occurred while processing your request.” To test
this process, attempt to view details of a product which does not yet exist, such as with a URL as below:

http://localhost:51823/Product/Details/999990

The error message can be more specific and you may wish to give the user more detailed info. To do this create a view in the Views/Shared folder named NoRecordErr.aspx with the below content:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<System.Web.Mvc.HandleErrorInfo>" %>
<asp:Content ID="errTitle" ContentPlaceHolderID="TitleContent" runat="server">
Error Occured
</asp:Content>
<asp:Content ID="errContent" ContentPlaceHolderID="MainContent" runat="server">
<h2>
Sorry, but that record does not yet exist.
</h2>
</asp:Content>

This is a modification of the default error view with a message to show the user that the product request does not yet exist in the database. Next, we can apply the HandleError filter to the Details controller method as in the below snippet:

[HandleError(View="NoRecordErr")]
public ActionResult Details(int id) {

The filter informs the MVC framework that it should use the NoRecordErr view for an exception that is thrown by the Details method. Now, you need to modify the backstop filter to be as show below:

 [HandleError(Order=2)]
public class ProductController : Controller {

An Order value of 2 ensures the controller-wide filter is to be applied only in the event that there is not a HandleError filter with a higher order available. If you do not set a value for Order, the default error view takes precedence.
Now if a user attempts to requests details for a product which does not exist they will be served the new error view. The default error view will be served if other controller methods throw exceptions.

However as it currently stands a user will be informed that they requested a non-existent record for any exception arising from the Details method. Thus you will need to be even more specific.
First, create an exception in the ProductController class which will be used when a record the user has requested is not available:

class NoRecordErr : Exception {
}

The next step is to modify the Details method so that it explicitly checks whether the LINQ query returned a record and if not record was returned throw a new exception.

[HandleError(View="NoRecordErr",
ExceptionType=typeof(NoRecordErr))]
public ActionResult Details(int id) {
NorthwindEntities db = new NorthwindEntities();
var data = db.Products.Where(e => e.ProductID == id).Select(e => e);
if (data.Count() == 0) {
throw new NoRecordErr();
} else {
Product record = data.Single();
return View(record);
}
}

In summery we changed the HandleError filter by including a value for the ExceptionType property, then specifying the type of the exception the filter should to apply to. Now when a NoRecordErr() exception is thrown, the NoRecordErr.aspx view will instead be used. Alternatively, the generic Error.aspx will be used for other exception types (since we applied the controller-wide backstop filter).

ASP.NET MVC 3 First Look

ASP.NET MVC 3 Preview 1 has just been released and is now available for download here. Microsoft is now using Preview as the name for its early releases which roughly corresponds with the old CTP release type.

The first thing to not is that MVC 3 is backwards compatible with MVC  2, and can be installed side-by-side with MVC 2 – so you can use the current distribution for testing without impacting your current MVC 2 projects.

MVC 3 View Enhancements

MVC 3 introduces two improvements to the MVC view engine:

  • Ability to select the view engine to use. MVC 3 allows you to select from any of your  installed view engines from Visual Studio by selecting Add > View (including the newly introduced ASP.NET “Razor” engine”):
    MVC 3
  • Support for the next ASP.NET “Razor” syntax. The newly previewed Razor syntax is a concise lightweight syntax.

MVC 3 Control Enhancements

  • Global Filters : ASP.NET MVC 3  allows you to specify that a filter which applies globally to all Controllers within an app by adding it to the GlobalFilters collection.  The RegisterGlobalFilters() method is now included in the default Global.asax class template and so provides a convenient place to do this since is will then be called by the Application_Start() method:
    void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
    filters.Add(new HandleLoggingAttribute());
    filters.Add(new HandleErrorAttribute());
    }
    void Application_Start()
    {
    RegisterGlobalFilters (GlobalFilters.Filters);
    }
  • Dynamic ViewModel Property : MVC 3 augments the ViewData API with a new “ViewModel” property on Controller which is of type “dynamic” – and therefore enables you to use the new dynamic language support in C# and VB pass ViewData items using a cleaner syntax than the current dictionary API.
    Public ActionResult Index()
    {
    ViewModel.Message = "Hello World";
    return View();
    }
  • New ActionResult Types : MVC 3 includes three new ActionResult types and helper methods:
    1. HttpNotFoundResult – indicates that a resource which was requested by the current URL was not found. HttpNotFoundResult will return a 404 HTTP status code to the calling client.
    2. PermanentRedirects – The HttpRedirectResult class contains a new Boolean “Permanent” property which is used to indicate that a permanent redirect should be done. Permanent redirects use a HTTP 301 status code.  The Controller class  includes three new methods for performing these permanent redirects: RedirectPermanent()RedirectToRoutePermanent(), andRedirectToActionPermanent(). All  of these methods will return an instance of the HttpRedirectResult object with the Permanent property set to true.
    3. HttpStatusCodeResult – used for setting an explicit response status code and its associated description.

MVC 3 AJAX and JavaScript Enhancements

MVC 3 ships with built-in JSON binding support which enables action methods to receive JSON-encoded data and then model-bind it to action method parameters.
For example a jQuery client-side JavaScript could define a “save” event handler which will be invoked when the save button is clicked on the client. The code in the event handler then constructs a client-side JavaScript “product” object with 3 fields with their values retrieved from HTML input elements. Finally, it uses jQuery’s .ajax() method to POST a JSON based request which contains the product to a /theStore/UpdateProduct URL on the server:

$('#save').click(function () {
var product = {
ProdName: $('#Name').val()
Price: $('#Price').val(),
}

$.ajax({
url: '/theStore/UpdateProduct',
type: "POST";
data: JSON.stringify(widget),
datatype: "json",
contentType: "application/json; charset=utf-8",
success: function () {
$('#message').html('Saved').fadeIn(),
},
error: function () {
$('#message').html('Error').fadeIn(),
}
});
return false;
});

MVC will allow you to implement the /theStore/UpdateProduct URL on the server by using an action method as below. The UpdateProduct() action method will accept a strongly-typed Product object for a parameter. MVC 3 can now automatically bind an incoming JSON post value to the .NET Product type on the server without having to write any custom binding.

[HttpPost]
public ActionResult UpdateProduct(Product product) {
// save logic here
return null
}

MVC 3 Model Validation Enhancements

MVC 3 builds on the MVC 2 model validation improvements by adding   support for several of the new validation features within the System.ComponentModel.DataAnnotations namespace in .NET 4.0:
Continues…

Implementing a Generic Data Access Layer in ADO.NET Part 3

In this the final article of this series, I will discuss the other classes in this framework and how we can use this framework to perform various CRUD operations in our applications.

Let us start from where we left off in the previous part of this series. Note that most of the methods of the DatabaseHelper class have been marked as “internal” to prevent them from being called outside of the “ApplicationFramework.DataAccessLayer” namespace.

Now we will come to the DBManager class; the wrapper class that encapsulates the calls to another class called DBHelper that actually performs the CRUD operations on the underlying database. The DBManager class extends the DBManagerBase abstract class. The DBManagerBase class contains the definition for the Open () and the Close () methods and some other public properties that are generic and can be used by any class that acts as a wrapper. We will have a look at the DBManagerBase class first.

The following code listing shows the DBManagerBase class.

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Configuration;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Data.Odbc;
using System.IO;

namespace ApplicationFramework.DataAccessLayer

{
public abstract class DBManagerBase

{

protected DatabaseHelper databaseHelper = null;
protected DbDataReader dbDataReader = null;
protected DataSet dataSet = null;
protected ProviderType providerType;
protected String connectionString = String.Empty;
protected bool isOpen = false;

public bool IsOpen

{

get
{
return isOpen;

}

set
{

isOpen = value;

}

}

 public string ConnectionString
{
get

{
return connectionString;
}

set

{
connectionString = value;
}

}

public DbConnection Connection
{
get
{

return databaseHelper.Connection;
}
}

public DbCommand Command

{
get
{

return databaseHelper.Command;
}

}

public ProviderType DBProvider
{
set
{
providerType = value;
}

get
{
return providerType;
}

}

public DataSet DBSet
{
get
{
return dataSet;
}

}

public DbDataReader DBReader
{
get
{
return dbDataReader;
}

}

protected void Open(string connectionString)

{
databaseHelper = new DatabaseHelper(connectionString, DBProvider);
}

protected void Close()
{
if (dbDataReader != null)
if (!dbDataReader.IsClosed)
dbDataReader.Close();
databaseHelper.Dispose();
}

public void BeginTransaction()
{
databaseHelper.BeginTransaction();
}

public void CommitTransaction()
{
databaseHelper.CommitTransaction();
}

 public void RollbackTransaction()
{
databaseHelper.RollbackTransaction();
}
}
}

Note that the DBManagerBase class contains the most common methods that are required. You can Open or Close a connection, Begin, Commit or Rollback transactions, etc. These methods would remain the same and are mandatory in this context even if you decide to have another version of the DBManager class with some more methods implemented it.
Continues…

ASP.NET MVC Routing – StopRoutingHandler and IgnoreRoute

There are two methods to exclude a URL from being handled by Routing – StopRoutingHandler and IgnoreRoute.

StopRoutingHandler

The below listing shows two routes created manually, the first of which has a StopRoutingHandler which blocks Routing for handling the matching URL:

public static void RegisterRoutes(RouteCollection routes)
{
routes.Add(new Route
(
"{appresource}.axd/{*urlInfo}", new StopRoutingHandler() ));

routes.Add(new Route
(
"articles/{cat}/{id}", new SomeRouteHandler()  ));
}

Therefore a URL such as resource1.axd will be matched to the first route and since that route returns a StopRoutingHandler  Routing system will pass this request on for normal ASP.NET processing.

IgnoreRoute

A simpler way to circumvent Routing is to use IgnoreRoute .

This is declared in a similar manner to the familiar MapRoute method and is normally used alongside it as shown below:

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute(“{appresource}.axd/{*urlInfo}“);
routes.MapRoute("norm", “articles/{cat}/{id}“, new MvcRouteHandler());
}

This is a lot tidier than the method using StopRoutingHandler and functions exactly the same.

ASP.NET MVC Routing – WildCard Parameters

A wildcard or catch-all parameter in MVC Routing allows for a route to match a URL with an arbitrary number of parameters. This feature is especially useful when building CMSs, blogs, wikis and other content driven applications.

Typically, URLs for such content driven apps should be as descriptive as possible, for example reviews/hotels/germany/berlin/fourseasons. But what if the CMS also handles airline reviews, and want to use URLs like reviews/airlines/northwest . In this circumstance reviews would be the controller and airlines or hotels the action, but the id is either germany/berlin/fourseasons or northwest. Normally the parameters are inferred from the “/” character, but with wildcard parameters a chunk of a URL with multiple / characters can be read as a single parameter. In this case the below route definition could be used:

routes.MapRoute("reviews", "{controller}/{action}/{*id}");

The WildCard * character allows everything beyond the action parameter to be placed in the id parameter.

ASP.NET MVC Routing – Constraints

MVC Routing Constraints allow for the application of a regular expression to a URL segment to determine if the route will match the request.

Previously in the introductory MVC Routing Tutorial we looked at defining Routes based on the number of segments in a URL. So the Route definition:

routes.MapRoute(“simple”, “{controller}/{action}/{id}“);

would match the URL /articles/category/12 . But suppose the content management system we are building also had a blog and we wanted to use URLs such as /2010/04/03. Such a URL would map to the simple Route we defined above and so in our example it would be processed as if it were referring to an article category.

Therefore we can see that just mapping URL segments to Route definitions is extremely limiting. Constraints allow for regex to be used to read the contents of the URL parameters to determine which Route definition to use. For example:

routes.MapRoute(“blogpost”, “{year}/{month}/{day}“
, new {controller=”blogpost”, action=”index”}
, new {year=@“\d{4}“, month=@“\d{2}“, day=@“\d{2}“});

routes.MapRoute(“simple”, “{controller}/{action}/{id}“);

Here there are two route definitions both of which have three parameters. Note the highlighted part of the blogpost route definition which is the definition of the constraint. The constraint in this case matches a URL of  4 digit number/2 digit number/2 digit number format. If this test is met the blogpost route definition will be applied, for all other 3 segment URLs the simple route definition will be applied.

Note the order of the definitions. ASP.NET MVC Routing attempts to match route definitions in sequence and once a match is made it is processed. Therefore, routes which contain constraints should always be placed before the simple non-constrained route definitions.

ASP.NET MVC Routing – Multiple Parameters

In MVC Routing, multiple parameters can be used in a URL segment. For example the route definition:

routes.MapRoute(“multiple”, “{controller}/{action}/{author}-{tag}");

contains multiple parameters (ie author and id) in the final segment. This will match the URL blog/technology/johnspencer-aspnet . Any literal string can separate the multiple parameters, so the route definitions {author}.{tag} , {author}on{tag}, author-{author}on{tag} are all be valid. The parameters must be separated by a literal string, so the definition {author}{tag} would not be valid.

When working with multiple parameters it is important to understand the concept of greedy matching. Under this concept the first parameter will take the maximum amount of the url fragment that is possible. For example, how would the URL fragment /john.francis.spencer.sqlserver/ be mapped the the route definition {author}.{tag} since the are three “.” characters and only one as a literal in the route definition? Under greedy matching, the first parameter (author) will take john.francis.spencer but leave sqlserver for the tag parameter since the tag parameter must take at least some text beyond a “.” character.  

ASP.NET MVC Routing – Default Values

Default values in ASP.NET MVC Routing allow for much more flexible URL pattern matching. In our previous   MVC Routing Tutorial we introduced Routing and how it matches a URL to a predefined Route and then extracts the parameters for processing. In our original simple examples, a URL segment had to be provided for each parameter in a URL Route.

So, to recap, if we defined a URL Route for handling incoming URLs for a content  management system  which needs to display the articles for a given category then the route may look as below:

routes.MapRoute(“simple”, “{controller}/{action}/{id}“);

and the URL of /articles/category/15 would result in the below controller (with 15 being passed in as the id parameter).

public class ArticlesController : Controller
{
public ActionResult Category(int id)
{
//Perform Operations....
}
}

This url would therefore  output the articles for Category ID 15. But what if we wanted to use the URL /articles/category/ to display all the articles irrespective of category. For this we would need to use default values in Routing.

The provision of a default value in the Route definition allows ASP.NET MVC Routing to provide a preset value when none is provided in the URL (in a  similar fashion to default values for parameters in function definitions).

The default value needs to be in the Route definition:

routes.MapRoute(“simple”, “{controller}/{action}/{id}“, new {id = 0});

Now, the URL /articles/category/ will be interpretted as /articles/category/0 and so in this example the 0 value for id can be used to display all articles regardless of category.

Multiple Default Values

Multiple default values can be used for different parameters as shown below:

routes.MapRoute(“simple” , “{controller}/{action}/{id}“,
new {id = 0, action=”home”});

In this example the URL /articles/category/ would behave as shown previously but the URL /articles/ would behave as /articles/home/ ( and so in the example of a content management system the URL /articles/category/ would be the articles home page).

One rule to bear in mind when using default values is the if a default is defined for a parameter then all subsequent parameters must have a default value as well. For example :

routes.MapRoute(“simple” , “{controller}/{action}/{id}“,
new { action=”home”});

is not valid and a default for the id parameter needs to be assigned.

Another caveat in using default values is that defaults cannot be used when literal values are used in parameters. For example the Route,

routes.MapRoute(“simple” , “{controller}/{action}-{id}”);

uses the literal string “  - ” to separate {controller} and {action} which would match URLs such as /articles/category-12/ . In this case a default cannot be used for action or id .