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的框架,個人認為它的路由機制很不錯,但是視圖用起來不是很舒服,還是沒人支持啊!
