Categories
ASP.NET ASP.NET MVC Microsoft

Create an authorized action link extension for ASP.NET MVC 3 (En anglais)

In this article I will explain how to create an action link extension that is authorizations aware, so that we can hide or disable an action link based on its authorizations.

When you create a website with multiple permissions, it would be nice to display action links depending on those permissions. For example if your website contains a menu, its better to display links according to the permissions. You don’t want your users to click on a link, and then display an unauthorized access message.

 

With ASP.NET MVC, we can easily create an action link that is authorizations aware. It will be above the standard action link.

Important: note that the code below is only for ASP.NET MVC 3. It’s because there has been some changes with filters since ASP.NET MVC 2.

 

 Creation

First we will create an extension that will allow us to know if an action is authorized:

using System.Web.Mvc;

namespace MvcApplication.AuthorizedActionLink.Extensions
{
	public static class ActionExtensions
	{
		public static bool ActionAuthorized(this HtmlHelper htmlHelper, string actionName, string controllerName)
		{
			ControllerBase controllerBase = string.IsNullOrEmpty(controllerName) ? htmlHelper.ViewContext.Controller : htmlHelper.GetControllerByName(controllerName);
			ControllerContext controllerContext = new ControllerContext(htmlHelper.ViewContext.RequestContext, controllerBase);
			ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(controllerContext.Controller.GetType());
			ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);

			if (actionDescriptor == null)
				return false;

			FilterInfo filters = new FilterInfo(FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor));

			AuthorizationContext authorizationContext = new AuthorizationContext(controllerContext, actionDescriptor);
			foreach (IAuthorizationFilter authorizationFilter in filters.AuthorizationFilters)
			{
				authorizationFilter.OnAuthorization(authorizationContext);
				if (authorizationContext.Result != null)
					return false;
			}
			return true;
		}
	}
}

As you can see we are retrieving action authorization filters. For each filter we test if the authorization context Result property is null. If this property is not null, it means that the user is not authorized to go on the action.

 

We also use an extension named GetControllerByName, in case the controller name is not specified:

using System;
using System.Globalization;
using System.Web.Mvc;

namespace MvcApplication.AuthorizedActionLink
{
	internal static class Helpers
	{
		public static ControllerBase GetControllerByName(this HtmlHelper htmlHelper, string controllerName)
		{
			IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
			IController controller = factory.CreateController(htmlHelper.ViewContext.RequestContext, controllerName);
			if (controller == null)
			{
				throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, "The IControllerFactory '{0}' did not return a controller for the name '{1}'.", factory.GetType(), controllerName));
			}
			return (ControllerBase)controller;
		}
	}
}

 

Now that we are able to know if an action is authorized, we can create a new link extension named ActionLinkAuthorized so it sticks to the standard ActionLink:

using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;
using MvcApplication.AuthorizedActionLink.Extensions;

namespace MvcApplication.AuthorizedActionLink.Html
{
	public static class LinkExtensions
	{
		public static MvcHtmlString ActionLinkAuthorized(this HtmlHelper htmlHelper, string linkText, string actionName, bool showActionLinkAsDisabled = false)
		{
			return htmlHelper.ActionLinkAuthorized(linkText, actionName, null, new RouteValueDictionary(), new RouteValueDictionary(), showActionLinkAsDisabled);
		}

		public static MvcHtmlString ActionLinkAuthorized(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, bool showActionLinkAsDisabled = false)
		{
			return htmlHelper.ActionLinkAuthorized(linkText, actionName, null, new RouteValueDictionary(routeValues), new RouteValueDictionary(), showActionLinkAsDisabled);
		}

		public static MvcHtmlString ActionLinkAuthorized(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, bool showActionLinkAsDisabled = false)
		{
			return htmlHelper.ActionLinkAuthorized(linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary(), showActionLinkAsDisabled);
		}

