近來學習了一下Nancy這個框架,感受挺好用的,就寫篇簡單的文章記錄一下大體用法,因爲是剛接觸,寫的代碼javascript
可能不規範,也沒有具體的分層。。莫吐槽。。。css
Nancy的官網:http://nancyfx.org/html
GitHub地址:https://github.com/NancyFx/Nancyjava
Nancy在文檔的介紹 -- 輕量級jquery
" Nancy is a lightweight, low-ceremony, framework for building HTTP based services on .NET and Mono. "git
Nancy有多種Hosting:github
Hosting Nancy with ASP.NET
Hosting Nancy with WCF
Hosting Nancy with Azure
Hosting Nancy with OWIN
Web (Katana)
Self Hosting
Environment Variables
Conditional Pass-through
Hosting Nancy with Umbraco
Hosting Nancy with Nginx on Ubuntu
Hosting Nancy with FastCgi
Self Hosting Nancy
Implementing a Host
Accessing the client certificate when using SSLweb
本文寫的Demo是基於Hosting Nancy with ASP.NET。sql
開發環境 :win 10 + VS2015 Community + SqlServer 2012數據庫
廢話很少說,開始正題:
建好以後空空如也
主要是Nancy、Nancy.Hosting.Aspnet、Nancy.Viewengines.Razor這三個。其版本依次爲1.4.三、1.4.一、1.4.3
我這裏選擇的視圖引擎是Razor,習慣了,大家能夠選擇其餘,這個問題不大。
默認安裝Nancy.Viewengines.Razor以後,它會安裝 Microsoft.AspNet.Razor.2.0.30506.0,咱們用的是最新版的3.2.3
在NuGet經過已安裝的Packages來更新
到這裏,基本的工做已經OK了。
這裏用到了Dapper,因此我也添加了它的引用。
注:這裏是經過NuGet安裝的,因此它也在web.config裏生成了一些配置。若是是手動添加引用的,注意要修改web.config。
容許我偷偷懶,這裏的我是直接copy通常新建mvc項目的,就連頁面佈局也是用的新建項目的模板。。
Modules-->至關於MVC中的Controllers文件夾
Models-->存放模型
ViewModels-->存放視圖模型
Views-->存放視圖
就新建的mvc模板copy過來,稍加修改
1 @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<dynamic> 2 <!DOCTYPE html> 3 <html> 4 <head> 5 <meta charset="utf-8" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>@ViewBag.Title - Catcher's NancyDemo</title> 8 <link href="~/Content/bootstrap.min.css" rel="stylesheet" /> 9 <link href="~/Content/Site.css" rel="stylesheet" /> 10 <link rel="shortcut icon" href="~/favicon.ico" /> 11 </head> 12 <body> 13 <div class="navbar navbar-inverse navbar-fixed-top"> 14 <div class="container"> 15 <div class="navbar-header"> 16 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> 17 <span class="icon-bar"></span> 18 <span class="icon-bar"></span> 19 <span class="icon-bar"></span> 20 </button> 21 <a href="/" class="navbar-brand">NancyDemo</a> 22 </div> 23 <div class="navbar-collapse collapse"> 24 <ul class="nav navbar-nav"> 25 <li><a href="/">首頁</a></li> 26 <li><a href="/home/about">關於咱們</a></li> 27 <li><a href="/home/contact">聯繫咱們</a></li> 28 <li><a href="/movie/">電影</a></li> 29 <li><a href="/movie-type/">類型</a></li> 30 </ul> 31 </div> 32 </div> 33 </div> 34 <div class="container body-content"> 35 @RenderBody() 36 <hr /> 37 <footer> 38 <p>© @DateTime.Now.Year - My ASP.NET Application</p> 39 </footer> 40 </div> 41 <script src="~/Scripts/jquery-1.10.2.min.js"></script> 42 <script src="~/Scripts/bootstrap.min.js"></script> 43 </body> 44 </html>
1 public class HomeModule : NancyModule 2 { 3 public HomeModule() 4 { 5 Get["/"] = _ => ShowHomePage(); 6 Get["/home/about"] = _ => ShowAboutPage(); 7 Get["/home/contact"] = _ => ShowContactPage(); 8 } 9 10 private dynamic ShowContactPage() 11 { 12 return View["Contact"]; 13 } 14 15 private dynamic ShowAboutPage() 16 { 17 return View["About"]; 18 } 19 20 private dynamic ShowHomePage() 21 { 22 return View["Index"]; 23 } 24 }
同時在Views文件夾下面新建一個Home的子文件夾,在把mvc模板中的Index.cshtml,About.cshtml,Contact.cshtml
copy過來稍加修改
1 @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<dynamic> 2 @{ 3 ViewBag.Title = "首頁"; 4 Layout = "Views/_Layout.cshtml"; 5 } 6 <div class="jumbotron"> 7 <h1>NancyDemo</h1> 8 <p class="lead">Nancy is a lightweight, low-ceremony, framework for building HTTP based services on .NET and Mono. The goal of the framework is to stay out of the way as much as possible and provide a super-duper-happy-path to all interactions.</p> 9 <p><a href="http://nancyfx.org/" class="btn btn-primary btn-lg">Learn more »</a></p> 10 </div>
1 @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<dynamic> 2 @{ 3 ViewBag.Title = "About"; 4 Layout = "Views/_Layout.cshtml"; 5 } 6 <h2>@ViewBag.Title.</h2> 7 <p>Use this area to provide additional information.</p>
1 @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<dynamic> 2 @{ 3 ViewBag.Title = "Contact"; 4 Layout = "Views/_Layout.cshtml"; 5 } 6 <h2>@ViewBag.Title.</h2> 7 8 <address> 9 One Microsoft Way<br /> 10 Redmond, WA 98052-6399<br /> 11 <abbr title="Phone">P:</abbr> 12 425.555.0100 13 </address> 14 15 <address> 16 <strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br /> 17 <strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a> 18 </address>
而後F5,跑一下
已經能跑起來了。
下面就是結合數據庫了。
1 public class Movie 2 { 3 public int MovieId { get; set; } 4 5 public string MovieName { get; set; } 6 7 public int MovieTypeId { get; set; } 8 9 public DateTime MovieAddTime { get; set; } 10 11 public virtual MovieType MovieType { get; set; } 12 13 public Movie() 14 { 15 MovieAddTime = DateTime.Now; 16 } 17 }
1 public class MovieType 2 { 3 public MovieType() 4 { 5 Movies = new HashSet<Movie>(); 6 } 7 8 9 public int TypeId { get; set; } 10 11 public string TypeName { get; set; } 12 13 public virtual ICollection<Movie> Movies { get; set; } 14 }
以Movie表爲例,繼續下面的工做。
在ViewModels文件夾下面創建MovieViewModel.cs、MovieListViewModel.cs
1 public class MovieViewModel 2 { 3 public int MovieId { get; set; } 4 5 public string MovieName { get; set; } 6 7 public int MovieTypeId { get; set; } 8 9 public string MovieTypeName { get; set; } 10 11 public DateTime MovieAddTime { get; set; } 12 }
1 public class MovieListViewModel 2 { 3 public IEnumerable<MovieViewModel> Movies { get; set; } 4 }
把數據提取出來
1 public class MovieModule : NancyModule 2 { 3 public MovieModule() : base("/movie") 4 { 5 Get["/"] = _ => ShowMovieIndexPage(); 6 } 7 8 private readonly string _sqlconnection = 9 "Data Source=192.168.0.71;Initial Catalog=NancyDemo;User Id=sa;Password=dream_time1314;"; 10 11 public SqlConnection OpenConnection() 12 { 13 SqlConnection connection = new SqlConnection(_sqlconnection); 14 connection.Open(); 15 return connection; 16 } 17 18 private dynamic ShowMovieIndexPage() 19 { 20 using (IDbConnection conn = OpenConnection()) 21 { 22 string getAllMoviesStoredProcedure = @"up_GetAllMovies"; 23 MovieListViewModel viewModel = new MovieListViewModel 24 { 25 Movies = conn.Query<MovieViewModel>(getAllMoviesStoredProcedure, 26 null, null, true, null, CommandType.StoredProcedure) 27 }; 28 return View["Index", viewModel]; 29 } 30 } 31 }
而後就去編寫視圖
在Views下面新建一個Movie文件夾,用於存放相關視圖
1 @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<MovieDemo.ViewModels.MovieListViewModel> 2 @{ 3 Layout = "Views/_Layout.cshtml"; 4 ViewBag.Title = "電影列表"; 5 } 6 <a href="/movie/create">添加</a> 7 <div> 8 <table class="table"> 9 <tr> 10 <th> 11 # 12 </th> 13 <th> 14 電影名稱 15 </th> 16 <th> 17 電影類型 18 </th> 19 <th> 20 添加時間 21 </th> 22 <th></th> 23 </tr> 24 @foreach (var item in Model.Movies) 25 { 26 <tr> 27 <td> 28 @item.MovieId 29 </td> 30 <td> 31 @item.MovieName 32 </td> 33 <td> 34 @item.MovieTypeName 35 </td> 36 <td> 37 @item.MovieAddTime 38 </td> 39 <td> 40 <a href="/movie/edit/@item.MovieId">修改</a> 41 <a class="delete" href="/movie/delete/@item.MovieId">刪除</a> 42 </td> 43 </tr> 44 } 45 </table> 46 </div>
F5跑一下
OK!
而後就是修改某條數據,
在MovieModule.cs 的構造函數中添加
1 Get["/edit/{movieId}"] = _ => ShowMovieEditPage(_.movieId); 2 Post["/edit/{movieId}"] = _ => 3 { 4 var movie = this.Bind<Movie>(); 5 return MovieEdit(movie); 6 };
而後添加ShowMovieEditPage和MovieEdit這兩個方法
1 private dynamic ShowMovieEditPage(int movieId) 2 { 3 string getOneMovieStoredProcedure = @"up_GetMovieByMovieId"; 4 string getALLTypeStoredProcedure = @"up_GetAllMovieTypes"; 5 DynamicParameters dynamicParameters = new DynamicParameters(); 6 dynamicParameters.Add("@MovieId", movieId); 7 8 using (IDbConnection conn = OpenConnection()) 9 { 10 var movieViewModel = conn.Query<MovieViewModel>(getOneMovieStoredProcedure, dynamicParameters, null, true, null, CommandType.StoredProcedure).SingleOrDefault(); 11 ViewBag.typeList = conn.Query<MovieType>(getALLTypeStoredProcedure, null, null, true, null, CommandType.StoredProcedure); 12 return View["Edit", movieViewModel]; 13 14 } 15 }
1 private dynamic MovieEdit(Movie movie) 2 { 3 string updateMovieStoredProcedure = @"up_UpdateMovieByMovieId"; 4 DynamicParameters dynamicParameters = new DynamicParameters(); 5 dynamicParameters.Add("@MovieId", movie.MovieId); 6 dynamicParameters.Add("@MovieName", movie.MovieName); 7 dynamicParameters.Add("@MovieTypeId", movie.MovieTypeId); 8 9 using (IDbConnection conn = OpenConnection()) 10 { 11 conn.Execute(updateMovieStoredProcedure, dynamicParameters, null, null, CommandType.StoredProcedure); 12 return Response.AsRedirect("/movie"); 13 } 14 }
添加一個Movie的Edit視圖
1 @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<MovieDemo.ViewModels.MovieViewModel> 2 @{ 3 ViewBag.Title = "修改電影信息"; 4 Layout = "Views/_Layout.cshtml"; 5 } 6 7 <form action="/movie/edit/@Model.MovieId" method="post"> 8 <div class="form-group"> 9 <label class="control-label col-md-2">電影名稱</label> 10 <div class="col-md-10"> 11 <input type="text" class="form-control" id="MovieName" name="MovieName" value="@Model.MovieName" /> 12 </div> 13 </div> 14 <div class="form-group"> 15 <label class="control-label col-md-2">電影類型</label> 16 <div class="col-md-10"> 17 <select id="MovieTypeId" name="MovieTypeId" class="form-control"> 18 @foreach (var item in (System.Collections.Generic.List<MovieDemo.Models.MovieType>)ViewBag.typeList) 19 { 20 if (Model.MovieTypeId == item.TypeId) 21 { 22 <option selected="selected" value="@item.TypeId">@item.TypeName</option> 23 } 24 else 25 { 26 <option value="@item.TypeId">@item.TypeName</option> 27 } 28 } 29 30 </select> 31 </div> 32 </div> 33 <div class="form-group"> 34 <div class="col-md-offset-2 col-md-10"> 35 <input type="submit" value="修改" class="btn btn-default" /> 36 </div> 37 </div> 38 </form>
而後便可跑起來了。
其中用到了一個模型綁定,須要添加Nancy.ModelBinding引用,有了這個綁定,省了不少事!!
var movie = this.Bind<Movie>();
同理,增長和刪除也是一樣的作法,下面是MovieModule.cs的完整代碼
1 using MovieDemo.Models; 2 using MovieDemo.ViewModels; 3 using Dapper; 4 using Nancy; 5 using Nancy.ModelBinding; 6 using System.Data; 7 using System.Data.SqlClient; 8 using System.Linq; 9 10 namespace MovieDemo.Modules 11 { 12 public class MovieModule : NancyModule 13 { 14 public MovieModule() : base("/movie") 15 { 16 Get["/"] = _ => ShowMovieIndexPage(); 17 18 Get["/edit/{movieId}"] = _ => ShowMovieEditPage(_.movieId); 19 Post["/edit/{movieId}"] = _ => 20 { 21 var movie = this.Bind<Movie>(); 22 return MovieEdit(movie); 23 }; 24 25 Get["/create"] = _ => ShowMovieCreatePage(); 26 Post["/create"] = _ => 27 { 28 var movie = this.Bind<Movie>(); 29 return MovieCreate(movie); 30 }; 31 32 Get["/delete/{movieId}"] = _ => MovieDelete(_.movieId); 33 } 34 35 private readonly string _sqlconnection = 36 "Data Source=192.168.0.71;Initial Catalog=NancyDemo;User Id=sa;Password=dream_time1314;"; 37 38 public SqlConnection OpenConnection() 39 { 40 SqlConnection connection = new SqlConnection(_sqlconnection); 41 connection.Open(); 42 return connection; 43 } 44 45 private dynamic MovieDelete(int movieId) 46 { 47 string deleteMovieStoredProcedure = @"up_DeleteMovieByMovieId"; 48 DynamicParameters dynamicParameters = new DynamicParameters(); 49 dynamicParameters.Add("@MovieId", movieId); 50 using (IDbConnection conn = OpenConnection()) 51 { 52 conn.Execute(deleteMovieStoredProcedure, dynamicParameters, null, null, CommandType.StoredProcedure); 53 return Response.AsRedirect("/movie"); 54 } 55 } 56 57 private dynamic MovieCreate(Movie movie) 58 { 59 string createMovieStoredProcedure = @"up_InsertMovie"; 60 DynamicParameters dynamicParameters = new DynamicParameters(); 61 dynamicParameters.Add("@MovieName", movie.MovieName); 62 dynamicParameters.Add("@MovieTypeId", movie.MovieTypeId); 63 dynamicParameters.Add("@MovieAddTime", movie.MovieAddTime); 64 65 using (IDbConnection conn = OpenConnection()) 66 { 67 conn.Execute(createMovieStoredProcedure, dynamicParameters, null, null, CommandType.StoredProcedure); 68 return Response.AsRedirect("/movie"); 69 } 70 } 71 72 private dynamic ShowMovieCreatePage() 73 { 74 string getALLTypeStoredProcedure = @"up_GetAllMovieTypes"; 75 using (IDbConnection conn = OpenConnection()) 76 { 77 MovieTypeListViewModel viewModel = new MovieTypeListViewModel 78 { 79 MovieTypes = conn.Query<MovieType>(getALLTypeStoredProcedure, null, null, true, null, CommandType.StoredProcedure) 80 }; 81 return View["Create", viewModel]; 82 } 83 } 84 85 private dynamic MovieEdit(Movie movie) 86 { 87 string updateMovieStoredProcedure = @"up_UpdateMovieByMovieId"; 88 DynamicParameters dynamicParameters = new DynamicParameters(); 89 dynamicParameters.Add("@MovieId", movie.MovieId); 90 dynamicParameters.Add("@MovieName", movie.MovieName); 91 dynamicParameters.Add("@MovieTypeId", movie.MovieTypeId); 92 93 using (IDbConnection conn = OpenConnection()) 94 { 95 conn.Execute(updateMovieStoredProcedure, dynamicParameters, null, null, CommandType.StoredProcedure); 96 return Response.AsRedirect("/movie"); 97 } 98 } 99 100 private dynamic ShowMovieEditPage(int movieId) 101 { 102 string getOneMovieStoredProcedure = @"up_GetMovieByMovieId"; 103 string getALLTypeStoredProcedure = @"up_GetAllMovieTypes"; 104 DynamicParameters dynamicParameters = new DynamicParameters(); 105 dynamicParameters.Add("@MovieId", movieId); 106 107 using (IDbConnection conn = OpenConnection()) 108 { 109 var movieViewModel = conn.Query<MovieViewModel>(getOneMovieStoredProcedure, dynamicParameters, null, true, null, CommandType.StoredProcedure).SingleOrDefault(); 110 ViewBag.typeList = conn.Query<MovieType>(getALLTypeStoredProcedure, null, null, true, null, CommandType.StoredProcedure); 111 return View["Edit", movieViewModel]; 112 113 } 114 } 115 116 private dynamic ShowMovieIndexPage() 117 { 118 using (IDbConnection conn = OpenConnection()) 119 { 120 string getAllMoviesStoredProcedure = @"up_GetAllMovies"; 121 MovieListViewModel viewModel = new MovieListViewModel 122 { 123 Movies = conn.Query<MovieViewModel>(getAllMoviesStoredProcedure, 124 null, null, true, null, CommandType.StoredProcedure) 125 }; 126 return View["Index", viewModel]; 127 } 128 } 129 } 130 }
在添加相應的視圖便可完成。
這個東西能夠簡單認爲是引導程序,你能夠自定義一些鬼東西,把它看成一個容器來用,
還能夠經過它來實現依賴注入,裏面有個默認的 TinyIoC 。。。。。詳細介紹請看https://github.com/NancyFx/Nancy/wiki/Bootstrapper
下面是個人CustomBootstrapper.cs配置
1 public class CustomBootstrapper : DefaultNancyBootstrapper 2 { 3 protected override void ConfigureApplicationContainer(TinyIoCContainer container) 4 { 5 base.ConfigureApplicationContainer(container); 6 //container.Register<IMoviesRepository, MoviesRepository>(); 7 //container.Register<IMovieTypesRepository, MovieTypesRepository>(); 8 } 9 protected override void ConfigureConventions(NancyConventions nancyConventions) 10 { 11 base.ConfigureConventions(nancyConventions); 12 nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("Scripts")); 13 nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("Content")); 14 } 15 }
依賴注入我是沒有用的,因此我註釋了。用過Ninject、Autofac、Unity這些的,相信依賴注入這一塊理解起來So easy!
Nancy也有相應的拓展
https://github.com/NancyFx/Nancy.Bootstrappers.Autofac
https://github.com/NancyFx/Nancy.Bootstrappers.Unity
https://github.com/NancyFx/Nancy.Bootstrappers.Ninject
還有一塊是ConfigureConventions
這一塊彷佛是用來處理靜態文件(css、js)的,跟Mvc中的BundleConfig很相似
到這裏,開發工做已經完成。下面是部署的時候了。
Linux環境及配置
CentOS 6.7 + mono 4.2.2 + Jexus 5.8.0
將發佈事後的目錄上傳到centos的 /var/www/ 中,而後在 /usr/jexus/siteconf 中創建一個新的配置文件
從新啓動jexus便可。
下面上幾張運行的圖
徹底的無縫兼容。
本篇的完整代碼已託管到GitHub
下載地址:https://github.com/hwqdt/Demos/tree/master/NancyDemoWithHostingAspnet
下雨天,心情壓抑,寫篇bolg來拯救本身的好心情 ~_~
後面有時間會寫基於owin的demo