LSTANCZYK
3/21/2017 - 4:55 PM

Rails-like before filter

Rails-like before filter

public class BeforeAttribute : ActionFilterAttribute {
	public BeforeAttribute() {
		Methods = string.Empty;
		Except  = string.Empty;
		Only    = string.Empty;
	}

	public BeforeAttribute(params string[] methodNames) : this() {
		Methods = string.Join(" ", methodNames);
	}

	public virtual string Methods { get; set; }
	public virtual string Except  { get; set; }
	public virtual string Only    { get; set; }

	public virtual string[] MethodNames   { get { return Methods.Split(' '); } }
	public virtual string[] ExceptActions { get { return Except.Split(' ');  } }
	public virtual string[] OnlyActions   { get { return Only.Split(' ');    } }

	// This is only called if we check Except/Only actions and determine that we should get a result
	public ActionResult GetResult(ActionExecutingContext filterContext) {
		ActionResult result = null;

		var type = filterContext.Controller.GetType();
		foreach (var methodName in MethodNames) {
			var method = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
			result     = method.Invoke(filterContext.Controller, new object[]{}) as ActionResult;
			if (result != null)
				break;
		}

		return result;
	}

	public override void OnActionExecuting(ActionExecutingContext filterContext) {
		var actionName      = filterContext.ActionDescriptor.ActionName;
		ActionResult result = null;
		
		if (OnlyActions.Any())
			if (OnlyActions.Contains(actionName))
				result = GetResult(filterContext);
		else
			if (! ExceptActions.Contains(actionName))
				result = GetResult(filterContext);

		if (result == null)
			base.OnActionExecuting(filterContext);
		else
			filterContext.Result = result;
	}
}