		public static MvcHtmlString ActionLinkAuthorized(this HtmlHelper htmlHelper, string linkText, string actionName, RouteValueDictionary routeValues, bool showActionLinkAsDisabled = false)
		{
			return htmlHelper.ActionLinkAuthorized(linkText, actionName, null, routeValues, new RouteValueDictionary(), showActionLinkAsDisabled);
		}

		public static MvcHtmlString ActionLinkAuthorized(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, object htmlAttributes, bool showActionLinkAsDisabled = false)
		{
			return htmlHelper.ActionLinkAuthorized(linkText, actionName, null, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlAttributes), showActionLinkAsDisabled);
		}

		public static MvcHtmlString ActionLinkAuthorized(this HtmlHelper htmlHelper, string linkText, string actionName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes, bool showActionLinkAsDisabled = false)
		{
			return htmlHelper.ActionLinkAuthorized(linkText, actionName, null, routeValues, htmlAttributes, showActionLinkAsDisabled);
		}

		public static MvcHtmlString ActionLinkAuthorized(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes, bool showActionLinkAsDisabled = false)
		{
			return htmlHelper.ActionLinkAuthorized(linkText, actionName, controllerName, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlAttributes), showActionLinkAsDisabled);
		}

		public static MvcHtmlString ActionLinkAuthorized(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes, bool showActionLinkAsDisabled)
		{
			if (htmlHelper.ActionAuthorized(actionName, controllerName))
			{
				return htmlHelper.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes);
			}
			else
			{
				if (showActionLinkAsDisabled)
				{
					TagBuilder tagBuilder = new TagBuilder("span");
					tagBuilder.InnerHtml = linkText;
					return MvcHtmlString.Create(tagBuilder.ToString());
				}
				else
				{
					return MvcHtmlString.Empty;
				}
			}
		}
	}
}

 

Example of use

Let’s say we want to authorize only users with role Administrator on the HomeController action named ThePrivilegeZone. ThePrivilegeZone action will be decorated with an authorize attribute. We add a link to this action in the site menu with the authorized action link extension specifying that we want to show the  action link as disabled if the user is not authorized:

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<%@ Import Namespace="MvcApplication.AuthorizedActionLink.Html" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
    <script src="<%: Url.Content("~/Scripts/jquery-1.4.4.min.js") %>" type="text/javascript"></script>
</head>

<body>
    <div class="page">

        <div id="header">
            <div id="title">
                <h1>My MVC Application</h1>
            </div>
              
            <div id="logindisplay">
                <% Html.RenderPartial("LogOnUserControl"); %>
            </div> 
            
            <div id="menucontainer">
            
                <ul id="menu">              
                    <li><%: Html.ActionLink("Home", "Index", "Home")%></li>
                    <li><%: Html.ActionLink("About", "About", "Home")%></li>
                    <li><%: Html.ActionLinkAuthorized("The Privilege Zone", "ThePrivilegeZone", "Home", true)%></li>
                </ul>
            
            </div>
        </div>

        <div id="main">
            <asp:ContentPlaceHolder ID="MainContent" runat="server" />

            <div id="footer">
            </div>
        </div>
    </div>
</body>
</html>

 

The result looks like below when the user is not authorized and the action link disabled:

It would be better to add some styling 🙂

 

To go further

To be honest I didn’t invent anything here. I have just take a deep look into the ASP.NET MVC 3 source code available on the Microsoft website in order to understand how authorizations works, and I have mixed it with the standard ActionLink. My code is based on three classes: ControllerActionInvoker, MvcHandler, LinkExtensions.

 

Summary

We have seen how to create and use an authorized action link.

You can download the example solution here:

Download full sources

(Note that the project uses ASP.NET MVC 3)

 

Please feel free to comment or contact me if you have any question about this article.

Categories
Microsoft SharePoint 2010

SharePoint Foundation or Server 2010: Error when you are trying to get an SPListItem value (En anglais)

You get a ‘System.ArgumentException: Value does not fall within the expected range » when you try to get the value of an SPListItem. Here is one solution to your problem!

This article will maybe help out some folks, because I didn’t find the answer elsewhere.

I wanted to retrieve an SPListItem value, and I got the following error:

System.ArgumentException: Value does not fall within the expected range.
at Microsoft.SharePoint.SPFieldMap.GetColumnNumber(String strFieldName, Boolean bThrow)
at Microsoft.SharePoint.SPListItemCollection.GetColumnNumber(String groupName, Boolean bThrowException)
at Microsoft.SharePoint.SPListItemCollection.GetRawValue(String fieldname, Int32 iIndex, Boolean bThrow)
at Microsoft.SharePoint.SPListItem.GetValue(SPField fld, Int32 columnNumber, Boolean bRaw, Boolean bThrowException)
at Microsoft.SharePoint.SPListItem.get_Item(Guid fieldId)

First, I didn’t understand why this error was thrown on a such basic operation in SharePoint development.

Then going step by step trying to find a solution, I noticed that on my current SPList I had several field of type « Lookup » and « Person or Group », eleven exactly.
 

I finally found the solution in the Web Application settings.

Go to the Central Administration > Manage web applications > General Settings > Resource Throttling.

Then take a look to the option named List View Lookup Threshold.

The description says: Specify the maximum number of Lookup, Person/Group, or workflow status fields that a database query can involve at one time.

This option is the solution to our problem!

By default the value is set to 8. Just modify it depending on your needs. For my part I set it to eleven, and the error didn’t show up again.

Just be carefull with this option, because it is used for performance reason. Don’t raise it too much, just modify it to suit your needs.

 

Please feel free to comment or contact me if you have any question about this article.

Categories
Bing Maps Microsoft

Utiliser les services REST Bing Maps avec jQuery pour construire une zone de saisie semi-automatique et trouver une localisation dynamiquement

Dans cet article nous allons découvrir comment construire une zone de saisie semi-automatique avec les services REST Bing Maps en utilisant uniquement HTML, JSON et jQuery.

Les services REST Bing Maps nous permettent d’effectuer des tâches telles que la création d’une carte avec des punaises, le géocodage d’une adresse, la récupération de métadonnées des images, ou la création d’un itinéraire.

Ici, nous allons apprendre à utiliser l’API Locations des services REST Bing Maps pour construire une zone de saisie semi-automatique avec jQuery. Pour utiliser les services REST Bing Maps, vous aurez besoin d’une clé Bing Maps. Il suffit d’aller sur le Bing Maps Account Center pour en obtenir une.

 

Création

Tout d’abord, nous allons créer une simple page HTML en ajoutant les références à jQuery et jQuery UI, une zone de saisie pour la localisation recherchée et une div dans laquelle les résultats seront affichés.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Use Bing Maps REST Services with jQuery to build an autocomplete box and find a location dynamically</title>
    <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.5.1.js" type="text/javascript"></script>
    <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/jquery-ui.js" type="text/javascript"></script>
    <link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" />
    <style type="text/css">
        #searchBox
        {
            width: 25em;
        }
    </style>
</head>
<body>
    <div>
        <div class="ui-widget">
            <label for="searchBox">
                Search:
            </label>
            <input id="searchBox" />
        </div>
        <div id="searchResult" class="ui-widget" style="margin-top: 1em;">
        </div>
    </div>
</body>
</html>

 

Pour appeler l’API Locations, nous utilisons l’adresse suivante : http://dev.virtualearth.net/REST/v1/Locations

Les paramètres qui suivent sont nécessaires pour obtenir une réponse du service :

  • query (or q) : la localisation recherchée.
  • key : est la clé Bing Maps à utiliser pour la requête (voir Bing Maps Account Center).

