近来学习了一下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项目的,就连页面布局也是用的新建项目的模板。。

五、新建Modules、Models、ViewModels、Views四个文件夹

Modules-->相当于MVC中的Controllers文件夹

Models-->存放模型

ViewModels-->存放视图模型

Views-->存放视图

六、在Views下面建一个布局页_Layout.cshtml

就新建的mvc模板copy过来,稍加修改

 @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<dynamic>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - Catcher's NancyDemo</title>
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/Site.css" rel="stylesheet" />
<link rel="shortcut icon" href="~/favicon.ico" />
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="/" class="navbar-brand">NancyDemo</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">首页</a></li>
<li><a href="/home/about">关于我们</a></li>
<li><a href="/home/contact">联系我们</a></li>
<li><a href="/movie/">电影</a></li>
<li><a href="/movie-type/">类型</a></li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
</body>
</html>

_Layout.cshtml

七、在Modules下新建一个HomeModules.cs,具体如下:

 public class HomeModule : NancyModule
{
public HomeModule()
{
Get["/"] = _ => ShowHomePage();
Get["/home/about"] = _ => ShowAboutPage();
Get["/home/contact"] = _ => ShowContactPage();
} private dynamic ShowContactPage()
{
return View["Contact"];
} private dynamic ShowAboutPage()
{
return View["About"];
} private dynamic ShowHomePage()
{
return View["Index"];
}
}

HomeModule.cs

同时在Views文件夹下面新建一个Home的子文件夹,在把mvc模板中的Index.cshtml,About.cshtml,Contact.cshtml

copy过来稍加修改

 @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<dynamic>
@{
ViewBag.Title = "首页";
Layout = "Views/_Layout.cshtml";
}
<div class="jumbotron">
<h1>NancyDemo</h1>
<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>
<p><a href="http://nancyfx.org/" class="btn btn-primary btn-lg">Learn more &raquo;</a></p>
</div>

Index.cshtml

 @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<dynamic>
@{
ViewBag.Title = "About";
Layout = "Views/_Layout.cshtml";
}
<h2>@ViewBag.Title.</h2>
<p>Use this area to provide additional information.</p>

About.cshtml

 @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<dynamic>
@{
ViewBag.Title = "Contact";
Layout = "Views/_Layout.cshtml";
}
<h2>@ViewBag.Title.</h2> <address>
One Microsoft Way<br />
Redmond, WA -<br />
<abbr title="Phone">P:</abbr>
425.555.
</address> <address>
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br />
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>

Contact.cshtml

然后F5,跑一下

     

已经能跑起来了。

下面就是结合数据库了。

八、在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 virtual MovieType MovieType { get; set; } public Movie()
{
MovieAddTime = DateTime.Now;
}
}

Movie.cs

     public class MovieType
{
public MovieType()
{
Movies = new HashSet<Movie>();
} public int TypeId { get; set; } public string TypeName { get; set; } public virtual ICollection<Movie> Movies { get; set; }
}

MovieType.cs

以Movie表为例,继续下面的工作。

九、由于movie表中的数据展示,抽取出应该有的视图模型

在ViewModels文件夹下面建立MovieViewModel.cs、MovieListViewModel.cs

     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; }
}

MovieViewModel.cs

      public class MovieListViewModel
{
public IEnumerable<MovieViewModel> Movies { get; set; }
}

MovieListViewModel.cs

十、现在就该写写烦人mvc控制器的东西了,在Modules文件夹下建立MovieModules.cs

把数据提取出来

     public class MovieModule : NancyModule
{
public MovieModule() : base("/movie")
{
Get["/"] = _ => ShowMovieIndexPage();
} private readonly string _sqlconnection =
"Data Source=192.168.0.71;Initial Catalog=NancyDemo;User Id=sa;Password=dream_time1314;"; public SqlConnection OpenConnection()
{
SqlConnection connection = new SqlConnection(_sqlconnection);
connection.Open();
return connection;
} private dynamic ShowMovieIndexPage()
{
using (IDbConnection conn = OpenConnection())
{
string getAllMoviesStoredProcedure = @"up_GetAllMovies";
MovieListViewModel viewModel = new MovieListViewModel
{
Movies = conn.Query<MovieViewModel>(getAllMoviesStoredProcedure,
null, null, true, null, CommandType.StoredProcedure)
};
return View["Index", viewModel];
}
}
}

MovieModule.cs

然后就去编写视图

在Views下面新建一个Movie文件夹,用于存放相关视图

 @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<MovieDemo.ViewModels.MovieListViewModel>
