asp.net-mvc
Filtri d'azione
Ricerca…
Un filtro di azione di registrazione
public class LogActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Log("OnActionExecuting", filterContext.RouteData);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
Log("OnActionExecuted", filterContext.RouteData);
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
Log("OnResultExecuting", filterContext.RouteData);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
Log("OnResultExecuted", filterContext.RouteData);
}
private void Log(string methodName, RouteData routeData)
{
var controllerName = routeData.Values["controller"];
var actionName = routeData.Values["action"];
var message = String.Format("{0} controller:{1} action:{2}", methodName, controllerName, actionName);
Debug.WriteLine(message, "Action Filter Log");
}
}
Filtro azioni di controllo sessione: richiesta di pagina e ajax
Solitamente i processi di autenticazione e autorizzazione vengono eseguiti tramite cookie e token support integrati in .net MVC. Ma se decidi di farlo da solo con Session
puoi usare la logica sottostante per entrambe le richieste di pagina e le richieste di ajax.
public class SessionControl : ActionFilterAttribute
{
public override void OnActionExecuting ( ActionExecutingContext filterContext )
{
var session = filterContext.HttpContext.Session;
/// user is logged in (the "loggedIn" should be set in Login action upon a successful login request)
if ( session["loggedIn"] != null && (bool)session["loggedIn"] )
return;
/// if the request is ajax then we return a json object
if ( filterContext.HttpContext.Request.IsAjaxRequest() )
{
filterContext.Result = new JsonResult
{
Data = "UnauthorizedAccess",
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
/// otherwise we redirect the user to the login page
else
{
var redirectTarget = new RouteValueDictionary { { "Controller", "Login" }, { "Action", "Index" } };
filterContext.Result = new RedirectToRouteResult(redirectTarget);
}
}
public override void OnResultExecuting ( ResultExecutingContext filterContext )
{
base.OnResultExecuting(filterContext);
/// we set a field 'IsAjaxRequest' in ViewBag according to the actual request type
filterContext.Controller.ViewBag.IsAjaxRequest = filterContext.HttpContext.Request.IsAjaxRequest();
}
}
Posizioni di utilizzo del filtro delle azioni (globale, controller, azione)
Puoi posizionare i filtri di azione a tre livelli possibili:
- Globale
- controllore
- Azione
Posizionare un filtro a livello globale significa che verrà eseguito su richieste a qualsiasi percorso. L'inserimento di uno su un controller lo rende eseguibile su richieste di qualsiasi azione in quel controller. Mettendo uno su un'azione significa che corre con l'azione.
Se abbiamo questo semplice filtro azione:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class CustomActionFilterAttribute : FilterAttribute, IActionFilter
{
private readonly string _location;
public CustomActionFilterAttribute(string location)
{
_location = location;
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
Trace.TraceInformation("OnActionExecuting: " + _location);
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
Trace.TraceInformation("OnActionExecuted: " + _location);
}
}
Possiamo aggiungerlo a livello globale aggiungendolo alla raccolta di filtri globale. Con la tipica configurazione del progetto ASP.NET MVC, ciò avviene in App_Start / FilterConfig.cs.
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomActionFilterAttribute("Global"));
}
}
Possiamo anche aggiungerlo al controller e al livello di azione in questo modo in un controller:
[CustomActionFilter("HomeController")]
public class HomeController : Controller
{
[CustomActionFilter("Index")]
public ActionResult Index()
{
return View();
}
}
Se eseguiamo l'applicazione e guardiamo la finestra Output, vedremo i seguenti messaggi:
iisexpress.exe Information: 0 : OnActionExecuting: Global
iisexpress.exe Information: 0 : OnActionExecuting: HomeController
iisexpress.exe Information: 0 : OnActionExecuting: Index
iisexpress.exe Information: 0 : OnActionExecuted: Index
iisexpress.exe Information: 0 : OnActionExecuted: HomeController
iisexpress.exe Information: 0 : OnActionExecuted: Global
Come puoi vedere, quando arriva la richiesta, i filtri vengono eseguiti:
- Globale
- controllore
- Azione
Esempi eccellenti di filtri posizionati a livello globale includono:
- Filtri di autenticazione
- Filtri di autorizzazione
- Registrazione dei filtri
Attributo gestore di eccezioni
Questo attributo gestisce tutte le eccezioni non gestite nel codice, (questo è principalmente per le richieste Ajax - che riguardano JSON - ma può essere esteso)
public class ExceptionHandlerAttribute : HandleErrorAttribute
{
/// <summary>
/// Overriden method to handle exception
/// </summary>
/// <param name="filterContext"> </param>
public override void OnException(ExceptionContext filterContext)
{
// If exeption is handled - return ( don't do anything)
if (filterContext.ExceptionHandled)
return;
// Set the ExceptionHandled to true ( as you are handling it here)
filterContext.ExceptionHandled = true;
//TODO: You can Log exception to database or Log File
//Set your result structure
filterContext.Result = new JsonResult
{
Data = new { Success = false, Message = filterContext .Exception.Message, data = new {} },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
Supponiamo che tu debba sempre inviare una risposta JSON simile a questa:
{
Success: true, // False when Error
data: {},
Message:"Success" // Error Message when Error
}
Quindi, invece di gestire le eccezioni nelle azioni del controller, come questo:
public ActionResult PerformMyAction()
{
try
{
var myData = new { myValue = 1};
throw new Exception("Handled", new Exception("This is an Handled Exception"));
return Json(new {Success = true, data = myData, Message = ""});
}
catch(Exception ex)
{
return Json(new {Success = false, data = null, Message = ex.Message});
}
}
Puoi farlo:
[ExceptionHandler]
public ActionResult PerformMyAction()
{
var myData = new { myValue = 1};
throw new Exception("Unhandled", new Exception("This is an unhandled Exception"));
return Json(new {Success = true, data = myData, Message = ""});
}
O puoi aggiungere a livello di Controller
[ExceptionHandler]
public class MyTestController : Controller
{
public ActionResult PerformMyAction()
{
var myData = new { myValue = 1};
throw new Exception("Unhandled", new Exception("This is an unhandled Exception"));
return Json(new {Success = true, data = myData, Message = ""});
}
}