Les services REST Bing Maps ont également d’autres paramètres optionnels tels que :

  • userLocation (or ul) : position actuelle de l’utilisateur.
  • culture (or c) : la culture à utiliser pour la requête.
  • output (or o) : format de sortie de la réponse (JSON ou XML). JSON est utilisé par défaut.
  • jsonp : nom de la fonction callback JSON qui est appelée quand la réponse à la requête est reçue. L’objet JSON fourni dans la réponse est passé à la fonction callback.

 

Pour créer une zone de saisie semi-automatique, nous utilisons jQuery UI. La source des suggestions fournies à l’utilisateur viendra des services REST Bing Maps.

Le fonctionnement est le suivant : lorsque l’utilisateur tape une localisation, une requête Ajax est déclenchée pour appeler l’API Locations des services REST Bing Maps et une réponse JSON est reçue. La réponse est traitée pour être affichée sous forme de suggestions à l’utilisateur. Voici le code JavaScript pour obtenir ce comportement :

<script type="text/javascript">
    $(document).ready(function () {
        $("#searchBox").autocomplete({
            source: function (request, response) {
                $.ajax({
                    url: "http://dev.virtualearth.net/REST/v1/Locations",
                    dataType: "jsonp",
                    data: {
                        key: "<yourbingmapskey>",
                        q: request.term
                    },
                    jsonp: "jsonp",
                    success: function (data) {
                        var result = data.resourceSets[0];
                        if (result) {
                            if (result.estimatedTotal > 0) {
                                response($.map(result.resources, function (item) {
                                    return {
                                        data: item,
                                        label: item.name + ' (' + item.address.countryRegion + ')',
                                        value: item.name
                                    }
                                }));
                            }
                        }
                    }
                });
            },
            minLength: 1
        });
    });
</script>

 

Il faut prêter attention à plusieurs choses ici :

  • Nous indiquons à jQuery que la source de la zone de saisie semi-automatique est une requête Ajax envoyée à l’API Locations des services REST Bing Maps. Une fois la réponse à la requête reçue, la zone de saisie semi-automatique obtient des suggestions grâce au callback qui s’appelle response.
  • La requête Ajax a plusieurs paramètres :
    • url : celle de l’API Locations.
    • dataType : jsonp.
    • jsonp : s’appelle jsonp pour remplacer le nom de la fonction de callback dans la requête jsonp. Ainsi jQuery rajoute « ?jsonp=? » à la fin de l’URL pour préciser le callback. Ceci est requis par les services REST Bing Maps.
  • On obtient le terme recherché à partir du paramètre nommé request.term.
  • On vérifie que la réponses des services REST Bing Maps contient un « resource sets » et également qu’il y a des localisations qui correspondent au terme recherché (result.estimatedTotal > 0). Pour plus de détails sur la réponse des services REST Bing Maps : Common Response Description on MSDN.
  • Dans le callback response, on indique que le label de la suggestion sera le nom de la localisation plus le nom du pays, et que la valeur sera égale au nom de la localisation. On utilise également la propriété nommée data pour sauver les informations de localisations complètes afin de les réutiliser lorsque l’utilisateur aura sélectionné une localisation.

 

Par exemple, lorsqu’un utilisateur cherche « San Francisco », l’URL de requête Ajax suivante est construite et appelée :

http://dev.virtualearth.net/REST/v1/Locations?jsonp=<callbackname>&key=<yourbingmapskey>&q=San+francisco&_=1298745707161

 

