NancyFx 是什么?
Nancy 是一个轻量级的独立的框架, 下面是官网的一些介绍:
Nancy 是一个轻量级用于构建基于 HTTP 的 web 服务, 基于 .NET 和 Mono 平台, 框架的目标是保持尽可能多的方式, 并提供一个 super-duper-happy-path 所有交互.
Nancy 设计用于处理 DELETE, GET, HEAD, OPTIONS, POST, PUT 和 PATCH 等请求方法, 并提供简单优雅的 DSL 以返回响应.
Nancy 和 ASP.NET MVC 原理相似, 但有自己的一套路由机制, 在使用上更加易用, 可以用 Nancy 快速开发一些网站.
Nancy 并不依赖任何现有的框架, 所以他可以运行在任何平台上面.
其 NancyFx 官方地址是: http://nancyfx.org/,Nancy 这个单词我们中国人的标准叫法 叫做 "南希".
我们为何要使用它呢?
没有配置
为了让 Nancy 启动并运行, 不需要配置, 没有令人讨厌的 xml 文件可以修改, 没有. 由于它是主机不可知的, 因此您不必修改 Web.config 中的任何内容以使其通过 IIS 运行.
随处运行
Nancy 是主机不可知的, 这意味着您可以在 IIS,WCF, 嵌入在 EXE 中, 作为 Windows 服务或在自托管应用程序中运行它. 到处都是!
在 Mono 上
Nancy 不把自己绑定在 Windows 上, 它在 OS X 和 Mono 下的 Linux 上工作得一样好, 这让您的团队可以在多个平台上工作.
如何在. NET 上使用 NancyFx
创建一个. Net Core App, 我们需要在项目中安装 NancyFx, 通过 nuget 安装, 也可以通过命令行, NancyFx 的依赖项可能有 OAuth 的邀请, 大部分 OAuth2.11 就 ok 了.
NancyFx.NET 之 HelloWorld
引用完成之后, 我们需要修改 Startup.cs 了, 这里我们在 Configure 中进行注册, 其目的是添加到 MVC 管道中.
- public void Configure(IApplicationBuilder App, IHostingEnvironment env)
- {
- if (env.IsDevelopment())
- {
- App.UseDeveloperExceptionPage();
- }
- App.UseOwin(x => x.UseNancy());
- }
接下来我们创建一个模块(类),HelloModule 继承自 NancyModule
- public class HelloModule : NancyModule
- {
- public HelloModule() { Get("/", p => "hello world"); }
- }
代码说明 & 结果:
这里的 Get 方法有两个参数, 第一个参数就是和. NET Core MVC Route 差不多, 那么第二个就是 action, 就是具体的定义, 我们启动项目, 发现网站正确的显示出了 Hello World!
NancyFx.NET 模块
模块你可以在任何地方上声明, 只要它运行在你的应用程序域即可, Nancy 会自动捕捉作为 NancyModule 类型后代的所有类型(因为你继承了南希模块).
我们把代码改一下, 通过 base 去构造模块其中写的是个你想要的路径:
- public class HelloModule : NancyModule
- {
- public HelloModule() : base("hello") { Get("/", p => "hello world"); }
- }
启动项目, 我们发现, 404 找不到了, 我们的路由应该是 port/hello/ 才对.
NancyFx.NET 路由
路由概念分类
这些我们逐一说一说.
纯文字路由片段(Literal Segment)
含变量的片段(Capture Segment)
含可空变量的片段(Capture Segment - Optional)
正则片段(RegEx Segment)
贪婪片段(Greedy Segment)
警告
注意: 如果你是在 ASP.NET Core MVC 中使用, 必须是 2.0 预览, 如不是 Core 中, 则是 1.4.5 以下, 下面是两个大版本路由语法比较:
- Get["/nancy/products"] = x => "hello world";
- Get("/", p => "hello world");
纯文字路由片段(Literal Segment)
纯文本路由片段我们已经知道了其实, 开头的 hello,world 即使如此.
含变量的片段(Capture Segment)
- public HelloModule()
- {
- Get("StudentList/{id?}",res=>res.id == null ? "咋不输入呢" : res.id);
- }
这实际上的第二个参数就是一个 Func 委托, 我们可以通过 url 去获取可变参数的值.
含可空变量的片段(Capture Segment - Optional)
- public HelloModule()
- {
- Get("StudentList/{id?}",res=>res.id == null ? "咋不输入呢" : res.id);
- }
可空类型就是在参数后面加个? 就可以了.
正则片段(RegEx Segment)
Nancy 的路由是支持正则的
- public HelloModule()
- {
- Get(@"/products/(?<productId>^[1]+[3,5]+\d{9})", p => "Your product id is" + p.productId);
- }
贪婪片段(Greedy Segment)
Nancy 中可以在变量尾部追加一个星号, 表示当 url 匹配结束后的字符串
- public class ProductModule : NancyModule
- {
- public ProductModule()
- {
- Get("/products/{productName*}", p => p.productName);
- }
- }
路由片段参数类型约束
只有为 int 类型的才会被匹配
- public class ProductModule : NancyModule
- {
- public ProductModule()
- {
- Get("/products/{productId:int}", p => "Product id is" + p.productId);
- }
- }
Nancy 前后端交互
如何返回视图, 我们尝试着在 Views 中创建静态文件 html(地址为: Views/Student/StudentList.HTML), 并构造 moduls 返回 view 视图:
- public HelloModule()
- {
- Get("/", p => View["Student/StudentList.html"]);
- }
F5, 启动项目你会发现..
Nancy 视图位置约定
Nancy 是有一套自己的约定的, 那我们也不想和它约定, 谁理他呢, 我们可以自己自定义约定.
为此, 您需要创建一个自定义引导程序, 并将您的约定 (使用前面描述的函数签名) 添加到 Conventions.ViewLocationConventions 集合中. 首先创建一个 CustomRootPathProvider 类, 继承了 IRootPathPrvider.
- public class CustomRootPathProvider : IRootPathProvider
- {
- public string GetRootPath()
- {
- return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Views");
- }
- }
特别提醒: 如果是测试环境而并非是生产环境请将路径换为: Directory.GetCurrentDirectory()
通过拼接我们已经将项目的根目录改编成了 Views, 然后我们再创建一个新类, CustomBootstrapper 是为了生效我们自定义的去重写了 RootPathProvider.
- public class CustomBootstrapper : DefaultNancyBootstrapper
- {
- protected override IRootPathProvider RootPathProvider
- {
- get
- {
- return new CustomRootPathProvider();
- }
- }
- }
这个时候, 原本的 Nancy 的追踪的功能就已经被我们给 kill 掉了, 如果想要再启动则需要在 CustomBootstrapper 添加代码如下:
- public override void Configure(INancyEnvironment environment)
- {
- environment.Tracing(enabled: true, displayErrorTraces: true);
- base.Configure(environment);
- }
那么我们现在启动, ok 成功了(找到了)!
超级简单视图引擎(NancyFx 默认推荐)
超级简单视图引擎, 也称为 SSVE, 是一个正则表达式 (实现使用正则表达式执行替换) 的视图引擎, 旨在支持简单的模板场景.
没有必要安装单独的 Nuget 来使用引擎, 因为它嵌入到主 Nancy 组件中, 并且将自动连接并准备好在您的应用程序中使用. 该引擎处理与任何意见 sshtml,HTML 或 htm 文件扩展名.
标准变量替换:
如果未指定参数, 则替换参数的字符串表示形式或模型本身. 如果无法执行替换, 例如, 如果指定了无效的模型属性, 则将替换为[Err!]
句法
@Model[.Parameters]
例
Hello @Model.Name, your age is @Model.User.Age
迭代:
使您可以迭代集合的模型. 迭代器不能嵌套, 语法如下:
- @Each[.Parameters]
- [@Current[.Parameters]]
- @EndEach
我们将 StudentList 作为参数传入到我们的视图中, 代码定义如下:
Student 类的简单定义:
- public class Student
- {
- public int StudentID { get; set; }
- public string StudentName { get; set; }
- }
Module.cs 的定义:
- public class HelloModule : NancyModule
- {
- List<Student> list = new List<Student>()
- {
- new Student(){ StudentID =1 , StudentName = "张子浩"},
- new Student(){ StudentID =2 , StudentName = "张得帅"},
- new Student(){ StudentID =3 , StudentName = "张大彪"}
- };
- public HelloModule()
- {
- Get("/hello", p => {
- return View["hello.html", new
- {
- list
- }];
- });
- }
- }
- hello.HTML:
- <table>
- <tr>
- ISBN
- </tr>
- <tr>
- Book Name
- </tr>
- <tbody>
- @Each.list
- <tr>
- <td>
- @Current.StudentID
- </td>
- <td>
- @Current.StudentName
- </td>
- </tr>
- @EndEach
- </tbody>
- </table>
条件:
参数必须是布尔值(请参阅下面的隐式条件). 不支持嵌套 @If 和 @IfNot 语句, 语法如下:
- @If[Not].Parameters
- [contents]
- @EndIf
栗子:
- @IfNot.HasUsers
- No users found!
- @EndIf
我们在 Student 实体中添加了一个布尔值为了给其中的示例做出演示:
- public class HelloModule : NancyModule
- {
- List<Student> list = new List<Student>()
- {
- new Student(){ StudentID =1 , StudentName = "张子浩",isDisplay = false},
- new Student(){ StudentID =2 , StudentName = "张得帅",isDisplay=false},
- new Student(){ StudentID =3 , StudentName = "张大彪",isDisplay=true}
- };
- public HelloModule()
- {
- Get("/hello", p => {
- return View["hello.html", new
- {
- list
- }];
- });
- }
- }
- public class Student
- {
- public int StudentID { get; set; }
- public string StudentName { get; set; }
- public bool isDisplay { get; set; }
- }
- hello.HTML:
- <table>
- <tr>
- ISBN
- </tr>
- <tr>
- Book Name
- </tr>
- <tbody>
- @Each.list
- @If.isDisplay
- <tr>
- <td>
- @Current.StudentID
- </td>
- <td>
- @Current.StudentName
- </td>
- </tr>
- @EndIf
- @EndEach
- </tbody>
- </table>
Partial View
呈现局部视图. 可以指定当前模型的属性以用作局部视图的模型, 或者可以省略它以使用当前视图的模型. 视图的文件扩展名是可选的.
语法:
@Partial['<view name>'[, Model.Property]]
例:
- // 只返回视图
- @Partial['subview.sshtml'];
- // 带模型的
- @Partial['subview.sshtml', Model.User];
我们创建一个 HTML, 名为 Partial.HTML, 定义如下:
<body>
部分 View: @Model
- </body>
- hello.HTML:
- <table>
- <tr>
- ISBN
- </tr>
- <tr>
- Book Name
- </tr>
- <tbody>
- @Each.list
- <tr>
- <td>
- @Current.StudentID
- </td>
- <td>
- @Partial['Partial.html',Model.StudentName]
- </td>
- </tr>
- @EndEach
- </tbody>
- </table>
如果不需要去构造部分视图的内部实体, 那么你就不用传第二个参数.
南希生命周期
当接收到客户端的请求之后, 我们回到南希的管道中, 分析了路由和一些模块规则, 通过使用 irouteinvoker 调用路由, 返回对应的静态文件, 通过钩子继续配置引导程序, 看看是否报错, 没有的话直接通过 Handler 返回 response.
评价 NancyFx
在 2016 年 Nancy 就停止了更新, 它是一个类似于 mvc 的框架, 个人认为它的路由机制很不错, 但是视图用起来不是很舒服, 还是没人支持啊!
来源: http://www.bubuko.com/infodetail-2909084.html