Last active
December 17, 2015 10:58
-
-
Save puryfury/5598613 to your computer and use it in GitHub Desktop.
Nancy Attrubute-Driven Module Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Dynamic; | |
| using System.Linq; | |
| using System.Linq.Expressions; | |
| using System.Reflection; | |
| using System.Web; | |
| using Nancy; | |
| namespace Nancy | |
| { | |
| /// <summary> | |
| /// Nancy Attribute Driver Module (Must inherit) | |
| /// </summary> | |
| public abstract class NancyAttributeModule : NancyModule | |
| { | |
| /// <summary> | |
| /// If true, Strict Method check and throws Exception. otherwise, ignore it if not valid. | |
| /// </summary> | |
| protected bool IsStrict = true; | |
| /// <summary> | |
| /// Class Base Route Path | |
| /// </summary> | |
| protected readonly string basePath; | |
| public NancyAttributeModule() | |
| : base() | |
| { | |
| this.basePath = string.Empty; | |
| Init(); | |
| } | |
| public NancyAttributeModule(string path) | |
| : base(path) | |
| { | |
| this.basePath = path; | |
| Init(); | |
| } | |
| private void Init() | |
| { | |
| Type type = this.GetType(), nct = typeof(NancyContext); | |
| Type tattr = typeof(NancyRequestAttribute), battr = typeof(NancyBeforeFilterAttribute), aattr = typeof(NancyAfterFilterAttribute); | |
| MethodInfo[] methods = type.GetMethods(); | |
| foreach (MethodInfo method in methods) | |
| { | |
| string strE = "'" + type.FullName + "." + method.Name + "' method {0}"; | |
| Exception arglenE = new TargetParameterCountException(string.Format(strE, "must have 1 argument.")), | |
| ncE = new InvalidCastException(string.Format(strE, "must have 1 argument as Nancy.NancyContext!")); | |
| try | |
| { | |
| if (method.IsDefined(tattr, false)) | |
| { | |
| ParameterInfo[] ps = method.GetParameters(); | |
| if (ps.Length != 1) throw arglenE; | |
| if (method.ReturnType == typeof(void)) throw new InvalidCastException(string.Format(strE, "must have return any type!")); | |
| foreach (NancyRequestAttribute attr in method.GetCustomAttributes(tattr, false)) | |
| { | |
| if (attr == null) continue; | |
| ParameterExpression pex = Expression.Parameter(typeof(object)); | |
| Func<dynamic, dynamic> body = Expression.Lambda<Func<dynamic, dynamic>>(Expression.Call(Expression.Constant(this), method, pex), pex).Compile(); | |
| switch (attr.Type) | |
| { | |
| case RequestType.Get: Get[attr.Path] = body; break; | |
| case RequestType.Post: Post[attr.Path] = body; break; | |
| case RequestType.Put: Put[attr.Path] = body; break; | |
| case RequestType.Delete: Delete[attr.Path] = body; break; | |
| case RequestType.Options: Options[attr.Path] = body; break; | |
| case RequestType.Patch: Patch[attr.Path] = body; break; | |
| } | |
| } | |
| } | |
| else if (method.IsDefined(battr, false)) | |
| { | |
| ParameterInfo[] ps = method.GetParameters(); | |
| if (ps.Length != 1) throw arglenE; | |
| if (!ps.All(param => param.ParameterType == nct)) throw ncE; | |
| if (method.ReturnType != typeof(Response)) throw new MethodAccessException(string.Format(strE, "must return Nancy.Response!")); | |
| ParameterExpression pex = Expression.Parameter(nct); | |
| BeforePipeline body = Expression.Lambda<Func<NancyContext, Response>>(Expression.Call(Expression.Constant(this), method, pex), pex).Compile(); | |
| Before += body; | |
| } | |
| else if (method.IsDefined(aattr, false)) | |
| { | |
| ParameterInfo[] ps = method.GetParameters(); | |
| if (ps.Length != 1) throw arglenE; | |
| if (!ps.All(param => param.ParameterType == nct)) throw ncE; | |
| if (method.ReturnType != typeof(void)) throw new MethodAccessException(string.Format(strE, "must return NOTHING(void)!")); | |
| ParameterExpression pex = Expression.Parameter(nct); | |
| AfterPipeline body = Expression.Lambda<Action<NancyContext>>(Expression.Call(Expression.Constant(this), method, pex), pex).Compile(); | |
| After += body; | |
| } | |
| } | |
| catch (Exception E) | |
| { | |
| if (IsStrict) throw new InvalidOperationException("Attribute-Driven Module Initialization failed.", E); | |
| } | |
| } | |
| //DriverModule Helper ViewBag | |
| After += cx => | |
| { | |
| ViewBag.ClassName = this.GetType().Name; | |
| ViewBag.BasePath = this.basePath; | |
| }; | |
| } | |
| } | |
| /// <summary> | |
| /// Nancy Request Attribute (Can't Inherit with this.) | |
| /// </summary> | |
| [AttributeUsage(AttributeTargets.Method,AllowMultiple=true,Inherited=false)] | |
| public sealed class NancyRequestAttribute : Attribute | |
| { | |
| RequestType type; | |
| string path; | |
| /// <summary> | |
| /// Defines Request for declared request type and route path. | |
| /// </summary> | |
| /// <param name="type"></param> | |
| /// <param name="path"></param> | |
| public NancyRequestAttribute(RequestType type, string path) | |
| { | |
| this.type = type; | |
| this.path = path; | |
| } | |
| /// <summary> | |
| /// Defines Request for GET type and route path. | |
| /// </summary> | |
| /// <param name="path"></param> | |
| public NancyRequestAttribute(string path) : this(RequestType.Get, path) { } | |
| public RequestType Type { get { return type; } } | |
| public string Path { get { return path; } } | |
| } | |
| /// <summary> | |
| /// Nancy Before Filter Attribute | |
| /// </summary> | |
| [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] | |
| public sealed class NancyBeforeFilterAttribute : Attribute { } | |
| /// <summary> | |
| /// Nancy After Filter Attribute | |
| /// </summary> | |
| [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] | |
| public sealed class NancyAfterFilterAttribute : Attribute { } | |
| /// <summary> | |
| /// Nancy Request Types for Request Attribute | |
| /// </summary> | |
| public enum RequestType | |
| { | |
| Get, | |
| Post, | |
| Put, | |
| Delete, | |
| Patch, | |
| Options | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Nancy; | |
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Web; | |
| using CustomerWanso.Secutiry; | |
| namespace CustomerWanso.Controller | |
| { | |
| public class MainModule : NancySecurityModule | |
| { | |
| [NancyRequest("/")] | |
| public dynamic GetMain(dynamic route) | |
| { | |
| return View["Main.cshtml"]; | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Web; | |
| using Nancy; | |
| using Nancy.Responses; | |
| using CustomerWanso.DataModel; | |
| namespace CustomerWanso.Secutiry | |
| { | |
| public class NancySecurityModule : NancyAttributeModule | |
| { | |
| public const string LOGINURL = "/Login"; | |
| public const string USERSESS = "USER"; | |
| public NancySecurityModule() : base() { } | |
| public NancySecurityModule(string path) : base(path) { } | |
| [NancyBeforeFilter] | |
| public Response LoginFilter(NancyContext context) | |
| { | |
| Response res = null; | |
| if (context.Request.Session[USERSESS] as UserDto == null) | |
| return new RedirectResponse(LOGINURL); | |
| return res; | |
| } | |
| [NancyAfterFilter] | |
| public void UserInfoFilter(NancyContext context) | |
| { | |
| UserDto user = Session[USERSESS] as UserDto; | |
| if (user != null) | |
| { | |
| ViewBag.UserId = user.UserId; | |
| ViewBag.UserName = user.UserName; | |
| ViewBag.Status = user.Status; | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment