基於Nancy.Hosting.Aspnet的Nancy小Demo
近來學習了一下Nancy這個框架,感覺挺好用的,就寫篇簡單的文章記錄一下大致用法,由於是剛接觸,寫的代碼
可能不規範,也沒有具體的分層。。莫吐槽。。。
Nancy的官網:http://nancyfx.org/
GitHub地址:https://github.com/NancyFx/Nancy
Nancy在文檔的介紹 -- 輕量級
" Nancy is a lightweight, low-ceremony, framework for building HTTP based services on .NET and Mono. "
Nancy有多種Hosting:
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 SSL
本文寫的Demo是基於Hosting Nancy with ASP.NET。
開發環境 :win 10 + VS2015 Community + SqlServer 2012
廢話不多說,開始正題:
一、新建一個空的asp.net項目
建好之後空空如也
二、通過NuGet添加Nancy相關的Packages
主要是Nancy、Nancy.Hosting.Aspnet、Nancy.Viewengines.Razor這三個。其版本依次為1.4.3、1.4.1、1.4.3
我這裡選擇的視圖引擎是Razor,習慣了,你們可以選擇其他,這個問題不大。
三、更新一下Razor
預設安裝Nancy.Viewengines.Razor之後,它會安裝 Microsoft.AspNet.Razor.2.0.30506.0,我們用的是最新版的3.2.3
在NuGet通過已安裝的Packages來更新
到這裡,基本的工作已經OK了。
這裡用到了Dapper,所以我也添加了它的引用。
註:這裡是通過NuGet安裝的,所以它也在web.config里生成了一些配置。如果是手動添加引用的,註意要修改web.config。
四、加入css和javascript文件
允許我偷偷懶,這裡的我是直接copy一般新建mvc項目的,就連頁面佈局也是用的新建項目的模板。。
五、新建Moudles、Models、ViewModels、Views四個文件夾。
Modules-->相當於MVC中的Controllers文件夾
Models-->存放模型
ViewModels-->存放視圖模型
Views-->存放視圖
六、在Views下麵建一個佈局頁 _Layout.cshtml
就新建的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>_Layout.cshtml
七、在Modules下新建一個HomeModule.cs,具體如下:
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 }HomeModule.cs
同時在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>Index.cshtml
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>About.cshtml
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:[email protected]">[email protected]</a><br /> 17 <strong>Marketing:</strong> <a href="mailto:[email protected]">[email protected]</a> 18 </address>Contact.cshtml
然後F5,跑一下
已經能跑起來了。
下麵就是結合資料庫了。
八、在Models下麵建兩個類
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 }Movie.cs
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 }MovieType.cs
以Movie表為例,繼續下麵的工作。
九、由於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 }MovieViewModel.cs
1 public class MovieListViewModel 2 { 3 public IEnumerable<MovieViewModel> Movies { get; set; } 4 }MovieListViewModel.cs
十、現在就該寫寫類似mvc控制器的東西了,在Modules文件夾下建立MovieModule.cs
把數據提取出來
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 }MovieModule.cs
然後就去編寫視圖
在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>Index.cshtml
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 }ShowMovieEditPage
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 }MovieEdit
添加一個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>Edit.cshtml
然後即可跑起來了。
其中用到了一個模型綁定,需要添加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 {