本篇将介绍如何使用Nancy.Host实现脱离iis的Web应用,在开源任务管理平台TaskManagerV2.0代码里面已经使用了Nancy.Host实现自宿主的Web应用。学习Nancy之前最好了解一下ASP.NET MVC,因为Nancy和MVC实在是太相似了。

阅读目录

Nancy介绍

Nancy是一个轻量级的用来创建基于HTTP的服务的框架,该框架的可以运行在.net或者mono上。 Nancy处理和mvc类似的DELETEGETHEADOPTIONSPOSTPUT,PATCH请求,如果你有mvc开发的经验相信可以快速入门。最重要的一点可以让你的Web应用脱离IIS的束缚。

public class Module : NancyModule
{
public Module()
{
Get["/greet/{name}"] = x => {
return string.Concat("Hello ", x.name);
};
}
}

特征

  1. 自底向上全套都是新构建的,移除了对其他框架的引用和限制。
  2. Run anywhere. Nancy 能够在ASP.NET/IIS,OWIN,Self-hosting中运行。
  3. 集成支持各种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();
}
}                                                                                                                        
   3.创建模块和视图
  我们这里使用Razor视图引擎,熟悉MVC的应该很清楚怎么使用这里只做简单演示
  新建控制器文件夹Modules,视图文件夹Views
 
 创建控制器
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()}
}
};
};
    5.视图找不到解决方案
   由于需要将视图文件和静态资源文件拷贝到bin目录下除了设置文件生成属性还可以通过项目生成后事件解决
   
批处理脚本如下
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应用的更多相关文章

  1. 用Owin Host实现脱离IIS跑Web API单元测试

    开发笔记:用Owin Host实现脱离IIS跑Web API单元测试   今天在开发一个ASP.NET Web API项目写单元测试时,实在无法忍受之前的笨方法,决定改过自新. 之前Web API的单 ...

  2. 开发笔记:用Owin Host实现脱离IIS跑Web API单元测试

    今天在开发一个ASP.NET Web API项目写单元测试时,实在无法忍受之前的笨方法,决定改过自新. 之前Web API的单元测试需要进行以下的操作: 初始配置: 1)在IIS中创建一个站点指定We ...

  3. PCB 脱离IIS的Web应用

    在用.net Web编程中,我们写好的Web应用首选会挂在IIS上面,因为它足稳定并且功能齐全,但这不是我们唯一的选择,微软给我们提供了Owin组件,Web应该的宿主可以不再是IIS了,有了Owin后 ...

  4. Nancy.Host的Web应用

    Nancy.Host实现脱离iis的Web应用 本篇将介绍如何使用Nancy.Host实现脱离iis的Web应用,在开源任务管理平台TaskManagerV2.0代码里面已经使用了Nancy.Host ...

  5. 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 ...

  6. IIS 7 Web服务器上部署ASP.NET网站(转)

    IIS 7 Web服务器上部署ASP.NET网站小记 摘自:http://swanmsg.blog.sohu.com/162111073.html 网上查找了很久关于iis7配置asp.net配置问题 ...

  7. vs2015 无法启动IIS Express Web服务器

    今天在VS2015上装了 之后无法启动IIS Express Web服务器. 然后我去查看了windows日志发现vs创建的虚拟目录不见了(至于是不是以上原因导致的没去查明) 然后在vs2015中点击 ...

  8. VS2013无法启动IIS Express Web的解决办法

    关于 ASP.NET Web 开发服务器.本地 IIS和 IIS Express 的区别,请参见<VS2013无法启动IIS Express Web的解决办法>, 此文章最后提到的部分,即 ...

  9. 以Self Host的方式来寄宿Web API

    Common类及实体定义.Web API的定义请参见我的上一篇文章:以Web Host的方式来寄宿Web API. 一.以Self Host寄宿需要新建一个Console控制台项目(SelfHost) ...

随机推荐

  1. JS操作未跨域iframe里的DOM

    这里简单说明两个方法,都是未跨域情况下在index.html内操作b.html内的 DOM. 如:index.html内引入iframe,在index内如何用JS操作iframe内的DOM元素? 先贴 ...

  2. javascript如何设置DIV背景色为随机色

    随机色有两种格式: 效果预览:http://wjf444128852.github.io/DEMOLIST/JS/test/index.html 1.rgb(xxx,xxx,xxx) 2.#xxxxx ...

  3. vue+ vue-router + webpack 踩坑之旅

    说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案   老司机可以忽略下面的内容了 1)起因  考虑到数据分离的问题  因为server是express搭的   自然少 ...

  4. O365(世纪互联)SharePoint 之文档库使用小记

    前言 当O365越来越流行的时候,大家往往更多使用的是传统的Office功能,有太少订阅用户能触及到O365的一个非常棒的功能,叫做SharePoint online. 下面,我们就以图文并茂的方式, ...

  5. iOS 学习 - 22 异步解析 JSON,使用 FMDB 存储,TableView 显示

    前提是已经知道了有哪些 key 值 Model 类: .h @interface ListModel : NSObject @property (nonatomic, copy)NSString *t ...

  6. CocoaPods安装及使用详情

    CocoaPods是什么? 当你开发iOS应用时,会经常使用到很多第三方开源类库,比如JSONKit,SDWebImage等等.可能某个类库又用到其他类库,所以要使用它,必须得另外下载其他类库,而其他 ...

  7. ajax参数设置略解

    通过ajax可以直接由页面访问到服务器.做到不刷新页面,就能刷新数据,为开发带来很大的便利. 1.ajax方式的参数及其功能: $.ajax({ type : "POST", // ...

  8. CRLF line terminators导致shell脚本报错:command not found

    Linux和Windows文本文件的行结束标志不同.在Linux中,文本文件用"/n"表示回车换行,而Windows用"/r/n"表示回车换行.有时候在Wind ...

  9. SQL SERVER如何通过SQL语句获服务器硬件和系统信息

    在SQL SERVER中如何通过SQL语句获取服务器硬件和系统信息呢?下面介绍一下如何通过SQL语句获取处理器(CPU).内存(Memory).磁盘(Disk)以及操作系统相关信息.如有不足和遗漏,敬 ...

  10. Linq专题之提高编码效率—— 第一篇 Aggregate方法

    我们知道linq是一个很古老的东西,大家也知道,自从用了linq,我们的foreach少了很多,但有一个现实就是我们在实际应用中使用到的却是屈指可数 的几个方法,这个系列我会带领大家看遍linq,好的 ...