@{
Layout = "Views/_Layout.cshtml";
ViewBag.Title = "电影列表";
}
<a href="/movie/create">添加</a>
<div>
<table class="table">
<tr>
<th>
#
</th>
<th>
电影名称
</th>
<th>
电影类型
</th>
<th>
添加时间
</th>
<th></th>
</tr>
@foreach (var item in Model.Movies)
{
<tr>
<td>
@item.MovieId
</td>
<td>
@item.MovieName
</td>
<td>
@item.MovieTypeName
</td>
<td>
@item.MovieAddTime
</td>
<td>
<a href="/movie/edit/@item.MovieId">修改</a>
<a class="delete" href="/movie/delete/@item.MovieId">删除</a>
</td>
</tr>
}
</table>
</div>

Index.cshtml

F5跑一下

OK!

然后就是修改某条数据,

在MovieModule.cs 的构造函数中添加

            Get["/edit/{movieId}"] = _ => ShowMovieEditPage(_.movieId);
Post["/edit/{movieId}"] = _ =>
{
var movie = this.Bind<Movie>();
return MovieEdit(movie);
};

然后添加ShowMovieEditPage和MovieEdit这两个方法

 private dynamic ShowMovieEditPage(int movieId)
{
string getOneMovieStoredProcedure = @"up_GetMovieByMovieId";
string getALLTypeStoredProcedure = @"up_GetAllMovieTypes";
DynamicParameters dynamicParameters = new DynamicParameters();
dynamicParameters.Add("@MovieId", movieId); using (IDbConnection conn = OpenConnection())
{
var movieViewModel = conn.Query<MovieViewModel>(getOneMovieStoredProcedure, dynamicParameters, null, true, null, CommandType.StoredProcedure).SingleOrDefault();
ViewBag.typeList = conn.Query<MovieType>(getALLTypeStoredProcedure, null, null, true, null, CommandType.StoredProcedure);
return View["Edit", movieViewModel]; }
}

ShowMovieEditPage

     private dynamic MovieEdit(Movie movie)
{
string updateMovieStoredProcedure = @"up_UpdateMovieByMovieId";
DynamicParameters dynamicParameters = new DynamicParameters();
dynamicParameters.Add("@MovieId", movie.MovieId);
dynamicParameters.Add("@MovieName", movie.MovieName);
dynamicParameters.Add("@MovieTypeId", movie.MovieTypeId); using (IDbConnection conn = OpenConnection())
{
conn.Execute(updateMovieStoredProcedure, dynamicParameters, null, null, CommandType.StoredProcedure);
return Response.AsRedirect("/movie");
}
}

MovieEdit

添加一个Movie的Edit视图

 @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<MovieDemo.ViewModels.MovieViewModel>
@{
ViewBag.Title = "修改电影信息";
Layout = "Views/_Layout.cshtml";
} <form action="/movie/edit/@Model.MovieId" method="post">
<div class="form-group">
<label class="control-label col-md-2">电影名称</label>
<div class="col-md-10">
<input type="text" class="form-control" id="MovieName" name="MovieName" value="@Model.MovieName" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">电影类型</label>
<div class="col-md-10">
<select id="MovieTypeId" name="MovieTypeId" class="form-control">
@foreach (var item in (System.Collections.Generic.List<MovieDemo.Models.MovieType>)ViewBag.typeList)
{
if (Model.MovieTypeId == item.TypeId)
{
<option selected="selected" value="@item.TypeId">@item.TypeName</option>
}
else
{
<option value="@item.TypeId">@item.TypeName</option>
}
} </select>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="修改" class="btn btn-default" />
</div>
</div>
</form>

Edit.cshtml

然后即可跑起来了。

其中用到了一个模型绑定,需要添加Nancy.ModelBinding引用,有了这个绑定,省了很多事!!

 var movie = this.Bind<Movie>();

同理,增加和删除也是同样的做法,下面是MovieModule.cs的完整代码

 using MovieDemo.Models;
