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类似的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 = 9000;
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, 0, 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的Web应用的更多相关文章

  1. 使用Nancy.Host实现脱离iis的Web应用

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

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

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

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

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

  4. .NET的微型Web框架 Nancy

    .NET的微型Web框架 Nancy .NET的微型Web框架 Nancy   大部分微软平台的开发人员如果选择开发框架只能是在ASP.NET WEBFORM和ASP.NET MVC两个之间选择. 而 ...

  5. 在Linux中运行Nancy应用程序

    最近在研究如何将.NET应用程序移植到非Windows操作系统中运行,逐渐会写一些文章出来.目前还没有太深的研究,所以这些文章大多主要是记录我的一些实验. 这篇文章记录了我如何利用NancyFx编写一 ...

  6. Nancy之基于Nancy.Hosting.Aspnet的小Demo

    近来学习了一下Nancy这个框架,感觉挺好用的,就写篇简单的文章记录一下大致用法,由于是刚接触,写的代码 可能不规范,也没有具体的分层..莫吐槽... Nancy的官网:http://nancyfx. ...

  7. .NET轻量级MVC框架:Nancy入门教程(二)——Nancy和MVC的简单对比

    在上一篇的.NET轻量级MVC框架:Nancy入门教程(一)——初识Nancy中,简单介绍了Nancy,并写了一个Hello,world.看到大家的评论,都在问Nancy的优势在哪里?和微软的MVC比 ...

  8. Nancy和MVC的简单对比

    Nancy和MVC的简单对比 在上一篇的.NET轻量级MVC框架:Nancy入门教程(一)——初识Nancy中,简单介绍了Nancy,并写了一个Hello,world.看到大家的评论,都在问Nancy ...

  9. [转]NancyFx/Nancy

    本文转自:https://github.com/NancyFx/Nancy/wiki/Documentation Getting Started Introduction Exploring the ...

随机推荐

  1. iOS-响应上下左右滑动手势

    -(void)viewDidLoad{ UISwipeGestureRecognizer *recognizer; recognizer = [[UISwipeGestureRecognizer al ...

  2. saltstack:使用教程之二高级模块用法Grains、Pillar

    1.grains用法: 在客户端服务启动的时候收集客户的基础信息,在配置发生变化后也可以通过master重新同步 显示一个客户端的所有项目: [root@node5 ~]# salt "no ...

  3. mockito中两种部分mock的实现,spy、callRealMethod

    什么是类的部分mock(partial mock)?A:部分mock是说一个类的方法有些是实际调用,有些是使用mockito的stubbing(桩实现). 为什么需要部分mock? A:当需要测试一个 ...

  4. Android应用之基本的组件(一)

    请大家伙多多指教: 邮箱:weimingweicom@sina.com 请关注:ailiandeziwei 总的页面: 注意:按钮间方法的改变需要:     android:onClick=" ...

  5. Python 对Twitter中指定话题的被转载Tweet数量的频谱分析

    CODE: #!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on 2014-7-10 @author: guaguastd @name: r ...

  6. EF架构使用随机排序

    c#当中,可以用Random类来获取随机数 EF当中,我们写Linq时,抑或是采用Linq的扩展方法时,发现都没有随机排序的方法,这就要求我们自己去扩展了 引用自http://www.cnblogs. ...

  7. 软件下载网(包括MAC软件大全)

    http://www.ddooo.com/ MAC软件大全: http://www.ddooo.com/apple/15_5_1.htm

  8. Docker学习笔记(1) — docker 常用命令

    1. docker version显示 Docker 版本信息.2. docker info显示 Docker 系统信息,包括镜像和容器数.3. docker searchdocker search ...

  9. linux下抓取网页快照

    1.下载 https://code.google.com/p/wkhtmltopdf/downloads/detail?name=wkhtmltoimage-0.11.0_rc1-static-i38 ...

  10. HDU 4882 ZCC Loves Codefires(贪心)

     ZCC Loves Codefires Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...