La source finale de la page est la suivante :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Use Bing Maps REST Services with jQuery to build an autocomplete box and find a location dynamically</title>
    <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.5.1.js" type="text/javascript"></script>
    <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/jquery-ui.js" type="text/javascript"></script>
    <link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" />
    <style type="text/css">
        .ui-autocomplete-loading
        {
            background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat;
        }
        #searchBox
        {
            width: 25em;
        }
    </style>

    <script type="text/javascript">
        $(document).ready(function () {
            $("#searchBox").autocomplete({
                source: function (request, response) {
                    $.ajax({
                        url: "http://dev.virtualearth.net/REST/v1/Locations",
                        dataType: "jsonp",
                        data: {
                            key: "<yourbingmapskey>",
                            q: request.term
                        },
                        jsonp: "jsonp",
                        success: function (data) {
                            var result = data.resourceSets[0];
                            if (result) {
                                if (result.estimatedTotal > 0) {
                                    response($.map(result.resources, function (item) {
                                        return {
                                            data: item,
                                            label: item.name + ' (' + item.address.countryRegion + ')',
                                            value: item.name
                                        }
                                    }));
                                }
                            }
                        }
                    });
                },
                minLength: 1,
                change: function (event, ui) {
                    if (!ui.item)
                        $("#searchBox").val('');
                },
                select: function (event, ui) {
                    displaySelectedItem(ui.item.data);
                }
            });
        });

        function displaySelectedItem(item) {
            $("#searchResult").empty().append('Result: ' + item.name).append(' (Latitude: ' + item.point.coordinates[0] + ' Longitude: ' + item.point.coordinates[1] + ')');
        }
    </script>
</head>
<body>
    <div>
        <div class="ui-widget">
            <label for="searchBox">
                Search:
            </label>
            <input id="searchBox" />
        </div>
        <div id="searchResult" class="ui-widget" style="margin-top: 1em;">
        </div>
    </div>
</body>
</html>

 

Vidéo de démonstration (En anglais) 

Liens

Plusieurs liens qui vous aideront à comprendre et aller plus loin sur le sujet :

 

En résumé

Nous avons vu comment utiliser les services REST Bing Maps avec jQuery, jQuery UI pour construire une zone de saisie semi-automatique afin de trouver une localisation dynamiquement. Comme nous utilisons HTML, JSON et jQuery, cela peut être intégré avec la technologie que vous préférez.

Si vous souhaitez aller plus loin sur le sujet, regardez les liens ci-dessus pour comprendre ce que vous pouvez faire avec les services REST Bing Maps. Par exemple, nous pourrions afficher la localisation sélectionnée sur une carte avec le contrôle Bing Maps AJAX ou le contrôle Bing Maps Silverlight. Ce sera certainement le sujet d’un de mes prochains articles, en complément de celui-ci.

Vous pouvez télécharger les sources complète ici :

Télécharger les sources complètes

 

N’hésitez pas à commenter ou à me contacter si vous avez des questions à propos de cet article.

Categories
Microsoft Windows Phone 7

Première mise à jour de Windows Phone 7 disponible

Voici quelques photos pour vous montrer à quoi ressemble la notification de mise à jour sur le téléphone.

Je viens de recevoir la première notification de mise à jour sur mon Samsung Omnia 7. Voici quelques photos :

Je vais attendre avant de mettre à jour mon téléphone, suite au problème signalé par plusieurs personnes lors du processus de mise à jour avec le Samsung Omnia 7.

Categories
ASP.NET ASP.NET MVC Microsoft

Créer un AuthorizeAttribute personnalisé qui accèpte des paramètres de type enum

Dans cet article je vais vous expliquer comment créer simplement un AuthorizeAttribute qui accepte des paramètres de type enum afin d’éviter le codage en dur des rôles.

Avez-vous déjà essayé dans l’un de vos projets ASP.NET MVC d’utiliser un attribut [Authorize] pour par exemple assigner des rôles, en utilisant la valeur d’une Enum ?

Si c’est le cas, vous obtiendrez le message d’erreur suivant en anglais lors de la compilation :

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type

 

C’est parce que vous avez besoin d’utiliser des valeurs statiques et il est impossible d’utiliser une Enum pour définir les propriétés d’un Attribute. Cela signifie que vous ne pouvez pas définir la propriété Roles d’un [AuthorizeAttribute] avec une valeur d’Enum.

C’est frustrant, parce que personnellement je n’aime pas avoir à coder en dur les rôles dans une application. Cela rend l’application pas très lisible et plus compliquée à maintenir.

 

