使用Nancy.Host实现脱离iis的Web应用
本篇将介绍如何使用Nancy.Host实现脱离iis的Web应用,在开源任务管理平台TaskManagerV2.0代码里面已经使用了Nancy.Host实现自宿主的Web应用。学习Nancy之前最好了解一下ASP.NET MVC,因为Nancy和MVC实在是太相似了。
阅读目录
Nancy介绍
Nancy是一个轻量级的用来创建基于HTTP的服务的框架,该框架的可以运行在.net或者mono上。 Nancy处理和mvc类似的DELETE
, GET
, HEAD
, OPTIONS
, POST
, PUT,
PATCH请求,如果你有mvc开发的经验相信可以快速入门。最重要的一点可以让你的Web应用脱离IIS的束缚。
public class Module : NancyModule
{
public Module()
{
Get["/greet/{name}"] = x => {
return string.Concat("Hello ", x.name);
};
}
}
特征
- 自底向上全套都是新构建的,移除了对其他框架的引用和限制。
- Run anywhere. Nancy 能够在ASP.NET/IIS,OWIN,Self-hosting中运行。
- 集成支持各种View engine(Razor, Spark, dotLiquid, SuperSimpleViewEngine...)
资源
Github:https://github.com/NancyFx/Nancy 官网:http://nancyfx.org 使用介绍:http://liulixiang1988.github.io/nancy-webkuang-jia.html
创建第一个应用
1.创建控制台程序,引用相关Package
使用Nuget安装Nancy,Nancy.Hosting.Self,Nancy.Viewengines.Razor,Newtonsoft.Json四个Package
2.监听端口
class Program
{
static void Main(string[] args)
{
try
{
int port = ;
string url = string.Format("http://localhost:{0}", port);
var _host = new NancyHost(new Uri(url));
_host.Start();
Process.Start(url);
Console.WriteLine("站点启动成功,请打开{0}进行浏览",url);
}
catch (Exception ex)
{
Console.WriteLine("站点启动失败:"+ex.Message);
}
Console.ReadKey();
}
}
public class HomeModule : NancyModule
{
public HomeModule()
{
//主页
Get["/"] = r =>
{
return Response.AsRedirect("/Home/Index");
}; //主页
Get["/Home/Index"] = r =>
{
return View["index", "测试站点"];
}; ///桌面
Get["/DestTop"] = r =>
{
return View["DestTop"];
};
}
}
小知识点:Nancy里面的所有控制器都需要继承NancyModule类,类比MVC的控制器都需要继承Controller类
创建视图
新建index.cshtml视图内容如下:
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase @{
ViewBag.Title = @Model;
} @section style{ } 我是第一个Nancy应用 @section scripts{
<script> </script>
}
至此一个简单的应用完成了,运行项目后你会发现提示找不到视图index,是因为index视图没有拷贝到 bin\Debug目录下,添加视图的时候需要手工设置文件属性->始终复制到输出目录。如果嫌这样设置太麻烦可以采取我后面提供的一种方案。
使用技巧
仅上面这点东西做一个Web应用是完全不够的,下面讲解一下进阶内容和使用小技巧。
1.使用CSS和JS等静态资源
要想在视图里面使用静态资源需要设置允许访问的静态资源类型,通过继承DefaultNancyBootstrapper类重写ConfigureConventions方法
public class CustomBootstrapper : DefaultNancyBootstrapper
{
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
base.ApplicationStartup(container, pipelines); //pipelines.BeforeRequest += ctx =>
//{
// return null;
//}; pipelines.AfterRequest += ctx =>
{
// 如果返回状态吗码为 Unauthorized 跳转到登陆界面
if (ctx.Response.StatusCode == HttpStatusCode.Unauthorized)
{
ctx.Response = new RedirectResponse("/login?returnUrl=" + Uri.EscapeDataString(ctx.Request.Path));
}
else if (ctx.Response.StatusCode == HttpStatusCode.NotFound)
{
ctx.Response = new RedirectResponse("/Error/NotFound?returnUrl=" + Uri.EscapeDataString(ctx.Request.Path));
}
}; pipelines.OnError += Error;
} protected override IRootPathProvider RootPathProvider
{
get { return new CustomRootPathProvider(); }
} /// <summary>
/// 配置静态文件访问权限
/// </summary>
/// <param name="conventions"></param>
protected override void ConfigureConventions(NancyConventions conventions)
{
base.ConfigureConventions(conventions); ///静态文件夹访问 设置 css,js,image
conventions.StaticContentsConventions.AddDirectory("Content");
} protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
//替换默认序列化方式
container.Register<ISerializer, CustomJsonNetSerializer>();
} private dynamic Error(NancyContext context, Exception ex)
{
//可以使用log4net记录异常 ex 这里直接返回异常信息
return ex.Message;
}
}
这里设置的根目录下的Content文件夹下所有文件都可以被访问,我们可以将所有静态资源放在该文件夹下
2.使用视图模版
视图模版使用方式和mvc的一模一样,在视图文件夹下创建_ViewStart.cshtml视图,内容如下
@{
Layout = "/Shared/_Layout.cshtml";
}
_Layout.cshtml里面放置页面公共的内容比如公共css和js,定义相关占位符
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<title>@ViewBag.Title</title>
<link rel="shortcut icon" type="image/x-icon" href="~/Content/Image/favicon.ico">
<link href="~/Content/Css/style.css" rel="stylesheet">
@RenderSection("style", required: false)
</head>
<body>
@RenderBody() <script src="~/Content/Scripts/jquery-1.10.2.min.js"></script>
@RenderSection("scripts", required: false)
</body>
</html>
3.控制器返回JSON值控制
默认Nancy使用的是自己内置的JSON序列化库,个人倾向于使用JSON.NET库。所以通过设置替换成了JSON.NET。在CustomBootstrapper的ConfigureApplicationContainer容器里面替换了序列化库
/// <summary>
/// 使用Newtonsoft.Json 替换Nancy默认的序列化方式
/// </summary>
public class CustomJsonNetSerializer : JsonSerializer, ISerializer
{
public CustomJsonNetSerializer()
{
ContractResolver = new DefaultContractResolver();
DateFormatHandling = DateFormatHandling.IsoDateFormat;
Formatting = Formatting.None;
NullValueHandling = NullValueHandling.Ignore;
} public bool CanSerialize(string contentType)
{
return contentType.Equals("application/json", StringComparison.OrdinalIgnoreCase);
} public void Serialize<TModel>(string contentType, TModel model, Stream outputStream)
{
using (var streamWriter = new StreamWriter(outputStream))
using (var jsonWriter = new JsonTextWriter(streamWriter))
{
Serialize(jsonWriter, model);
}
} public IEnumerable<string> Extensions { get { yield return "json"; } }
}
4.返回文件
Get["/Home/Download"] = r =>
{
string path = AppDomain.CurrentDomain.BaseDirectory+@"\Content\UpFile\使用说明.docx";
if (!File.Exists(path))
{
return Response.AsJson("文件不存在,可能已经被删除!");
}
var msbyte = default(byte[]);
using (var memstream = new MemoryStream())
{
using (StreamReader sr = new StreamReader(path))
{
sr.BaseStream.CopyTo(memstream);
}
msbyte = memstream.ToArray();
} return new Response()
{
Contents = stream => { stream.Write(msbyte, , msbyte.Length); },
ContentType = "application/msword",
StatusCode = HttpStatusCode.OK,
Headers = new Dictionary<string, string> {
{ "Content-Disposition", string.Format("attachment;filename={0}", HttpUtility.UrlPathEncode(Path.GetFileName(path))) },
{"Content-Length", msbyte.Length.ToString()}
}
};
};
rd/s/q $(TargetDir)Content
rd/s/q $(TargetDir)Views
xcopy $(ProjectDir)\Content\*.* $(TargetDir)Content\ /s/d/r/y
xcopy $(ProjectDir)\Views\*.* $(TargetDir)Views\ /s/d/r/y
总结
本篇要介绍的内容到此结束了,源代码下载地址:http://files.cnblogs.com/files/yanweidie/NancyConsole.rar,更多关于Nancy的使用可以下载TaskManager源码进行研究http://code.taobao.org/svn/TaskManagerPub/Branch。下一篇介绍如何使用MEF实现通用的参数配置管理。
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】按钮。
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【关注我】。
因为,我的写作热情也离不开您的肯定支持。
感谢您的阅读,如果您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是焰尾迭 。
使用Nancy.Host实现脱离iis的Web应用的更多相关文章
- 用Owin Host实现脱离IIS跑Web API单元测试
开发笔记:用Owin Host实现脱离IIS跑Web API单元测试 今天在开发一个ASP.NET Web API项目写单元测试时,实在无法忍受之前的笨方法,决定改过自新. 之前Web API的单 ...
- 开发笔记:用Owin Host实现脱离IIS跑Web API单元测试
今天在开发一个ASP.NET Web API项目写单元测试时,实在无法忍受之前的笨方法,决定改过自新. 之前Web API的单元测试需要进行以下的操作: 初始配置: 1)在IIS中创建一个站点指定We ...
- PCB 脱离IIS的Web应用
在用.net Web编程中,我们写好的Web应用首选会挂在IIS上面,因为它足稳定并且功能齐全,但这不是我们唯一的选择,微软给我们提供了Owin组件,Web应该的宿主可以不再是IIS了,有了Owin后 ...
- Nancy.Host的Web应用
Nancy.Host实现脱离iis的Web应用 本篇将介绍如何使用Nancy.Host实现脱离iis的Web应用,在开源任务管理平台TaskManagerV2.0代码里面已经使用了Nancy.Host ...
- Getting Started with OWIN and Katana(Console 代替iis 制作 web服务的简单方案)
Open Web Interface for .NET (OWIN) defines an abstraction between .NET web servers and web applicati ...
- IIS 7 Web服务器上部署ASP.NET网站(转)
IIS 7 Web服务器上部署ASP.NET网站小记 摘自:http://swanmsg.blog.sohu.com/162111073.html 网上查找了很久关于iis7配置asp.net配置问题 ...
- vs2015 无法启动IIS Express Web服务器
今天在VS2015上装了 之后无法启动IIS Express Web服务器. 然后我去查看了windows日志发现vs创建的虚拟目录不见了(至于是不是以上原因导致的没去查明) 然后在vs2015中点击 ...
- VS2013无法启动IIS Express Web的解决办法
关于 ASP.NET Web 开发服务器.本地 IIS和 IIS Express 的区别,请参见<VS2013无法启动IIS Express Web的解决办法>, 此文章最后提到的部分,即 ...
- 以Self Host的方式来寄宿Web API
Common类及实体定义.Web API的定义请参见我的上一篇文章:以Web Host的方式来寄宿Web API. 一.以Self Host寄宿需要新建一个Console控制台项目(SelfHost) ...
随机推荐
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(23)-设置角色遗留问题和为权限设置角色以及EasyUI Tabs的使用
ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) (1):框架搭建 (2):数据库访问层的设计Demo (3):面向接口编程 (4 ):业务逻辑层的封装 ...
- 中文字体font-family常用列表
Windows的一些: 黑体:SimHei 宋体:SimSun 新宋体:NSimSun 仿宋:FangSong 楷体:KaiTi 仿宋_GB2312:FangSong_GB2312 楷体_GB2312 ...
- js instanceof
a instanceof b: 1,首先a不是对象,返回false,b的原型不是对象抛出TypeError 2,取得b的prototype标记为bp,对a的原型链做循环,令ap为当前原型,如果ap与b ...
- Android中GridView通过自定义适配器(未优化)实现图文视图排列
Android中GridView组件用来以网格方式排列视图,与矩阵类似,当屏幕上有很多元素(文字.图片或其他元素)需要显示时,可以使用该组件.下面我们通过代码实现如下图例(为了方便截图,将事件处理(土 ...
- AFNetworking 3.0 断点续传 使用记录
最近项目中用到了压缩包下载,使用AFNetworking 3.0 下载压缩包 支持断点续传 代码如下: #import "HDInternet_handler.h" #import ...
- iOS 学习 - 22 异步解析 JSON,使用 FMDB 存储,TableView 显示
前提是已经知道了有哪些 key 值 Model 类: .h @interface ListModel : NSObject @property (nonatomic, copy)NSString *t ...
- TFS源代码管理原则
1.工作开始初次打开解决方案是应向服务器请求更新代码.2.工作结束时,应向服务器签入最新代码,并保证解决方案能够编译通过.3.不要长时间签出项目或解决方案,当向项目添加新项目后为编辑任何程序代码时,应 ...
- SQL SERVER 2008:内部查询处理器错误: 查询处理器在执行过程中遇到意外错误
今天一个同事突然告诉我,以前跑得很正常的一个SQL语句,执行时突然报如下错误: 消息1222,级别16,状态18,第1 行 已超过了锁请求超时时段. ...
- MySQL Performance-Schema(一) 配置篇
performance-schema最早在MYSQL 5.5中出现,而现在5.6,5.7中performance-Schema又添加了更多的监控项,统计信息也更丰富,越来越有ORACLE-AWR统计信 ...
- ORA-00911: invalid character --- 字符集的问题
网上搜了一遍, 大多数是因为分号( ; ) 的问题. 而我的sql文件是没有分号的, 最后发现是sql文件编码和服务器字符集的差异造成 sql文件怎么都看不出问题,直到在UltraEdit里切换到1 ...