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上,它在OSX和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>
如果不需要去構造部分視圖的內部實體,那么你就不用傳第二個參數。
南希生命周期
評價NancyFx
在2016年Nancy就停止了更新,它是一個類似於mvc的框架,個人認為它的路由機制很不錯,但是視圖用起來不是很舒服,還是沒人支持啊!