Sunteți pe pagina 1din 13

JOSEMARTINEZ.INFO (HTTP://JOSEMARTINEZ.

INFO/)
BLOG SOBRE EL DESARROLLO DE SOFTWARE

INICIO (HTTP://JOSEMARTINEZ.INFO/)

Filtros en 0 (http://josemartinez.info/2015/05/11/filtros-en-asp-net-mvc/#respond)
Search … SEARCH
ASP.NET MVC
Posted on 11 mayo, 2015 (http://josemartinez.info/2015/05/11/filtros­en­asp­net­mvc/) by Jose Martínez
(http://josemartinez.info/author/dervin/) ENTRADAS RECIENTES
Filtros en ASP.NET MVC
En ASP.NET MVC los controladores (mediante sus métodos de acción) son los encargados de
(http://josemartinez.info/2015/05/11/filtros­en­asp­
ejercer como intermediarios entre el usuario y el sistema.  Cuando por ejemplo se pulsa un botón, se net­mvc/)
envía un formulario o se introduce una dirección url en el navegador, se genera una petición al
No uses using con clientes WCF
servidor y el framework mediante el módulo de rutas (UrlRoutingModule
(http://josemartinez.info/2015/01/23/no­uses­using­
(https://msdn.microsoft.com/es­es/library/system.web.routing.urlroutingmodule(v=vs.110).aspx)) con­clientes­wcf/)
analiza la url y la redirecciona al controlador y método de acción adecuado, que la gestiona y
Configuración y optimización de los motores de vista
devuelve el resultado. (View Engines) de ASP.NET MVC
(http://josemartinez.info/2015/01/14/configuracion­y­
optimizacion­de­los­motores­de­vista­view­engines­
de­mvc/)

CATEGORÍAS
ASP.NET MVC
(http://josemartinez.info/category/asp­net­mvc/)

Services (http://josemartinez.info/category/services/)

COMENTARIOS RECIENTES
Jose Martínez en No uses using con clientes WCF
(http://josemartinez.info/2015/01/23/no­uses­using­
con­clientes­wcf/#comment­47)

Ricardo Aranibar (http://www.credinformsa.com) en
No uses using con clientes WCF
(http://josemartinez.info/2015/01/23/no­uses­using­
con­clientes­wcf/#comment­46)

Jose Martínez en Configuración y optimización de
los motores de vista (View Engines) de ASP.NET
MVC
(http://josemartinez.info/2015/01/14/configuracion­y­
optimizacion­de­los­motores­de­vista­view­engines­
de­mvc/#comment­10)

Gerard en Configuración y optimización de los
motores de vista (View Engines) de ASP.NET MVC
(http://josemartinez.info/2015/01/14/configuracion­y­
optimizacion­de­los­motores­de­vista­view­engines­
de­mvc/#comment­9)

Configuración y Optimización de motores de vista |
(http://josemartinez.info/wordpress/wp­content/uploads/2015/05/Filters1.png) My Coding Corner
(http://joanvilarino.info/2015/01/15/configuracion­y­
Los filtros de ASP.NET MVC nos permiten mediante atributos agregar comportamientos previos y optimizacion­de­motores­de­vista/) en Configuración
posteriores a los métodos de acción de los controladores. Es decir, nos van a permitir ejecutar y optimización de los motores de vista (View
Engines) de ASP.NET MVC
código antes y/o después de que se ejecute una acción en el controlador. En la imagen anterior
(http://josemartinez.info/2015/01/14/configuracion­y­
podemos ver dentro de la Pipeline de ASP.NET MVC (en la imagen la he resumido) donde y cuando
optimizacion­de­los­motores­de­vista­view­engines­
se ejecuta cada filtro. Podemos crear tantos filtros como sean necesarios ya sea implementando las de­mvc/#comment­8)
interfaces en nuestras clases, heredando de los filtros ya existentes o de clases abstractas ya
creadas en el framework.
ARCHIVOS
Un filtro de asp.net es un atributo que normalmente implementa la clase abstracta FilterAttribute
(https://msdn.microsoft.com/es­es/library/system.web.mvc.filterattribute(v=vs.100).aspx). Estos mayo 2015 (http://josemartinez.info/2015/05/)

atributos pueden asociarse a un método de acción de un controlador,  al controlador directamente enero 2015 (http://josemartinez.info/2015/01/)
para que todas las acciones se asocien al filtro, o asociarlo a nivel global de la aplicación para que
todos los métodos de acción del proyecto se vean ajustados.

ASP.NET MVC nos proporciona los siguientes tipos de filtros:
SÍGUEME EN TWITTER

Filtro de autenticación Tweets por ​


@JoseMartinezTo

Este tipo de filtros son nuevos en ASP.NET MVC 5 y vienen a complementar a los filtros de Jose Martinez torres 
@JoseMartinezTo

autorización. Básicamente han sido creados con el objetivo de separar responsabilidades con los
Microsoft compra Xamarin, la universalidad está 
filtros de autorización. El filtro de autenticación se responsabilizará de validar si el usuario es válido e cada vez más cerca 
incluirlo en la petición, mientras que el filtro de autorización se encargará de comprobar si el usuario microsoftinsider.es/98876/microsof… vía 
@msftinsider
puede o no ejecutar una acción. Este tipo de filtro y más concretamente su método
OnAuthentication se ejecuta antes que cualquier otro filtro. Implementan la interfaz
IAuthenticationFilter  (https://msdn.microsoft.com/en­
us/library/system.web.mvc.filters.iauthenticationfilter(v=vs.118).aspx)

Fuente: Framework MVC
1 public interface IAuthenticationFilter
2 { Microsoft compra Xamarin, la universalidad es…
3     void OnAuthentication(AuthenticationContext filterContext); Una de las principales herramientas para los des…
4     void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext); microsoftinsider.es
5 }
Insertar Ver en Twitter

Podemos observar que se declaran dos métodos:

OnAuthentication: Es el método que se ejecutará antes de cualquier acción o filtro. Su objetivo es
el de autenticar la solicitud, como por ejemplo inicializando el principal o modificándolo.
META

OnAuthenticationChallenge: Este método nos puede servir por ejemplo para añadir tareas Registrarse (http://josemartinez.info/wordpress/wp­
login.php?action=register)
adicionales a la solicitud  o redirigir al usuario a otra página. La idea es que el método puede
utilizarse para contribuir al resultado, por ejemplo para convertir un HttpUnauthorizedResult Acceder (http://josemartinez.info/wordpress/wp­
login.php)
(https://msdn.microsoft.com/es­
es/library/system.web.mvc.httpunauthorizedresult.httpunauthorizedresult(v=vs.118).aspx) en una RSS (Really Simple Syndication) de las entradas
redirección a otra página de conexión según cierta lógica, añadir una sesión en un momento (http://josemartinez.info/feed/)

determinado, etc. RSS (Really Simple Syndication) de los comentarios
(http://josemartinez.info/comments/feed/)
Es  importante recalcar que este método no necesariamente tiene que ejecutarse justo después de
OnAuthentication sino que según el contexto de la solicitud puede hacerlo después de la acción y WordPress.org (https://es.wordpress.org/)

de otros tipos de filtros.. Si no hicieramos nada en el OnAuthentication seguidamente se ejecutaría
la acción o algún otro de sus filtros, pero si por ejemplo en el OnAuthentication modificamos el
result enviando un HttpUnauthorizedResult (https://msdn.microsoft.com/es­
es/library/system.web.mvc.httpunauthorizedresult.httpunauthorizedresult(v=vs.118).aspx) (indicando
una petición no autorizada), estaríamos impediedo la ejecución de cualquier acción y de sus
correspondientes filtros y en este caso después de OnAuthentication se ejecutaría
OnAuthenticacionChallenge.

Fuente: Framework MVC
1 public void OnAuthentication(AuthenticationContext filterContext)
2 {
3     if (!filterContext.Principal.Identity.IsAuthenticated)
4         filterContext.Result = new HttpUnauthorizedResult();
5 }

Filtro de autorización:
Como ya he adelantado, su objetivo es la toma decisiones de seguridad para restringir el acceso
a las acciones. AuthorizeAttribute  (https://msdn.microsoft.com/es­
es/library/system.web.mvc.authorizeattribute(v=vs.118).aspx)es un ejemplo de filtro de autorización.
Este tipo de filtros se ejecutan después del filtro de autenticación e implementan la interfaz
IAuthorizationFilter (https://msdn.microsoft.com/es­
es/library/system.web.mvc.iauthorizationfilter(v=vs.98).aspx) .

Fuente: Framework MVC
1 public interface IAuthorizationFilter
2 {
3     void OnAuthorization(AuthorizationContext filterContext);
4 }

La interfaz declara un método:

OnAuthorization: Se ejecutará cuando se necesite una autorización. Aquí podemos determinar que
permisos tiene el usuario y si se le permitirá por ejemplo acceder o ejecutar determinadas acciones.
Todos sabemos que un usuario puede tener permisos para modificar un registro mientras que otro
puede tener sólo permisos de lectura.

Filtro de acción:
Añade procesamiento adicional a la acción haciendo posible agregar comportamientos antes o
después de que la acción se ejecute. Se usan para multitud de escenarios, añadir logs, tareas de
localización e internalización de idioma como es el determinar  y establecer el idioma de la
aplicacion( culture/locale), modificar el comportamiento de la aplicación en función del agente de
usuario del navegador, añadir restricciones para “Anti­image­leeching” con el objetivo de negar
imágenes a peticiones que no son de tu web,  injectar acciones dinámicas al controlador y muchas
cosas más. Estos filtros implementan la interfaz IActionFilter (https://msdn.microsoft.com/es­
es/library/system.web.mvc.iactionfilter(v=vs.98).aspx).

Fuente: Framework MVC
1 public interface IActionFilter
2 {
3     void OnActionExecuted(ActionExecutedContext filterContext);
4     void OnActionExecuting(ActionExecutingContext filterContext);
5 }

Como vemos, la interfaz declara dos métodos:

OnActionExecuted: Se llama a este método después de ejecutar una acción.

OnActionExecuting: Se llama a este método antes de ejecutar una acción.

Filtro de resultados:
Añaden procesamiento adicional a los resultados de la acción (ActionResult), como por ejemplo
la modificación de la vista o resultados,registro de logs, modificar el modelo, redirigir a una página
de error si detectamos que el modelo no es valido, etc. La clase OutputCacheAttribute es un ejemplo
de filtro de resultado. Son parecidos a los filtros de acción pero en este caso la acción ya ha sido
ejecutada. Estos tipos de filtro implementan la interfaz IResultFilter (https://msdn.microsoft.com/es­
es/library/system.web.mvc.iresultfilter(v=vs.98).aspx).

Fuente: Framework MVC
1 public interface IResultFilter
2 {
3     void OnResultExecuted(ResultExecutedContext filterContext);
4     void OnResultExecuting(ResultExecutingContext filterContext);
5 }

Podemos ver que la interfaz declara dos métodos:

OnResultExecuted: Se ejecuta inmediatamente después de que el resultado (ActionResult
(https://msdn.microsoft.com/es­es/library/system.web.mvc.actionresult(v=vs.98).aspx)) ha sido
ejecutado.

OnResultExecuting: Se ejecuta justo antes de invocar a la instancia/objeto ActionResult
(https://msdn.microsoft.com/es­es/library/system.web.mvc.actionresult(v=vs.98).aspx).

Filtro de excepciones:
Se ejecutan cuando se inicia una excepción no controlada en el método de acción o en alguno de
sus filtros. Se suelen utilizar para registrar logs, tratar excepciones y/o mostrar páginas de error.
HandleErrorAttribute es un buen ejemplo de este tipo de filtros. Los filtros de excepción implementan
la interface IExceptionFilter (https://msdn.microsoft.com/es­
es/library/system.web.mvc.iexceptionfilter(v=vs.118).aspx)

Fuente: Framework MVC
1 public interface IExceptionFilter
2 {
3     void OnException(ExceptionContext filterContext);
4 }

La interfaz define un único método:

OnException: Es llamado cuando se produce una excepción.

La clase Controller de ASP.NET MVC


Voy ha hacer un parentisis puesto que aquí nos topamos con una de las características de ASP.NET
MVC y no es otra que el número de enfoques que se pueden tomar para hacer algo.

Todas las interfaces nombradas anteriormente son implementadas por el Controller, por lo que de
hecho nos bastaría con sobreescribir alguno de los métodos de estas interfaces en el propio
controlador para introducir lógica antes y después de las acciones, al producirse una excepción, etc..

Podemos sobreescribir uno de los métodos, por ejemplo podríamos sobreesribir en el controlador el
OnActionExecuting para hacer un log y registrar el nombre de la acción que se va a ejecutar. Pero
donde dejaríamos la separación de responsabilidades?. Es más, ese código ya no podríamos
reutilizarlo a no ser que crearamos un controlador base y luego hacer que heredaran de él los
demás controladores. El problema es que con este enfoque nos podríamos ver en la situación de
que alguien (o nosotros mismos) sobreescribirá también el método en otro controlador y se olvidara
de llamar al método base. Podriamos aceptar barco si realmente es algo muy característico del
controlador, esto ya es decisión de cada programador y la situación que se encuentre. Mi opinión
general es que siempre es mas recomendable usar un filtro por atributos que sobrescribir los
método en el controlador. Si lo incluimos en el controlador base vamos a tener la seguridad de que
será ejecutado.

Filtros definidos en ASP.NET MVC


En ASP.NET MVC podemos crear nuestros propios filtros o usar los ya desarrollados en el
framework. Algunos de estos filtros son los siguientes:

Authorize:
Al marcar una acción con este filtro estaremos indicando que el acceso a esa acción esta restringido
a los usuarios. Si lo añadimos al controlador todos los métodos de acción de ese controlador estarán
restringidos y si lo ponemos a nivel global todos los filtros de la aplicación quedarán restringidos. Por
defecto si sólo ponemos el filtro sin indicar nada más, los usuarios que no hagan login no tendrán
acceso, pero también podemos indicar cuales serán los  usuarios o roles que tendrán acceso a ese
método.

1 public class HomeController : Controller
2  {
3      public ActionResult Index()
4      {
5          ViewData["Message"] = "Bienvenido";
6  
7          return View();
8      }
9  
10      public ActionResult AllUsers()
11      {
12          return View();
13      }
14  
15      [Authorize]
16      public ActionResult AuthenticatedUsers()
17      {
18          return View();
19      }
20  
21      [Authorize(Roles = "Admin")]
22      public ActionResult AdministratorsOnly()
23      {
24          return View();
25      }
26  
27      [Authorize(Users = "Jose, Izan")]
28      public ActionResult SpecificUserOnly()
29      {
30          return View();
31      }
32  }

En el ejemplo anterior, cualquier usuario anónimo tendrá acceso a la acción AllUsers. Para la acción
AdministratorsOnly únicamente tendrán acceso aquellos usuarios con el rol “Admin”, mientras que
la acción SpecificUserOnly únicamente estará disponible para los usuarios Jose e Izan.

Un atributo muy útil para usar junto a Authorize es AllowAnonymous (https://msdn.microsoft.com/es­
es/library/system.web.http.allowanonymousattribute(v=vs.118).aspx). Si por ejemplo pusiéramos a
nivel global de la aplicación el filtro Authorize, todos nuestros métodos de acción estarián
restringidos. Si necesitamos que una acción en concreto sea accesible para los usuarios anónimos
la decoraremos con el atributo AllowAnonymous (https://msdn.microsoft.com/es­
es/library/system.web.http.allowanonymousattribute(v=vs.118).aspx).

Mas información en AuthorizeAttribute (https://msdn.microsoft.com/es­
es/library/system.web.mvc.authorizeattribute(v=vs.100).aspx)

ChildActionOnly:
Este filtro nos permitirá restringir el acceso a las acciones para que sólo puedan ser llamadas desde
nuestra aplicación y no desde fuera. Si decoramos un método de acción con este filtro y por ejemplo
 intentamos acceder a él  indicando la dirección en la barra url del navegador veremos que no
tenemos acceso a él. En la práctica al poner este filtro estamos restringiendo el uso de la acción a
llamadas dentro de nuestra aplicación mediante los métodos de extensión Action y RenderAction.
Además las acciones marcadas con este filtro sólo deberían devolver vistas parciales.
Más información en ChildActionOnlyAttribute (https://msdn.microsoft.com/es­
es/library/system.web.mvc.childactiononlyattribute(v=vs.118).aspx)

OutputCache:
Nos servirá para almacenar el resultado de un método de acción en la memoria caché. Pondré un
ejemplo de este filtro más adelante.

Más información en OutputCacheAttribute (https://msdn.microsoft.com/es­
es/library/system.web.mvc.outputcacheattribute(v=vs.100).aspx)

HandleError:
Se utiliza para controlar una excepción en un método de acción. Por defecto si se produce un error
en la aplicación, ASP.NET redirigirá a la vista Error situada en Views/shared de nuestro proyecto.
Podemos cambiar este coportamiento predeterminado de este filtro ajustando varias de
sus propiedades.

ExceptionType: Para indicar los tipos de excepción que controlará el filtro.

View: Nombre de vista que utilizará el filtro para mostrar el error.

Master: Especifica el nombre de la vista maestra que se va a utilizar, si es que vamos a utilizar
alguna vista maestra.

Order: Orden en el que se aplican los filtros. Vamos a hablar sobre esto más adelante en este
artículo.

Para habilitar el uso de los errores personalizados hay que añadir el elemento customErrors a
system.web del archivo web.config.

1 <system.web>;
2   <customErrors mode="On" defaultRedirect="Error" />
3 </system.web>;

Mas información en HandleErrorAttribute (https://msdn.microsoft.com/es­
es/library/system.web.mvc.handleerrorattribute(v=vs.118).aspx#enabling_custom_error_handling)

ValidateAntiForgeryToken:
Este filtro nos ayudará a defendernos contra la falsificación de entidades entre sitios. Podemos
añadir en nuestro formulario el helper AntiForgeryToken, que generará un token dentro de un
campo oculto, por otro lado decoramos nuestro método de acción para el post del formulario con el
filtro ValidateAntiForgeryToken. Cuando el usuario rellene el formulario y envie la petición (submit),
ASP.NET MVC comprobará que el token enviado es correcto. Esto lo hara comporando una cookie
que habrá creado con el token contra el campo de formulario.

Uso del helper AntiForgeryToken en la vista
1 @using (Html.BeginForm())
2 {
3     @Html.AntiForgeryToken()
4     ...
5 }

Decoramos la acción del post del formulario con el filtro
1 [ValidateAntiForgeryToken]
2 public ActionResult SubmitPost(ViewModel vm)
3 {
4     ...
5 }

Más información en ValidateAntiForgeryTokenAttribute (https://msdn.microsoft.com/es­
es/library/system.web.mvc.validateantiforgerytokenattribute(v=vs.118).aspx)
RequireHttps:
El uso de este filtro obligará a que la llamada a la acción se haga mediante el protocolo HTTPS.
(http://es.wikipedia.org/wiki/Hypertext_Transfer_Protocol_Secure)

Más información en RequireHttpsAttribute (https://msdn.microsoft.com/es­
es/library/system.web.mvc.requirehttpsattribute(v=vs.118).aspx)

Como usar los filtros:


Anteriormente hemos visto que un filtro es una clase que hereda de FilterAttribute
(https://msdn.microsoft.com/es­es/library/system.web.mvc.filterattribute(v=vs.100).aspx), que a su
vez hereda de System.Attribute (https://msdn.microsoft.com/es­
es/library/system.attribute(v=vs.100).aspx). Los filtros puedes utilizarse a nivel de acción, de
controlador o bien a nivel global. Por ejemplo, si quisiéramos utilizar un filtro en una acción, nos
bastaría con decorar el método con el atributo. En el siguiente ejemplo se usa un filtro ya existente,
como es OutputCache (https://msdn.microsoft.com/es­
es/library/system.web.mvc.outputcacheattribute(v=vs.118).aspx).

1 [OutputCache(Duration=20)]
2 public ActionResult Index()
3 {
4     ViewBag.Time = DateTime.Now.ToLongTimeString();
5     return View();
6 }

El código anterior estaría cacheando en memoria la respuesta de la acción cada 20 segundos. Si
mostramos la variable Time del ViewBag en la página, y la actualizamos antes de esos 20 segundos,
observariamos que los segundos no se han actualizado. Pasado ese tiempo vuelve a ejecutar la
acción y la cachea viendo actualizado el tiempo. Es un ejemplo un poco simple pero sirve para ver
como se utiliza un filtro en una acción en concreto. Un uso útil de OutputCache
(https://msdn.microsoft.com/es­es/library/system.web.mvc.outputcacheattribute(v=vs.118).aspx)
podría ser el de cachear la salida de una lista de datos fijos o que no se ven alterados
continuamente.. por ejemplo un listado de países o de categorías.

Otra manera de usar un filtro es decorando directamente el controlador con el atributo, de esta
manera todas las acciones verían cacheado su resultado.

1 [OutputCache(Duration = 20)]
2 public class HomeController : Controller
3 {
4     ...
5  
6 }

Por último y no menos importante, podemos usar los filtros de manera global en nuestro proyecto y
que se ejecuten siempre en cada llamada de acción a nuestro sistema. Para ello y en versiones de
MVC 4 o superiores lo correcto será editar el archivo FilterConfig.cs situado en la carpeta App_Start
de nuestro proyecto ASP.NET MVC y añadir el filtro a la colección en el método estático
RegisterGlobalFilters.

1 public class FilterConfig
2 {
3     public static void RegisterGlobalFilters(GlobalFilterCollection filters)
4     {
5         filters.Add(new HandleErrorAttribute());
6         filters.Add(new OutputCache(Duration = 20));
7         filters.Add(new AuthorizeAttribute());
8     }
9 }
En versiones de MVC 3 y anteriores no tendremos el archivo FilterConfig.cs, de hecho no
encontraremos en el proyecto ni la carpeta App_Start. En estos casos el lugar donde añadiremos los
filtros será en el método Application_Start() del archivo Global.asax

1 protected void Application_Start()
2 {
3     AreaRegistration.RegisterAllAreas();
4  
5     // Register global filter
6     GlobalFilters.Filters.Add(new OutputCache(Duration = 20));
7  
8     RegisterGlobalFilters(GlobalFilters.Filters);
9     RegisterRoutes(RouteTable.Routes);
10 }

Orden de ejecución de los filtros:


Los filtros siguen el siguiente orden de ejecución según su tipo.

1. Filtros de autenticación.

2. Filtros de autorización

3. Filtros de acción

4. Filtros de resultado.

5. Filtros de excepción

Este orden es inamovible, ahora bien, dentro de cada tipo podemos definir un orden. Todos los
filtros tienen una propiedad de tipo entero llamada Order (heredada de FilterAttribute)  que podemos
utilizar para establecer el orden de ejecución entre filtros de un mismo tipo. Si la propiedad se omite
tomará el valor de ­1. El tipo de ordenacion es ascendente, cuanto menor sea el número antes se
ejecutará. Por ejemplo, si definimos tres filtros de autorización en una acción del controlador.

1 public class HomeController : Controller
2 {
3     [AuthorizationFilterA(Order=3)]
4     [AuthorizationFilterB(Order=1)]
5     [AuthorizationFilterC(Order=2)]
6     public ActionResult Index()
7     {
8         return View();
9     }
10 }

El orden de ejecución, como ya podéis preveer será:

1. AuthorizationFilterB

2. AuthorizationFilterC

3. AuthorizationFilterA

Si en cambio tenemos varios tipos de filtros, la propiedad Order actuará entre los filtros de su mismo
tipo.

1 public class HomeController : Controller
2 {
3     [ActionFilterB(Order=3)]
4     [ActionFilterA(Order=1)]
5     [AuthorizationFilterA(Order=2)]
6     [AuthorizationFilterB]
7     public ActionResult Index()
8     {
9         return View();
10     }
11 }

El orden será el siguiente:

1. AuthorizationFilterB

2. AuthorizationFilterA

3. ActionFilterA
4. ActionFilterB

AuthorizationFilterB se ejecuta primero porque no hemos indicado ningún orden para él y por
tanto el valor para la propiedad Order se establece por defecto en ­1.

Hay otro tipo de orden prederterminado que mvc utiliza para los filtros, y es el del ámbito o
alcance del filtro. El ámbito o alcance del filtro es en la práctica donde esta declarado. Internamente
mvc utiliza la enumeración FilterScope

1 namespace System.Web.Mvc
2 {
3     public enum FilterScope
4     {
5         First = 0,
6         Global = 10,
7         Controller = 20,
8         Action = 30,
9         Last = 100
10     }
11 }

La lógica de ordenacion es la misma, se ejecutaran antes los filtros con el valor de enumeración mas
bajo. Si nos fijamos en la enumeración, podemos decir que los filtros en un ámbito global se
ejecutarán antes que los de ambito de controlador y estos a su vez se ejecutarán antes que los
filtros en ámbito de acción. Un ejemplo sencillo para verlo.

1 [ActionFilterA]
2 public class HomeController : Controller
3 {
4     [ActionFilterB]
5     public ActionResult Index()
6     {
7         return View();
8     }
9 }

… por otro lado definimos en ámbito global otro filtro de acción.

1 GlobalFilters.Filters.Add(new ActionFilterC());

El orden de ejecución quedará de esta manera:

1. ActionFilterC

2. ActionFilterA

3. ActionFilterB

Para aclarar y como resumen, el orden de los filtros se basa primero en el tipo de filtro al que
pertenece, luego por su propiedad Order y finalmente por su ámbito. Por tanto, la propiedad
Order no variará el orden entre tipos pero si tendrá prioridad sobre el ámbito.

Mismo ejemplo anterior pero añadiendo la propiedad order:

1 [ActionFilterA(Order=2)]
2 public class HomeController : Controller
3 {
4     [ActionFilterB(Order=1)]
5     public ActionResult Index()
6     {
7         return View();
8     }
9 }

… definimos en ámbito global otro filtro de acción.

1 GlobalFilters.Filters.Add(new ActionFilterC(){Order=3});

Orden de ejecución resultante:

1. ActionFilterA (Action)

2. ActionFilterB (Controller)

3. ActionFilterC (Global)
Si dos filtros del mismo tipo tienen un mismo valor de Order y ámbito, su orden de ejecución se
establecerá en indefinido,  y su orden real será el orden en el que se añadió a la lista de filtros. Por
otra parte la propiedad order no acepta valores inferiores a ­1, si lo hacemos nos lanzará una
excepción en tiempo de ejecución.

Hay otra particularidad en la ejecución del orden de los filtros. Como hemos ido viendo algunos
filtros tienen más de un método y algunos métodos se ejecutan en orden hacia adelante y otros en
orden inverso. Esto es más fácil explicarlo con un ejemplo.

1 [AuthorizationFilterB]
2 [ActionFilterB]
3 [ResultFilterB]
4 public class HomeController : Controller
5 {
6     [AuthorizationFilterC]
7     [ActionFilterC]
8     [ResultFilterC]
9     public ActionResult Index()
10     {
11         return View();
12     }
13 }

… por otro lado definimos en ámbito global otro filtro de acción.

1 GlobalFilters.Filters.Add(new AuthorizationFilterA());
2 GlobalFilters.Filters.Add(new ActionFilterA());
3 GlobalFilters.Filters.Add(new ResultFilterA());

Orden de ejecución:

  1. AuthorizationFilterA – OnAuthorization (Global) – orden Adelante
  2. AuthorizationFilterB – OnAuthorization(Controller)  – orden Adelante
  3. AuthorizationFilterC – OnAuthorization(Action) – orden Adelante
  4. ActionFilterA – OnActioExecuting (Global) – orden Adelante
  5. ActionFilterB – OnActioExecuting (Controller) – orden Adelante
  6. ActionFilterC – OnActioExecuting (Action) – orden Adelante

  7. Home Controller, Index Action

  8. ActionFilterC – OnActionExecuted (Action) – orden Inverso
  9. ActionFilterB – OnActionExecuted (Controller) – orden Inverso
10. ActionFilterA – OnActionExecuted (Global) – orden Inverso
11. ResultFilterA – OnResultExecuting (Global) – orden Adelante
12. ResultFilterB – OnResultExecuting (Controller) – orden Adelante
13. ResultFilterC – OnResultExecuting (Action) – orden Adelante
14. ResultFilterC – OnResultExecuting (Action) – orden Inverso
15. ResultFilterB – OnResultExecuting (Controller) – orden Inverso
16. ResultFilterA – OnResultExecuting (Global) – orden Inverso

Crear filtros personalizados:


Como he mencionado anteriormente o muy anteriormente visto el mamotreto en que se ha ido
convirtiendo el artículo, para crear un filtro nos basta o bien con implementar una de las interfaces
existentes o heredar de una clase ya creada. Sabemos las interfaces y clases que existen, las
hemos ido viendo a lo largo del artículo. Según el tipo de filtro que queramos crear usaremos una u
otra interfaz. Así mismo sabemos que para definir cualquier tipo de filtro tenemos la clase base
Abstracta FilterAttribute (https://msdn.microsoft.com/es­
es/library/system.web.mvc.filterattribute(v=vs.118).aspx). Con estos datos ya podemos crear nuestro
primer filtro. Vamos a crear un filtro de acción muy sencillo que escriba en la ventana de salida del
IDE de visual studio el paso por los diferentes métodos del filtro.

1 public class ActionFilter : FilterAttribute, IActionFilter
2 {
3     public void OnActionExecuted(ActionExecutedContext filterContext)
4     {
5         Debug.WriteLine("ActionFilter: OnActionExecuted");
6     }
7  
8     public void OnActionExecuting(ActionExecutingContext filterContext)
9     {
10         Debug.WriteLine("ActionFilter: OnActionExecuting");
11     }
12 }

Si queremos que además se registren los eventos de un filtro de resultado en el mismo filtro nos
bastaría con añadir e implementar la interfaz de los filtros de resultado.

1 public class ActionFilter : FilterAttribute, IActionFilter, IResultFilter
2 {
3     public void OnActionExecuted(ActionExecutedContext filterContext)
4     {
5         Debug.WriteLine("ActionFilter: OnActionExecuted");
6     }
7  
8     public void OnActionExecuting(ActionExecutingContext filterContext)
9     {
10         Debug.WriteLine("ActionFilter: OnActionExecuting");
11     }
12  
13     public void OnResultExecuted(ResultExecutedContext filterContext)
14     {
15         Debug.WriteLine("ActionFilter: OnResultExecuted");
16     }
17  
18     public void OnResultExecuting(ResultExecutingContext filterContext)
19     {
20         Debug.WriteLine("ActionFilter: OnResultExecuting");
21     }
22 }

Esta es una de las maneras de crear un filtro personalizado. Hay otras como por ejemplo heredar de
una clase ya existente. Por ejemplo existe la clase abstracta ActionFilterAttribute
(https://msdn.microsoft.com/es­es/library/system.web.mvc.actionfilterattribute(v=vs.100).aspx). Esta
clase implementa exactamente las mismas interfaces que hemos utilizado anteriormente. Este es su
código:

Fuente: Framework MVC
1 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited=true
2 public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter
3 {
4     protected ActionFilterAttribute()
5     {
6     }
7  
8     public virtual void OnActionExecuted(ActionExecutedContext filterContext)
9     {
10     }
11  
12     public virtual void OnActionExecuting(ActionExecutingContext filterContext)
13     {
14     }
15  
16     public virtual void OnResultExecuted(ResultExecutedContext filterContext)
17     {
18     }
19  
20     public virtual void OnResultExecuting(ResultExecutingContext filterContext)
21     {
22     }
23 }
Como podemos ver, la clase hereda de FilterAttribute (https://msdn.microsoft.com/es­
es/library/system.web.mvc.filterattribute(v=vs.100).aspx)que como ya sabeis es la clase de la que
heredan todos los filtros de asp.net mvc. Además implementa dos interfaces: IActionFilter
(https://msdn.microsoft.com/es­es/library/system.web.mvc.iactionfilter(v=vs.98).aspx)y IResultFilter
(https://msdn.microsoft.com/es­es/library/system.web.mvc.iresultfilter(v=vs.98).aspx). Sabiendo ya
esto.. nos basta con heredar de ella y sobreescribir los métodos para que se comporte exactamente
igual que nuestro anterior filtro.

1 public class ActionFilter : ActionFilterAttribute
2 {
3     public override void OnActionExecuted(ActionExecutedContext filterContext)
4     {
5         Debug.WriteLine("ActionFilter: OnActionExecuted");
6     }
7  
8     public override void OnActionExecuting(ActionExecutingContext filterContext)
9     {
10         Debug.WriteLine("ActionFilter: OnActionExecuting");
11     }
12  
13     public override void OnResultExecuted(ResultExecutedContext filterContext)
14     {
15         Debug.WriteLine("ActionFilter: OnResultExecuted");
16     }
17  
18     public override void OnResultExecuting(ResultExecutingContext filterContext)
19     {
20         Debug.WriteLine("ActionFilter: OnResultExecuting");
21     }
22 }

  ASP.NET MVC (http://josemartinez.info/category/asp­net­mvc/)   ASP.NET
(http://josemartinez.info/tag/asp­net/), Filtros (http://josemartinez.info/tag/filtros/), MVC
(http://josemartinez.info/tag/mvc/)

 NO USES USING CON CLIENTES WCF


(HTTP://JOSEMARTINEZ.INFO/2015/01/23/NO-
USES-USING-CON-CLIENTES-WCF/)

DEJA UN COMENTARIO

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

NOMBRE *

CORREO ELECTRÓNICO *

WEB

COMENTARIO
PUBLICAR COMENTARIO

© 2016 JoseMartinez.info. All rights reserved. Hiero (http://athemes.com/theme/hiero) by aThemes

S-ar putea să vă placă și