本文共 6063 字,大约阅读时间需要 20 分钟。
近年来,Nancy框架在.NET和Mono开发领域逐渐崭露头角。作为一名刚接触Nancy开发的新手,我在这里尝试记录下自己的学习历程,分享一个基于Nancy框架构建的简易电影管理系统的开发过程。
通过VS2015创建一个新的空ASP.NET项目,初始状态下项目看起来还是相当基础。为了便于后续开发,我直接复制了一个MVC项目的基本模板,包括页面布局和样本视图。
通过NuGet安装必要的Nancy组件:
在安装Razor后,默认会引用Microsoft.AspNet.Razor。为了使用最新版本,我手动更新至Razor 3.2.3。
此外,为了数据库操作,我还安装了Dapper ORM,以简化数据库调用。
为便于开发,按照MVC项目的标准结构进行组织:
在Views文件夹下新建布局页 _Layout.cshtml,并复制并修改自MVC项目的模板。为了方便后续开发,直接使用Razor引擎。
在Modules文件夹下新建HomeModule.cs,定义路由:
public class HomeModule : NancyModule{ public HomeModule() : base("/home") { Get["/"] = _ => ShowHomePage(); Get["/home/about"] = _ => ShowAboutPage(); Get["/home/contact"] = _ => ShowContactPage(); } private dynamic ShowHomePage() => View["Index"]; private dynamic ShowAboutPage() => View["About"]; private dynamic ShowContactPage() => View["Contact"];} 在Models文件夹下创建两个类:
public class Movie{ public int MovieId { get; set; } public string MovieName { get; set; } public int MovieTypeId { get; set; } public DateTime MovieAddTime { get; set; } public MovieType MovieType { get; set; } public Movie() { MovieAddTime = DateTime.Now; }}public class MovieType{ public MovieType() { Movies = new HashSet (); } public int TypeId { get; set; } public string TypeName { get; set; } public virtual ICollection Movies { get; set; }} 在ViewModels文件夹下创建两个类:
public class MovieViewModel{ public int MovieId { get; set; } public string MovieName { get; set; } public int MovieTypeId { get; set; } public string MovieTypeName { get; set; } public DateTime MovieAddTime { get; set; }}public class MovieListViewModel{ public IEnumerable Movies { get; set; }} 为了实现数据持久化,我使用了Dapper ORM,并创建了相应的存储过程。通过修改MovieModule.cs,实现了电影的增删改查功能。以下是核心代码:
public class MovieModule : NancyModule{ public MovieModule() : base("/movie") { Get["/"] = _ => ShowMovieIndexPage(); Get["/edit/{movieId}"] = _ => ShowMovieEditPage(_.movieId); Post["/edit/{movieId}"] = _ => { var movie = this.Bind (); return MovieEdit(movie); }; Get["/create"] = _ => ShowMovieCreatePage(); Post["/create"] = _ => { var movie = this.Bind (); return MovieCreate(movie); }; Get["/delete/{movieId}"] = _ => MovieDelete(_.movieId); } private readonly string _sqlConnection = "Data Source=192.168.0.71;Initial Catalog=NancyDemo;User Id=sa;Password=dream_time1314;"; public SqlConnection OpenConnection() => new SqlConnection(_sqlConnection); private dynamic MovieDelete(int movieId) { string deleteMovieStoredProcedure = @"up_DeleteMovieByMovieId"; using (SqlConnection conn = OpenConnection()) { conn.Execute(deleteMovieStoredProcedure, new { @MovieId = movieId }, null, null, CommandType.StoredProcedure); return Response.AsRedirect("/movie"); } } private dynamic MovieCreate(Movie movie) { string createMovieStoredProcedure = @"up_InsertMovie"; using (SqlConnection conn = OpenConnection()) { conn.Execute(createMovieStoredProcedure, new { @MovieName = movie.MovieName, @MovieTypeId = movie.MovieTypeId, @MovieAddTime = movie.MovieAddTime }, null, null, CommandType.StoredProcedure); return Response.AsRedirect("/movie"); } } private dynamic MovieEdit(Movie movie) { string updateMovieStoredProcedure = @"up_UpdateMovieByMovieId"; using (SqlConnection conn = OpenConnection()) { conn.Execute(updateMovieStoredProcedure, new { @MovieId = movie.MovieId, @MovieName = movie.MovieName, @MovieTypeId = movie.MovieTypeId }, null, null, CommandType.StoredProcedure); return Response.AsRedirect("/movie"); } } private dynamic ShowMovieCreatePage() { string getALLTypeStoredProcedure = @"up_GetAllMovieTypes"; using (SqlConnection conn = OpenConnection()) { MovieTypeListViewModel viewModel = new MovieTypeListViewModel { MovieTypes = conn.Query (getALLTypeStoredProcedure, null, null, true, null, CommandType.StoredProcedure) }; return View["Create", viewModel]; } } private dynamic ShowMovieEditPage(int movieId) { string getOneMovieStoredProcedure = @"up_GetMovieByMovieId"; string getALLTypeStoredProcedure = @"up_GetAllMovieTypes"; DynamicParameters dynamicParameters = new DynamicParameters(); dynamicParameters.Add("@MovieId", movieId); using (SqlConnection conn = OpenConnection()) { var movieViewModel = conn.Query (getOneMovieStoredProcedure, dynamicParameters, null, true, null, CommandType.StoredProcedure).SingleOrDefault(); ViewBag.typeList = conn.Query (getALLTypeStoredProcedure, null, null, true, null, CommandType.StoredProcedure); return View["Edit", movieViewModel]; } } private dynamic ShowMovieIndexPage() { using (SqlConnection conn = OpenConnection()) { MovieListViewModel viewModel = new MovieListViewModel { Movies = conn.Query (@"up_GetAllMovies", null, null, true, null, CommandType.StoredProcedure) }; return View["Index", viewModel]; } }} 在Views文件夹下创建相应的视图:
通过模型绑定(Nancy.ModelBinding)实现数据的自动绑定,简化了代码。
将开发好的项目部署到Linux环境中。推荐使用CentOS 6.7 + Mono 4.2.2 + Jexus 5.8.0。部署步骤如下:
/var/www//usr/jexus/siteconf 下新建配置文件通过本文的实例,可以看出Nancy框架的灵活性和高效性。虽然初期学习曲线较陡,但随着熟悉程度的提升,开发效率显著提升。未来,我将深入研究Nancy的高级功能,如依赖注入和中间件,探索更多可能性。
转载地址:http://azcfk.baihongyu.com/