Heureusement, ASP.NET MVC nous permet de personnaliser l'[AuthorizeAttribute] facilement sans avoir à remplacer le processus de sécurité standard.

 

 Création

Pour nos besoins, nous allons créer l’Enum ci-dessous pour déclarer les rôles:

namespace MvcApplication.HowTo.Enums
{
    public enum Role
    {
        Administrator = 1,
        UserWithPrivileges = 2,
        User = 3,
    }
}

 

Maintenant, nous allons créer un [AuthorizeAttribute] personnalisé qui accepte des Enum en tant que paramètres dans le constructeur. Il héritera de System.Web.Mvc.AuthorizeAttribute :

using System;
using System.Linq;
using System.Web.Mvc;

namespace MvcApplication.HowTo.Attributes
{
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
    public class AuthorizeEnumAttribute : AuthorizeAttribute
    {
        public AuthorizeEnumAttribute(params object[] roles)
        {
            if (roles.Any(r => r.GetType().BaseType != typeof(Enum)))
                throw new ArgumentException("roles");

            this.Roles = string.Join(",", roles.Select(r => Enum.GetName(r.GetType(), r)));
        }
    }
}

Comme vous pouvez le voir, il faut prêter attention à plusieurs choses ici :

  • Le constructeur accepte des paramètres de type object, c’est la petite astuce. Si vous utilisez des paramètres de type Enum, vous obtiendrez le même message d’erreur que ci-dessus. Nous pouvons faire cela car une Enum est un object.
  • Pour veiller à ce que l’on passe des paramètres de type Enum, on vérifie le type de tous les rôles. Si un rôle n’est pas de type Enum, le constructeur lèvera une ArgumentException.
  • Ensuite nous définissons la propriété standard Roles avec le nom de nos rôles, à l’aide de la méthode string.join.

 

Exemple d’utilisation

Disons que nous voulons autoriser uniquement les utilisateurs ayant les rôles Administrator ou UserWithPrivileges sur l’action nommée ThePrivilegeZone du HomeController. L’action ThePrivilegeZone sera décorée de notre authorize attribute personnalisé comme ci-dessous :

using System.Web.Mvc;
using MvcApplication.HowTo.Attributes;
using MvcApplication.HowTo.Enums;

namespace MvcApplication.HowTo.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";

            return View();
        }

        public ActionResult About()
        {
            return View();
        }

        [AuthorizeEnum(Role.Administrator, Role.UserWithPrivileges)]
        public ActionResult ThePrivilegeZone()
        {
            return View();
        }
    }
}

Notre code est propre comme ça, n’est-ce pas ?

 

Pour aller plus loin

Si l’on regarde avec un outil comme Reflector, il est intéressant de comprendre comment l’action ThePrivilegeZone est décorée lors de la compilation. Voici une capture d’écran :

Nous comprenons qu’une fois compilées, les valeurs de l’Enum Role sont utilisés et non les noms. Ici 1 (Administrator) et 2 (UserWithPrivileges).

Notez que si vous utilisez une Enum pour vos rôles sans mettre de valeurs comme nous l’avons fait ici, les valeurs de l’Enum seront dans l’ordre 0, 1, 2, etc juqsu’au nombre de vos rôles moins 1.

 

En résumé

Nous avons vu comment créer et utiliser un AuthorizeAttribute personnalisé qui accepte des paramètres de type enum. Ici nous définissons seulement la propriété Roles, mais en fonction de vos besoins vous pouvez faire la même chose avec la propriété Users. Personnellement, j’utilise cet attribut personnalisé dans mon framework afin de le réutiliser dans tous mes projets ASP.NET MVC.

Vous pouvez télécharger la solution exemple ici :

Télécharger la solution Authorize Enum

(Notez que le projet utilise ASP.NET MVC 3)

 

N’hésitez pas à commenter ou à me contacter si vous avez des questions à propos de cet article.