Condividi tramite


Creazione di un vincolo di route personalizzato (C#)

di Stephen Walther

Stephen Walther illustra come creare un vincolo di route personalizzato. Implementiamo un semplice vincolo personalizzato che impedisce la corrispondenza di una route quando viene effettuata una richiesta del browser da un computer remoto.

L'obiettivo di questa esercitazione è illustrare come creare un vincolo di route personalizzato. Un vincolo di route personalizzato consente di impedire la corrispondenza di una route a meno che non corrisponda a una condizione personalizzata.

In questa esercitazione viene creato un vincolo di route Localhost. Il vincolo di route Localhost corrisponde solo alle richieste effettuate dal computer locale. Le richieste remote da Internet non corrispondono.

Si implementa un vincolo di route personalizzato implementando l'interfaccia IRouteConstraint. Si tratta di un'interfaccia estremamente semplice che descrive un singolo metodo:

bool Match(
    HttpContextBase httpContext,
    Route route,
    string parameterName,
    RouteValueDictionary values,
    RouteDirection routeDirection
)

Il metodo restituisce un valore booleano. Se si restituisce false, la route associata al vincolo non corrisponde alla richiesta del browser.

Il vincolo Localhost è contenuto nell'elenco 1.

Elenco 1 - LocalhostConstraint.cs

using System.Web;
using System.Web.Routing;
namespace MvcApplication1.Constraints
{
    public class LocalhostConstraint : IRouteConstraint
    {
        public bool Match
            (
                HttpContextBase httpContext, 
                Route route, 
                string parameterName, 
                RouteValueDictionary values, 
                RouteDirection routeDirection
            )
        {
            return httpContext.Request.IsLocal;
        }
    }
}

Il vincolo in List 1 sfrutta la proprietà IsLocal esposta dalla classe HttpRequest. Questa proprietà restituisce true quando l'indirizzo IP della richiesta è 127.0.0.1 o quando l'INDIRIZZO IP della richiesta corrisponde all'indirizzo IP del server.

Si usa un vincolo personalizzato all'interno di una route definita nel file Global.asax. Il file Global.asax in List 2 usa il vincolo Localhost per impedire a chiunque di richiedere una pagina di Amministrazione a meno che non facciano la richiesta dal server locale. Ad esempio, una richiesta per /Amministrazione/DeleteAll avrà esito negativo quando viene eseguita da un server remoto.

Elenco 2 - Global.asax

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using MvcApplication1.Constraints;
namespace MvcApplication1
{
    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                "Admin",
                "Admin/{action}",
                new {controller="Admin"},
                new {isLocal=new LocalhostConstraint()}
            );
            //routes.MapRoute(
            //    "Default",                                              // Route name
            //    "{controller}/{action}/{id}",                           // URL with parameters
            //    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            //);
        }
        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

Il vincolo Localhost viene usato nella definizione della route Amministrazione. Questa route non verrà corrispondente a una richiesta del browser remoto. Tenere presente, tuttavia, che altre route definite in Global.asax potrebbero corrispondere alla stessa richiesta. È importante comprendere che un vincolo impedisce a una determinata route di corrispondere a una richiesta e non a tutte le route definite nel file Global.asax.

Si noti che la route predefinita è stata commentata dal file Global.asax nell'elenco 2. Se si include la route predefinita, la route predefinita corrisponderebbe alle richieste per il controller di Amministrazione. In tal caso, gli utenti remoti potrebbero comunque richiamare azioni del controller di Amministrazione anche se le richieste non corrispondono alla route Amministrazione.