Close this search box.

ASP.NET MVC Controller And Action Role Authentication

Today, I was playing around with ASP.NET MVC Framework when I came to an interesting situation. I was displaying Categories from the Northwind database as ActionLinks. When clicked on the link it will popup a confirmation box asking whether you want to delete the item or not. Here is the code to display the link and the confirmation box:.

void Can_Find_GenericMethodInvocations_With_Type_Parameters()<
    foreach (var category in ViewData){
        % >

        <%= Html.ActionLink<CategoryController>(
                c = > c.Delete(, category.CategoryName,
                new {onclick = "return confirmDelete(" + + ")"}) %>
        <br /> < % } %>

    function confirmDelete(id) {
  return confirm("Are you sure you want to delete?");

You don't need to define a separate function for confirmDelete but anyways!

The HTML code generated for this particular page (The Category List Page) is shown below:

<a href="/Category/Delete/1" onclick="return confirmDelete(1)" >Beverages Edite</a>
        <br />
        <a href="/Category/Delete/2" onclick="return confirmDelete(2)" >Condiments</a>

        <br />
        <a href="/Category/Delete/3" onclick="return confirmDelete(3)" >Confections</a>
        <br />
        <a href="/Category/Delete/4" onclick="return confirmDelete(4)" >Dairy Products</a>
        <br />
        <a href="/Category/Delete/5" onclick="return confirmDelete(5)" >Grains/Cereals</a>
        <br />

The above generated HTML code shows that Category/Delete/1 will delete the item with the id = 1. This means if I browse to the http://localhost:[portnumber]/Category/Delete/1 then the Item with the id = 1 will be deleted. But this opens a security hole since now anyone can type the URL with the id and delete the items. One way to solve this problem is by using the attribute based security as shown on this post. But then you will have to decorate your actions with the security attribute which is not a good idea.

Another way is to override the OnPreAction attribute which is fired before the action is fired. I created a BaseController and inherited all my controllers from the BaseController. This way the OnPreAction is fired for each controller.

public class BaseController : Controller

  BaseController() {}

  override bool OnPreAction(string actionName,
                            System.Reflection.MethodInfo methodInfo) {
    string controllerName = methodInfo.DeclaringType.Name;

    if (!IsAuthenticated(controllerName, actionName))
      throw new SecurityException("not authenticated");

    return base.OnPreAction(actionName, methodInfo);

  bool IsAuthenticated(string controllerName, string actionName) {
    System.Web.HttpContext context = System.Web.HttpContext.Current;

    XDocument xDoc = null;

    if (context.Cache["ControllerActionsSecurity"] == null) {
      xDoc = XDocument.Load(
      context.Cache.Insert("ControllerActionsSecurity", xDoc);

    xDoc = (XDocument)context.Cache["ControllerActionsSecurity"];
    IEnumerable<XElement> elements =

    var role =
        (from e in elements where((string)e.Attribute("controllerName")) ==
             controllerName &&
         ((string)e.Attribute("actionName")) ==
             actionName select new {RoleName = e.Attribute("Roles").Value})

    if (role == null) return true;

    if (!User.IsInRole(role.RoleName)) return false;

    return true;

I have created a ControllerActionsSecurity.XML file which stores the controllers, actions and roles allowed to fire the action.

  <add controllerName="CategoryController" actionName="Delete" Roles="Admin" />

Now, when you request for the /Category/Delete/1 your request will be denied if you are not of the Admin role. This way you will protect the controllers from firing restricted actions.      

Print | posted @ Sunday, February 24, 2008 4:06 PM

This article is part of the GWB Archives. Original Author: AzamSharp

Related Posts