Nancy之静态文件处理
今天我们来谈谈Nancy中的静态文件(JavaScript,CSS等)该如何处理。
在前面的Demo中,我们也已经用到了这一块的内容,
但并没有深入理解,只是停留在使用的层面上。
在进入今天的正题之前,我们先来简单看看我们熟悉的ASP.NET MVC中是如何管理我们项目中的这些静态文件呢?
其实当我们新建一个MVC的项目时,已经生成了一个“模板”让我们参考,
这个“模板”就是App_Start下面的 BundleConfig.cs
public class BundleConfig
{
// For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));
// Use the development version of Modernizr to develop with and learn from. Then, when you're
// ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
}
}
其中的ScriptBundle和StyleBundle分别是用于管理js和css的类,这两个类都是继承了Bundle这个类!
它位于System.Web.Optimization程序集,如果想要用这个功能,记得添加引用喔!
那我们要怎么使用这个呢?
现在假设在根目录下面有css和js两个文件夹,里面分别存放着Style1.css、Style2.css和js1.js、js2.js
下面就来看看怎么把它交于Bundle管理
bundles.Add(new ScriptBundle("~/bundles/js").Include(
"~/js/js1.js",
"~/js/js2.js"));
bundles.Add(new StyleBundle("~/bundles/css").Include(
"~/css/Style1.css",
"~/css/Style2.css"));
@Styles.Render("~/bundles/css")
@Scripts.Render("~/bundles/js")
是不是很方便呢!更多关于Bundle的内容可以参考
因为它不是我们今天的主要内容,只是拿来与Nancy中的静态文件处理形成对比,便于我们的理解。
下面就来看看Nancy中的静态文件怎么处理。
为了演示的方便,这里仅使用css。
先看看具体的使用,然后再简单分析其内部的实现。
一、新建一个空的asp.net应用程序
在这个应用程序中添加我们需要的引用,这里可以根据前面介绍的,
按自己喜欢的方式、方法来添加Nancy相关的引用
二、建立Modules
老规矩:Modules文件夹、HomeModule.cs
public class HomeModule : NancyModule
{
public HomeModule()
{
Get["/"] = _ =>
{
return View["index"];
}; Get["/default"] = _ =>
{
return View["default"];
}; Get["/custom"] = _ =>
{
return View["custom"];
}; Get["/other"] = _ =>
{
return View["other"];
}; Get["/sub"] = _ =>
{
return View["sub"];
};
}
}
三、新建content、assets、other三个文件夹,以及在assets文件夹下面新建一个sub文件夹用于存放样式表
四、分别添加一些简单的样式在这些文件夹中
content下面的sytle.css内容如下
body {background-color:#00ffff;}
p {font-size:xx-large; }
assets和other下面的style.css内容如下
body {background-color:#00ffff;}
p {font-size:xx-large;color:#ff0000;}
assets/sub下面 的style.css内容如下
body {background-color:#808080;}
p {font-size:xx-large;color:#ff0000;}
五、添加Views
老规矩:Views文件夹、Home文件夹
添加 index.html、default.html、custom.html、other.html、sub.html 五个页面
<!DOCTYPE html>
<html>
<head>
<title>index</title>
<meta charset="utf-8" />
</head>
<body>
<a href="/default">page with default convention</a><br />
<a href="/custom">page with custom convention</a><br />
<a href="/other">page without custom convention</a><br />
<a href="/sub">page sub</a>
</body>
</html>
index.html
<!DOCTYPE html>
<html>
<head>
<title>default</title>
<meta charset="utf-8" />
<link href="../../content/style.css" rel="stylesheet" />
</head>
<body>
<p>这是引用 /content/sytle.css 的页面(默认的convention配置)</p>
</body>
</html>
default.html
<!DOCTYPE html>
<html>
<head>
<title>custom</title>
<meta charset="utf-8" />
<link href="../../assets/style.css" rel="stylesheet" />
</head>
<body>
<p>这是引用 /assets/style.css 的页面(自定义Convention配置)</p>
</body>
</html>
custom.html
<!DOCTYPE html>
<html>
<head>
<title>other</title>
<meta charset="utf-8" />
<link href="../../other/style.css" rel="stylesheet" />
</head>
<body>
<p>这是引用 /other/style.css 的页面(没有Convention配置)</p>
</body>
</html>
other.html
<!DOCTYPE html>
<html>
<head>
<title>sub</title>
<meta charset="utf-8" />
<link href="../../assets/sub/style.css" rel="stylesheet" />
</head>
<body>
<p>这是引用 /assets/sub/style.css 的页面(自定义Convention配置,子文件夹测试)</p>
</body>
</html>
sub.html
六、在"引导程序"中配置Convention(至关重要的一步)
新建DemoBootstrapper.cs,使其继承DefaultNancyBootstrapper并且override我们的ConfigureConventions
public class DemoBootstrapper : DefaultNancyBootstrapper
{
protected override void ConfigureConventions(NancyConventions nancyConventions)
{
base.ConfigureConventions(nancyConventions);
nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("assets"));
}
}
七、运行结果
八、结果分析与探讨
1、default.html 用的样式是在content下面的,能正常加载样式!
2、custom.html用的样式是在assets下面的,能正常加载样式!
3、other.html用的样式是在other下面的,不能正常加载样式!!
4、sub.html用的样式是在assets/sub下面的,能正常加载样式!
很明显,结果有点出乎我们的意料,我们在Convetion的配置中,只配置了一项!
就是对assets文件夹进行了处理。其他都没有手动配置!
但是在content下面的样式是能够正常显示的!!而other下面的是不能正常显示的!!assets的子文件夹sub的样式也正常显示!!
这个给人貌似不是很合理的感觉。
看看Network的内容会发现other下面的样式表不是不能正常加载那么简单,而是直接给个404!!!
那我们就深入的去看看这里面到底发生了什么事吧!
fork一份Nancy的源码,clone到本地,来看看个所以然。(其实上面的例子我就是在源码上面添加的一个Demo)
首先看看我们今天的主题Conventions下面的东西
其中从名字就可以看出跟我们今天的主题静态文件,相关的就有7个!!
但这并不是我们的出发点,我们的出发点是下面这个!
protected override void ConfigureConventions(NancyConventions nancyConventions)
{
base.ConfigureConventions(nancyConventions);
nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("assets"));
}
Convention的配置指引着我们要先去看看NancyConvetions这个类
在其构造方法中调用了 BuildDefaultConventions 这个方法
/// <summary>
/// Initializes a new instance of the <see cref="NancyConventions"/> class.
/// </summary>
public NancyConventions()
{
this.BuildDefaultConventions();
}
这就很明显的告诉我们,无论如何,它都会有默认的Conventions!!而且看了里面的实现
会发现,默认的Convention还不仅仅是一个!!而是包含多个。这里我们仅探讨关于静态文件的。
private void BuildDefaultConventions()
{
var defaultConventions =
AppDomainAssemblyTypeScanner.TypesOf<IConvention>(ScanMode.OnlyNancy);
this.conventions = defaultConventions
.Union(AppDomainAssemblyTypeScanner.TypesOf<IConvention>(ScanMode.ExcludeNancy))
.Select(t => (IConvention)Activator.CreateInstance(t));
foreach (var convention in this.conventions)
{
convention.Initialise(this);
}
}
现在我们就该去找关于静态文件的默认Convetion
发现刚才的7个相关中,有一个DefaultStaticContentsConventions
它实现了IConvention接口(Nancy中基本都是接口化编程,很Nice!!)。
其中的初始化方法中
public void Initialise(NancyConventions conventions)
{
conventions.StaticContentsConventions = new List<Func<NancyContext, string, Response>>
{
StaticContentConventionBuilder.AddDirectory("Content")
};
}
是不是跟我们自定义配置几乎相差无几!!我想看到AddDirectory的参数"Content",大家也应该都知道了
为什么我们的content下面的样式,没有配置都能正常加载(我去,它默认都是content,能不正常加载么。。)
里面的StaticContentConventionBuilder又是何方神圣呢?
这个是静态基于目录的帮助类
里面有两个主要的方法 AddDirectory和AddFile ,都是返回Func<NancyContext, string, Response>类型的东东。
看名字都已经知道大概实现了什么东西,一个基于某个目录,一个基于某个单独的文件。
这里需要注意一下这两个方法的参数!
还有一些其他的东西是用于拼接目录和处理Cache的。
把这几个重要的类看了一下,是不是对这个静态文件的默认配置也清晰了不少呢?
然后对自定义Convetion配置的理解也是类似的,所以这里就不再累赘了。
从"引导程序"的ConfigureConventions中可以知道,无论我们自定义多少个Convetion,
都是要添加到StaticContentsConventions这个集合中的。
九、简单总结
ConfigureConventions 与 BundleConfig 都是用于处理静态文件的,有相同之处,也有各自的特点。
在项目开发过程中,我们可能会根据习惯把css、javascript这些静态文件放在自己喜欢的位置,
但是在Nancy中这个的处理需要十分注意的是,只要我们没有将css和javascript文件放在content中时,就一定要记得在Convention中进行配置!
否则页面死活不是我们期待的那样。。。。
所以我个人感觉这块内容不是很友好,一旦不小心忘了配置,而且发现页面样式不对,首先想到的是不是样式的路径写错了
而不会直接考虑到Nancy的Convention配置这一层面。
为此,提醒各位使用Nancy的朋友,并建议各位:只要您的项目用到了静态文件,请务必要override我们的ConfigureConventions !!
Nancy之静态文件处理的更多相关文章
- ASP.NET Core应用针对静态文件请求的处理[5]: DefaultFilesMiddleware中间件如何显示默认页面
DefaultFilesMiddleware中间件的目的在于将目标目录下的默认文件作为响应内容.我们知道,如果直接请求的就是这个默认文件,那么前面介绍的StaticFileMiddleware中间件会 ...
- ASP.NET Core应用针对静态文件请求的处理[4]: DirectoryBrowserMiddleware中间件如何呈现目录结构
和StaticFileMiddleware中间件一样,DirectoryBrowserMiddleware中间本质上还是定义了一个请求地址与某个物理目录之间的映射关系,而目标目录体现为一个FilePr ...
- ASP.NET Core应用针对静态文件请求的处理[3]: StaticFileMiddleware中间件如何处理针对文件请求
我们通过<以Web的形式发布静态文件>和<条件请求与区间请求>中的实例演示,以及上面针对条件请求和区间请求的介绍,从提供的功能和特性的角度对这个名为StaticFileMidd ...
- ASP.NET Core应用针对静态文件请求的处理[2]: 条件请求与区间请求
通过调用ApplicationBuilder的扩展方法UseStaticFiles注册的StaticFileMiddleware中间件帮助我们处理针对文件的请求.对于StaticFileMiddlew ...
- ASP.NET Core应用针对静态文件请求的处理[1]: 以Web的形式发布静态文件
虽然ASP.NET Core是一款"动态"的Web服务端框架,但是在很多情况下都需要处理针对静态文件的请求,最为常见的就是这对JavaScript脚本文件.CSS样式文件和图片文件 ...
- IIS7禁用单个静态文件的缓存配置方法
IIS7中,想将一个经常修改的静态文件设置为不可缓存,在IIS配置界面里怎么也找不到... 一番google之后在stackoverflow里边发现了这样一段回答,最终解决了问题: just stum ...
- ASP.NET Core 中文文档 第三章 原理(3)静态文件处理
原文:Working with Static Files 作者:Rick Anderson 翻译:刘怡(AlexLEWIS) 校对:谢炀(kiler398).许登洋(Seay).孟帅洋(书缘) 静态文 ...
- ASP.NET Core 静态文件及JS包管理器(npm, Bower)的使用
在 ASP.NET Core 中添加静态文件 虽然ASP.NET主要大都做着后端的事情,但前端的一些静态文件也是很重要的.在ASP.NET Core中要启用静态文件,需要Microsoft.AspNe ...
- 来玩Play框架07 静态文件
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Play框架的主要功能是提供动态响应的内容.但一个网络项目中必然有大量的静态内容, ...
随机推荐
- 标准数据源访问库 - JayData
JayData 是一个标准的.跨平台的库和方法,用于访问和操作各种不同的数据源,最适合用于 JavaScript 和 HTML5 应用. 官方网站:http://jaydata.org/ ASP.N ...
- Nova PhoneGap框架 第八章 滚动条
你可能会疑惑为什么滚动条这么常见的功能会在这里单独列出,但如果你有过PhoneGap开发经验的话,你就会发现要在Android 2.3 里面实现滚动条那真不是一件容易的事. 8.1 概述 目前主流的P ...
- C#温故知新:《C#图解教程》读书笔记系列
一.此书到底何方神圣? 本书是广受赞誉C#图解教程的最新版本.作者在本书中创造了一种全新的可视化叙述方式,以图文并茂的形式.朴实简洁的文字,并辅之以大量表格和代码示例,全面.直观地阐述了C#语言的各种 ...
- [Voice communications] 声音的滤波
本系列文章主要是介绍 Web Audio API 的相关知识,以及 web语音通信 中会遇到的一些问题,阐述可能存在错误,还请多多斧正! 通过设备获取音频流会不可避免的渗入一些杂音,这些杂音可能来自你 ...
- 人生苦短,我用python——当我在玩python的时候我玩些什么
文章背景 家里的第一台电脑是在2006年夏天买的,10年上大学之后基本上就没人用,过没两年就当二手卖给一个熟人. 弟弟小我10岁,今年刚上初一.他在我毕业前半年就整天用妈妈的手机发短信给我,问我什么时 ...
- 学习Cassandra的开源电子书(中英文版)
学习Cassandra的开源电子书(中英文版)发布啦:http://teddymaef.github.io/learncassandra/ 之前发布了英文版,现在包含中文版了. 学习Cassandra ...
- Aspose.Words 16.8 破解版、添加自定义HTML导出Jpeg压缩质量配置
0x01 Aspose.Words 介绍Aspose.Words是一个商业.NET类库,可以使得应用程序处理大量的文件任务.Aspose.Words支持Doc,Docx,RTF,HTML,OpenDo ...
- C语言 · 特殊回文数
问题描述 123321是一个非常特殊的数,它从左边读和从右边读是一样的. 输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n . 输入格式 输入一行,包含一个正整数n. 输 ...
- iOS-提高iOS开发效率的方法和工具
提高iOS开发效率的方法和工具 介绍 这篇文章主要是介绍一下我在iOS开发中使用到的一些可以提升开发效率的方法和工具. IDE 首先要说的肯定是IDE了,说到IDE,Xcode不能跑,当然你也可能同时 ...
- php 操作数组(合并,拆分,追加,查找,删除等)(转载)
1. 合并数组 array_merge()函数将数组合并到一起,返回一个联合的数组.所得到的数组以第一个输入数组参数开始,按后面数组参数出现的顺序依次迫加.其形式为: array array_merg ...