using MovieDemo.ViewModels;
using Dapper;
using Nancy;
using Nancy.ModelBinding;
using System.Data;
using System.Data.SqlClient;
using System.Linq; namespace MovieDemo.Modules
{
public class MovieModule : NancyModule
{
public MovieModule() : base("/movie")
{
Get["/"] = _ => ShowMovieIndexPage(); Get["/edit/{movieId}"] = _ => ShowMovieEditPage(_.movieId);
Post["/edit/{movieId}"] = _ =>
{
var movie = this.Bind<Movie>();
return MovieEdit(movie);
}; Get["/create"] = _ => ShowMovieCreatePage();
Post["/create"] = _ =>
{
var movie = this.Bind<Movie>();
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()
{
SqlConnection connection = new SqlConnection(_sqlconnection);
connection.Open();
return connection;
} private dynamic MovieDelete(int movieId)
{
string deleteMovieStoredProcedure = @"up_DeleteMovieByMovieId";
DynamicParameters dynamicParameters = new DynamicParameters();
dynamicParameters.Add("@MovieId", movieId);
using (IDbConnection conn = OpenConnection())
{
conn.Execute(deleteMovieStoredProcedure, dynamicParameters, null, null, CommandType.StoredProcedure);
return Response.AsRedirect("/movie");
}
} private dynamic MovieCreate(Movie movie)
{
string createMovieStoredProcedure = @"up_InsertMovie";
DynamicParameters dynamicParameters = new DynamicParameters();
dynamicParameters.Add("@MovieName", movie.MovieName);
dynamicParameters.Add("@MovieTypeId", movie.MovieTypeId);
dynamicParameters.Add("@MovieAddTime", movie.MovieAddTime); using (IDbConnection conn = OpenConnection())
{
conn.Execute(createMovieStoredProcedure, dynamicParameters, null, null, CommandType.StoredProcedure);
return Response.AsRedirect("/movie");
}
} private dynamic ShowMovieCreatePage()
{
string getALLTypeStoredProcedure = @"up_GetAllMovieTypes";
using (IDbConnection conn = OpenConnection())
{
MovieTypeListViewModel viewModel = new MovieTypeListViewModel
{
MovieTypes = conn.Query<MovieType>(getALLTypeStoredProcedure, null, null, true, null, CommandType.StoredProcedure)
};
return View["Create", viewModel];
}
} private dynamic MovieEdit(Movie movie)
{
string updateMovieStoredProcedure = @"up_UpdateMovieByMovieId";
DynamicParameters dynamicParameters = new DynamicParameters();
dynamicParameters.Add("@MovieId", movie.MovieId);
dynamicParameters.Add("@MovieName", movie.MovieName);
dynamicParameters.Add("@MovieTypeId", movie.MovieTypeId); using (IDbConnection conn = OpenConnection())
{
conn.Execute(updateMovieStoredProcedure, dynamicParameters, null, null, CommandType.StoredProcedure);
return Response.AsRedirect("/movie");
}
} private dynamic ShowMovieEditPage(int movieId)
{
string getOneMovieStoredProcedure = @"up_GetMovieByMovieId";
string getALLTypeStoredProcedure = @"up_GetAllMovieTypes";
DynamicParameters dynamicParameters = new DynamicParameters();
dynamicParameters.Add("@MovieId", movieId); using (IDbConnection conn = OpenConnection())
{
var movieViewModel = conn.Query<MovieViewModel>(getOneMovieStoredProcedure, dynamicParameters, null, true, null, CommandType.StoredProcedure).SingleOrDefault();
ViewBag.typeList = conn.Query<MovieType>(getALLTypeStoredProcedure, null, null, true, null, CommandType.StoredProcedure);
return View["Edit", movieViewModel]; }
} private dynamic ShowMovieIndexPage()
{
using (IDbConnection conn = OpenConnection())
{
string getAllMoviesStoredProcedure = @"up_GetAllMovies";
MovieListViewModel viewModel = new MovieListViewModel
{
Movies = conn.Query<MovieViewModel>(getAllMoviesStoredProcedure,
null, null, true, null, CommandType.StoredProcedure)
};
return View["Index", viewModel];
}
}
}
}

MovieModule.cs

在添加相应的视图即可完成。

十一、下面还需要简单讲一下Bootstrapper

这个东西可以简单认为是引导程序,你可以自定义一些鬼东西,把它当作一个容器来用,

还可以通过它来实现依赖注入,里面有个默认的 TinyIoC 。。。。。详细介绍请看https://github.com/NancyFx/Nancy/wiki/Bootstrapper

下面是我的CustomBootstrapper.cs配置

 public class CustomBootstrapper : DefaultNancyBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
//container.Register<IMoviesRepository, MoviesRepository>();
//container.Register<IMovieTypesRepository, MovieTypesRepository>();
}
protected override void ConfigureConventions(NancyConventions nancyConventions)
{
base.ConfigureConventions(nancyConventions);
nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("Scripts"));
nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("Content"));
}
}

CustomBootstrapper.cs

依赖注入我是没有用的,所以我注释了。用过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很类似

到这里,开发工作已经完成。下面是部署的时候了。

十二、将做的MovieDemo部署到Linux下

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

Nancy之基于Nancy.Hosting.Aspnet的小Demo的更多相关文章

  1. Nancy之基于Self Hosting的补充小Demo

    前面把Hosting Nancy with ASP.NET.Self Hosting Nancy和Hosting Nancy with OWIN 以demo的形式简单描述了一下. 这篇是为Self H ...

  2. Nancy之基于Nancy.Hosting.Self的小Demo

    继昨天的Nancy之基于Nancy.Hosting.Aspnet的小Demo后, 今天来做个基于Nancy.Hosting.Self的小Demo. 关于Self Hosting Nancy,官方文档的 ...

  3. Nancy之基于Nancy.Owin的小Demo

    前面做了基于Nancy.Hosting.Aspnet和Nancy.Hosting.Self的小Demo 今天我们来做个基于Nancy.Owin的小Demo 开始之前我们来说说什么是Owin和Katan ...

  4. 一个基于ES6+webpack的vue小demo

    上一篇文章<一个基于ES5的vue小demo>我们讲了如何用ES5,vue-router做一个小demo,接下来我们来把它变成基于ES6+webpack的demo. 一.环境搭建及代码转换 ...

  5. 一个基于ES5的vue小demo

    由于现在很多vue项目都是基于ES6开发的,而我学vue的时候大多是看vue官网的API,是基于ES5的,所以对于刚接触项目的我来说要转变为项目的模块化写法确实有些挑战.因此,我打算先做一个基于ES5 ...

  6. 基于FPGA的飞机的小游戏

    基于FPGA的飞机的小游戏 实验原理 该实验主要分为4个模块,采用至上而下的设计方法进行设计.由50M的晶振电路提供时钟源,VGA显示控制模块.图形显示控制模块.移动模块的时钟为25M,由时钟分频电路 ...

  7. 基于HTML5实现五彩连珠小游戏

    今天给大家分享一款基于HTML5实现五彩连珠小游戏.这款游戏的规则:点击彩球移动到期望的位置,每移动一次,画面将随机出现3个新的彩球:当同一颜色的彩球连成5个一行或一列或一斜线时,这5个彩球同时消失, ...

  8. 基于Shiro,JWT实现微信小程序登录完整例子

    小程序官方流程图如下,官方地址 : https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html ...

  9. CRMEB系统就是集客户关系管理+营销电商系统,能够真正帮助企业基于微信公众号、小程序实现会员管理、数据分析,精准营销的电子商务管理系统。可满足企业新零售、批发、分销、等各种业务需求。

    **可以快速二次开发的开源小程序商城系统源码**源码开源地址:https://github.crmeb.net/u/LXT 项目介绍: CRMEB系统就是集客户关系管理+营销电商系统,能够真正帮助企业 ...

随机推荐

  1. linux内核分析作业6:分析Linux内核创建一个新进程的过程

    task_struct结构: struct task_struct {   volatile long state;进程状态  void *stack; 堆栈  pid_t pid; 进程标识符  u ...

  2. NEsper Nuget包

    Esper是专门进行复杂事件处理(CEP)的流处理平台,Java版本为Esper,.Net版本为NEsper.Esper & NEsper可以方便开发者快速开发部署处理大容量消息和事件的应用系 ...

  3. ABP理论学习之MVC视图

    返回总目录 本篇目录 介绍 AbpWebViewPage基类 介绍 ABP通过Abp.Web.Mvc Nuget包集成了MVC视图.因此你可以像常规那样创建MVC视图. AbpWebViewPage基 ...

  4. 使用VS2013分析DMP文件

    当一个发布的.NET应用程序出现app crash,无法通过日志分析异常原因时,就需要通过分析DMP文件了,传统方式是通过WinDbg来分析DMP文件,但是WinDbg用起来不是很方便,其实VS就是一 ...

  5. Linux 挂载管理(mount)

    标签:mount,umount 概述 在上一章增加linux操作系统空间中已经使用过了mount命令对分区进行挂载,这一章详细介绍挂载管理,该命令涉及的知识点也挺多的而且也还比较重要,是需要掌握的一个 ...

  6. SQL Server 数据库镜像

    标签:SQL SERVER/MSSQL SERVER/数据库/DBA/镜像 概述 本章内容主要讲述数据库镜像的安装,安装环境是在域环境下进行安装. 环境:SQL Server 2008 r2 企业版 ...

  7. 记录Office Add-in开发经验

    原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com 得益于微软系强大的共通能力和Visual Studio的开发支持,做Office插件不是什么难事.一点经验记录如下 ...

  8. 学习scala03 控制结构

    scala拥有非常宽松的控制结构. if与while scala中的if和while几乎和java中的结构一模一样. //if语句 val a= ){ println(“”) }else{ print ...

  9. 小型文件数据库 (a file database for small apps) SharpFileDB

    小型文件数据库 (a file database for small apps) SharpFileDB For english version of this article, please cli ...

  10. 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递

    通过第一天的学习之后,我们相信您已经对MVC有一些基本了解. 本节所讲的内容是在上节的基础之上,因此需要确保您是否掌握了上一节的内容.本章的目标是在今天学习结束时利用最佳实践解决方案创建一个小型的MV ...