译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 40 章 ASP.NET Core(上)),不对的地方欢迎指出与交流。
章节出自《Professional C# 6 and .NET Core 1.0》。水平有限,各位阅读时仔细分辨,唯望莫误人子弟。
附英文版原文:Professional C# 6 and .NET Core 1.0 - 40 ASP.NET Core
本章节译文分为上下篇,下篇见:C# 6 与 .NET Core 1.0 高级编程 - 40 ASP.NET Core(下)
---------------------------
本章内容
- 了解ASP.NET Core 1.0和Web技术
- 使用静态内容
- 使用HTTP请求和应答
- 使用依赖注入与ASP.NET
- 定义自定义简单路由
- 创建中间件组件
- 使用会话进行状态管理
- 读取配置设置
Wrox.com网站关于本章的源代码下载
本章的wrox.com代码下载位于http://www.wrox.com/go/professionalcsharp6的“下载代码”选项卡上。本章的代码包含此示例项目:WebSampleApp。
ASP.NET Core 1.0
ASP.NET经过15年(译者注:第一个版本的asp.net在2002年2月发布),ASP.NET Core 1.0是一个完全重写的ASP.NET。它具有模块化编程的特征,完全开放源代码,轻量级以便在云平台得到最佳使用,并且可用于非Microsoft平台。
完全重写ASP.NET有很多优点,但这也意味着要重新处理基于ASP.NET的旧版本的现有Web应用程序。是否有必要将现有的Web应用程序重写到ASP.NET Core 1.0?让我们试着回答这个问题。
ASP.NET Web窗体不再是ASP.NET Core 1.0的一部分。然而,拥有包含此技术的Web应用程序并不意味着必须重写它们。仍然可以使用完整的框架来维护使用ASP.NET Web Forms编写的遗留的应用程序。 甚至在最新版本的ASP.NET 4.6 中对ASP.NET Web窗体进行了增强,例如异步模型捆绑。
ASP.NET MVC仍然是ASP.NET Core 1.0的一部分。因为ASP.NET MVC 6已经完全重写,所以您需要对使用ASP.NET MVC 5或更早版本编写的Web应用程序进行一些更改,以将它们带到新的应用程序堆栈。
将ASP.NET Web窗体转换为ASP.NET MVC可能需要做很多工作。 ASP.NET Web窗体从开发者角度抽象出HTML和JavaScript。使用ASP.NET Web窗体,没有必要知道HTML和JavaScript,而是使用带有C#代码的服务器端控件。服务器端控件本身返回HTML和JavaScript。这种编程模型类似于旧的Windows窗体编程模型。使用ASP.NET MVC,开发人员需要知道HTML和JavaScript。 ASP.NET MVC是基于模型 - 视图 - 控制器(MVC)模式,这很容易进行单元测试。因为ASP.NET Web窗体和ASP.NET MVC基于截然不同的架构模式,所以将ASP.NET Web窗体应用程序迁移到ASP.NET MVC是一项巨大的工作。在进行这项任务之前,应该建立一个清单,列出使用解决方案保留旧技术的优点和缺点,并将其与使用新技术的优点和缺点进行比较。ASP.NET Web窗体还可以用来工作多年。
注意 本书编者的网站http://www.cninnoation.com最初是用ASP.NET Web窗体创建的。这个网站已经被转换成早期版本的新技术的ASP.NET MVC。由于原来的网站已经使用了很多独立的组件来抽象数据库和服务代码,它并不算是一个真正的巨大的任务,所以做得非常快。因此能够直接从ASP.NET MVC使用数据库和服务代码。另一方面,如果开始使用Web窗体控件访问数据库而不是使用自定义的控件,这也将是一个繁杂的工作。
注意 本书不包括传统技术的ASP.NET Web窗体。 也不包括ASP.NET MVC 5。本书重点介绍新技术,因此关于Web应用程序,材料基于ASP.NET 5和ASP.NET MVC 6。这些技术应该用于新的Web应用程序。如果需要维护较旧的应用程序,应该阅读比本书更早的版本,如《Professional C#5.0和.NET 4.5.1》,它介绍 ASP.NET 4.5,ASP.NET Web窗体4.5和ASP.NET MVC 5 。
本章介绍了ASP.NET Core 1.0的基础,第41章解释了使用ASP.NET MVC 6,这是一个构建在ASP.NET Core 1.0之上的框架。
Web技术
在本章后面介绍ASP.NET的基础之前,本节将介绍在创建Web应用程序时非常重要的核心Web技术:HTML,CSS,JavaScript和jQuery。
HTML
HTML是由Web浏览器解释的标记语言。它定义元素以显示各种标题、表、列表和输入元素,如文本和组合框。
自2014年10月以来,HTML5一直是W3C的一项建议(http://w3.org/TR/html5),而且所有主流浏览器都提供支持。使用HTML5的功能,很多浏览器插件(例如Flash和Silverlight)已经不需要,因为加载项所做的事情现在可以直接使用HTML和JavaScript完成。当然,您可能仍需要Flash和Silverlight,因为并非所有网站都迁移到新技术,或者用户可能仍在使用不支持HTML5的旧版浏览器版本。
HTML5增加了新的语义元素,搜索引擎能够更好地用于分析网站。画布元素允许动态使用2D形状和图像,视频和音频元素使对象元素过时。最近的媒体源产品(http://w3c.github.io/media-source)自适应流也由HTML提供,以前这是Silverlight的一个优势。
HTML5还定义了用于拖放、存储、Web套接字等的API。
CSS
HTML定义网页的内容,而CSS定义外观。例如在早期的HTML中,列表项标签<li>定义列表元素是否应该显示为圆形,圆盘或正方形。现在这些信息被完全从HTML中删除,而是放入级联样式表(CSS)。
CSS样式可以使用灵活的选择器来选择HTML元素,并且可以为这些元素定义样式。可以通过其ID或其名称选择元素,还可以定义HTML代码内的可被引用的CSS类。对于较新版本的CSS,可以定义比较复杂的规则来选择特定的HTML元素。
从Visual Studio 2015开始,Web项目模板可以使用Twitter Bootstrap。这是一个CSS和HTML约定的集合,可以轻松适应不同的外观和下载即用模板。有关文档和基本模板,请访问www.getbootstrap.com。
JavaScript和TypeScript
并非所有平台和浏览器都可以使用.NET代码,但几乎每个浏览器都支持JavaScript。一个对JavaScript的常见误解是它与Java有关。事实上,只有名称是类似的,因为Netscape(JavaScript的发起者)与Sun(Sun发明Java)达成协议,允许在名称中使用Java。如今,这两家公司已不再存在。 Sun被Oracle收购,现在Oracle持有Java的商标。
Java和JavaScript(和C#)都有相同的根 - C编程语言。 JavaScript是一种不是面向对象的功能性编程语言,尽管它已经添加面向对象的功能。
JavaScript允许从HTML页面访问文档对象模型(DOM),这使得客户端上可以动态更改元素。
ECMAScript是定义JavaScript语言的当前和即将到来的特性的标准。因为其他公司不允许在其语言实现中使用术语Java,所以标准名称为ECMAScript。 Microsoft的JavaScript实现名称是JScript。请查看http://www.ecmascript.org了解JavaScript语言的现状和发展动态。
即使许多浏览器不支持最新的ECMAScript版本,但仍然可以编写ECMAScript 5代码。可以使用TypeScript代替编写JavaScript代码。 TypeScript语法基于ECMAScript,但它具有一些增强功能,例如强类型代码和注释。可以看到C#和TypeScript之间有很多相似之处。因为TypeScript编译器编译为JavaScript,所以TypeScript可以在需要JavaScript的任何地方使用。有关TypeScript的详细信息,请访问http://www.typescriptlang.org。
脚本库
除了JavaScript编程语言,还需要脚本库,来使生活更轻松(译者注:这句话有点调侃的意味)。
- jQuery(http://www.jquery.org)是一个库,它在访问DOM元素并对事件做出反应时抽象出浏览器的差异。
- Angular(http://angularjs.org)是一个基于MVC模式的库,用于简化单页Web应用程序的开发和测试。 (与ASP.NET MVC不同,Angular提供了客户端代码的MVC模式。)
ASP.NET Web项目模板包括jQuery库和Bootstrap。 Visual Studio 2015支持IntelliSense和调试JavaScript代码。
注意 本书中没有介绍为Web应用程序设计样式和编写JavaScript代码。可以在 《HTML和CSS》中阅读更多关于HTML和样式:John Ducket设计和构建网站(Wiley,2011),并通过Nicholas C. Zakas(Wrox,2012)为Web开发人员加快专业JavaScript技术提升。
ASP.NET Web项目
首先创建一个名为WebSampleApp的空ASP.NET Core 1.0 Web应用程序(参见图40.1)。本章从一个空模板开始添加功能。
图40.1
注意通过本章的示例代码下载,需要取消注释启动类中的特定代码块来激活所讨论的功能。也可以从头开始创建项目。没有太多的代码可以看到所有的功能。
创建项目后,将看到一个名为WebSampleApp的解决方案和项目文件,其中包含一些文件和文件夹(参见图40.2)。
图40.2该解决方案包含global.json配置文件,该文件列出解决方案的目录。可以在以下代码段中从“projects”键的值查看此内容。 src目录包含具有源代码的解决方案的所有项目。“test”目录用于定义单元测试,虽然它们还不存在。 sdk设置定义所使用的SDK的版本号(代码文件global.json)。
{
"projects": ["src","test" ],
"sdk": {
"version":"1.0.0-0"
}
}
在项目结构中,使用浏览器打开文件Project_Readme.html时,可以看到有关ASP.NET Core 1.0的一些总体信息。在项目文件夹中可以看到一个“References”文件夹。它包含所有引用的NuGet包。对于一个空的ASP.NET Web应用程序项目,引用的软件包仅有Microsoft.AspNetCore.IISPlatformHandler和Microsoft.AspNetCore.Server.Kestrel。
IISPlatformHandler包含IIS的模块,用于将IIS基础结构映射到ASP.NET Core 1.0。 Kestrel是ASP.NET Core 1.0的一个新的Web服务器,在Linux平台上也可以使用它。
还可以在project.json文件中找到NuGet包的引用。 (在以下代码片段中,它们在“dependencies”部分。)框架部分列出了支持的.NET框架,如net452(.NET 4.5.2)和netstandard1.0(.NET Core 1.0)。可以删除不需要托管的那个。 “exclude”部分列出了不应用于编译应用程序的文件和目录。“publishExclude”部分列出不应发布的文件和文件夹(代码文件WebSampleApp/project.json):
{
"version":"1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"NETStandard.Library":"1.0.0-*",
"Microsoft.AspNetCore.IISPlatformHandler":"1.0.0-*",
"Microsoft.AspNetCore.Server.Kestrel":"1.0.0-*"
},
"frameworks": {
"net452": { },
"netstandard1.0": {
"dependencies": {
"NETStandard.Library":"1.0.0-*"
}
}
},
"content": ["hosting.json" ]
"exclude": [
"wwwroot",
"node_modules"
],
"publishExclude": [
"**.user",
"**.vspscc"
]
}
“项目设置”中的“调试”选项可以配置使用Visual Studio开发时使用的Web服务器(请参见图40.3)。默认情况下,IIS Express使用“调试”设置指定的端口号进行配置。 IIS Express由Internet信息服务器(IIS)派生,并提供IIS的所有核心功能。这样在几乎相同的环境中开发Web应用程序变得容易,在该环境中应用程序将被稍后托管(如果IIS用于托管)。
图40.3
要使用 Kestrel 服务器运行应用程序,可以使用“调试项目”设置选择Web配置文件。Profile选项中的可用选项列表是project.json中列出的命令。
使用Visual Studio项目设置更改的设置会影响launchSettings.json文件的配置。此文件还可以定义一些其他配置,如命令行参数(代码文件WebSampleApp/Properties/launchsettings.json):
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl":"http://localhost:19879/",
"sslPort":
}
},
"profiles": {
"IIS Express": {
"commandName":"IISExpress",
"launchBrowser": true,
"environmentVariables": {
"Hosting:Environment":"Development"
}
},
"web": {
"commandName":"web",
"launchBrowser": true,
"launchUrl":"http://localhost:5000/",
"commandLineArgs":"Environment=Development",
"environmentVariables": {
"Hosting:Environment":"Development"
}
}
}
}
解决方案资源管理器中项目结构中的“Dependencies”文件夹显示JavaScript库的依赖项。 创建空项目时,该文件夹为空。 本章后面的“添加静态内容”部分添加依赖项。
“wwwroot”文件夹是需要发布到服务器的静态文件的文件夹。 目前这个文件夹是空的,但通过这一章,可以添加HTML和CSS文件和JavaScript库。
一个C#源文件 - Startup.cs - 也包括在一个空项目中。 接下来讨论这个文件。在创建项目期间,需要这些依赖项和命名空间:
依赖项
Microsoft.AspNetCore.Http.Abstractions
Microsoft.AspNetCore.IISPlatformHandler
Microsoft.AspNetCore.Server.Kestrel
Microsoft.AspNetCore.StaticFiles
Microsoft.AspNetCore.Session
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.UserSecrets
Microsoft.Extensions.Logging
Microsoft.Extensions.Logging.Console
Microsoft.Extensions.Logging.Debug
Microsoft.Extensions.PlatformAbstractions
Newtonsoft.Json
System.Globalization
System.Text.Encodings.Web
System.Runtime
命名空间
Microsoft.AspNetCore.Builder;
Microsoft.AspNetCore.Hosting;
Microsoft.AspNetCore.Http;
Microsoft.Extensions.Configuration
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Logging
Microsoft.Extensions.PlatformAbstractions
Newtonsoft.Json
System
System.Globalization
System.Linq
System.Text
System.Text.Encodings.Web
System.Threading.Tasks
启动
现在是时候开始从Web应用程序中获得一些功能。 要获取有关客户端的信息并返回响应,需要对HttpContext写一个响应。
在空的ASP.NET Web应用程序模板创建一个启动类,其中包含以下代码(代码文件WebSampleApp/Startup.cs):
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
// etc.
namespace WebSampleApp
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseIISPlatformHandler();
// etc. app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseDefaultConfiguration(args)
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}
Web应用程序的入口点是 Main 方法。之前在project.json配置文件中看到的emitEntryPoint配置可以定义是否应该使用Main方法。还定义了在本书中创建的.NET Core控制台应用程序的Main方法。只有库不需要Main方法。
使用从Visual Studio模板生成的默认实现,Web应用程序在WebHostBuilder实例的帮助下配置。WebHostBuilder将调用UseDefaultConfiguration方法。该方法接收命令行参数并创建包括可选托管文件(hosting.json)的配置,添加环境变量,并将命令行参数添加到配置。方法UseStartup定义使用Startup类,它反过来调用方法ConfigureServices和Configure。WebApplicationBuilder调用的最后一个方法是Build方法,它返回实现接口IWebApplication的对象。返回的应用程序对象调用Run方法,启动托管引擎,现在服务器进入侦听和等待请求状态。hosting.json文件用于配置服务器(代码fileWebSampleApp/hosting.json):
{
"server":"Microsoft.AspNetCore.Server.Kestrel",
"server.urls":"http://localhost:5000"
}
Startup类被传递给具有通用模板参数的UseStartup方法,然后调用ConfigureServices和Configure方法。
Configure方法通过实现接口IApplicationBuilder的依赖注入接收内部应用程序编译器类型。该接口用于定义应用程序使用的服务。调用接口的Use方法,可以创建HTTP请求管道以定义请求的应答要做什么。Run方法是接口IApplicationBuilder的扩展方法,它调用Use方法。该方法在程序集Microsoft.AspNetCore.Http.Abstractions中的RunExtensions扩展类和命名空间Microsoft.AspNetCore.Builder实现。
Run方法的参数是RequestDelegate类型的委托。该类型接收HttpContext作为参数,并返回一个Task。HttpContext(代码片段中的 context 变量)可以访问浏览器中的请求信息(HTTP头,Cookie和表单数据),也可以发送响应。代码片段返回一个简单的字符串 - Hello,World! - 到客户端,如图40.4所示。
图40.4
注意 如果使用Microsoft Edge测试Web应用程序,则需要启用localhost。在地址栏中键入about:flags,并启用“允许本地主机环回”选项(见图40.5)。不仅可以使用Microsoft Edge的内置用户界面来设置此选项,还可以使用命令行选项:实用程序CheckNetIsolation。命令 “CheckNetIsolation LoopbackExempt -a - n = Microsoft.MicrosoftEdge_8wekyb3d8bbwe”启用本地主机类似于为Microsoft Edge使用更友好的用户界面。如果要配置其他Windows应用程序以允许localhost,则实用程序CheckNetIsolation非常有用。
图40.5
将日志信息添加到Web应用程序对获取更多的信息是非常有用的,能够了解发生了什么。为了达到这个目的,Startup 类的Configure方法接收ILoggerFactory对象。该接口可以使用AddProvider方法添加日志提供程序,并使用CreateLogger方法创建一个实现ILogger接口的日志程序。以下代码段中显示的AddConsole和AddDebug方法是用于添加不同提供程序的扩展方法。 AddConsole方法添加一个提供程序负责将日志信息写入控制台,AddDebug方法添加一个提供程序负责将日志信息写入调试程序。这两种方法不传递参数值,默认值用于配置日志消息。默认值指定为写入信息的日志消息类型或者更高级别。可以用不同的重载来指定其他用于记录的过滤项,或者可以使用配置文件配置日志记录(代码文件WebSampleApp/Startup.cs):
public void Configure(IApplicationBuilder app, ILoggerFactory
loggerFactory)
{
// etc.
loggerFactory.AddConsole();
loggerFactory.AddDebug();
// etc.
}
ILogger接口可以在 Log 方法中编写自定义日志信息。
添加静态内容
通常不会只是发送简单的字符串到客户端。 默认情况下,无法发送简单的HTML文件和其他静态内容。 因为ASP.NET 5会尽可能减少开销。 如果不启用它们,不会从服务器返回静态文件。
要启用从Web服务器提供的静态文件,可以添加扩展方法UseStaticFiles(并注释先前创建的Run方法):
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseiISPlatformHandler();
app.UseStaticFiles();
//etc.
}
只要将相同大小写的代码行添加到Configure方法中,编辑器中的智能标记就会添加NuGet包Microsoft.AspNet.StaticFiles。 选中该项,NuGet包下载并在project.json中列出:
"dependencies": {
"Microsoft.AspNetCore.IISPlatformHandler":"1.0.0-*",
"Microsoft.AspNetCore.Server.Kestrel":"1.0.0-*",
"Microsoft.AspNetCore.StaticFiles":"1.0.0-*"
},
添加静态文件的文件夹是项目中的“wwwroot”文件夹。 可以使用webroot设置来配置 project.json 文件中的文件夹的名称。 如果没有配置文件夹,默认是“wwwroot”。 通过添加配置添加NuGet包,可以将HTML文件添加到wwwroot文件夹(代码文件WebSampleApp/wwwroot/Hello.html),如下所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<h1>Hello, ASP.NET with Static Files</h1>
</body>
</html>
启动服务器之后,从浏览器发出对HTML文件的请求,例如 http://localhost:5000/Hello.html 。根据配置,端口号可能因项目而异。
注意 在使用ASP.NET MVC创建Web应用程序时,还需要了解HTML,CSS,JavaScript和一些JavaScript库。由于本书的重点是C#和.NET,这些主题的内容保持在最低限度。编者只是谈及ASP.NET MVC和Visual Studio需要知道的最重要的任务。
使用JavaScript包管理器:npm
对于Web应用程序,通常需要一些JavaScript库。在Visual Studio 2015之前,JavaScript库可用作NuGet包 - 类似于.NET程序集作为NuGet包使用。因为脚本库周围的社区通常不使用NuGet服务器,他们也不创建NuGet包。从Microsoft或Microsoft友好社区为JavaScript库创建NuGet包需要额外的工作。因此JavaScript周围的社区使用具有类似于NuGet的功能的服务器而不是使用NuGet。
节点包管理器(npm)是JavaScript库的包管理器。最初来自Node.Js(用于服务器端开发的JavaScript库),npm对服务器端脚本很强大。然而,越来越多的客户端脚本库也可以与npm一起使用。
Visual Studio 2015 可以通过从项目模板添加NPM配置文件,将npm添加到项目。添加项目模板时,package.json文件将添加到项目中:
{
"version":"1.0.0",
"name":"ASP.NET",
"private":"true",
"devDependencies": {
}
}
在Visual Studio中打开文件后,可以在编辑器中看到npm标志,如图40.6所示。
图40.6
注意 单击“显示所有文件”按钮时,解决方案资源管理器中才会显示package.json文件。
当向此文件的devDependencies部分添加JavaScript库,在键入时将连接npm服务器以允许完成JavaScript库,并显示可用的版本号。在编辑器中选择版本号时,还可以获得^和~的前缀。如果没有前缀,从服务器检索键入的确切名称的库的版本。^前缀检索相同主版本号的最新库,〜前缀检索具有相同次要版本号的最新库。下面的package.json文件引用了几个gulp库和rimraf库。保存package.json文件时,将从服务器加载npm软件包。在解决方案资源管理器中,可以在“依赖关系”部分中查看npm加载的库。 Dependencies部分有一个npm子节点,其中显示所有已加载的库。
{
"version":"1.0.0",
"name":"ASP.NET",
"private":"true",
"devDependencies": {
"gulp":"3.9.0",
"gulp-concat":"2.6.0",
"gulp-cssmin":"0.1.7",
"gulp-uglify":"1.2.0",
"rimraf":"2.4.2"
}
}
这些JavaScript库引用有什么用? gulp是一个编译系统,将在下一节中讨论。 gulp-concat连接JavaScript文件;gulp-cssmin最小化CSS文件;gulp-uglify缩小JavaScript文件;而rimraf允许删除层次结构中的文件,minification 删除所有不必要的字符。
添加软件包后,可以使用解决方案资源管理器中“依赖项”部分中的npm节点轻松地更新或卸载软件包。
使用gulp编译
Gulp是JavaScript的编译系统。npm类似于NuGet,而 gulp 类似于.NET开发实用程序(DNU)。既然 JavaScript代码被解析,为什么还需要一个使用JavaScript的编译系统?在将HTML,CSS和JavaScript这些文件放到服务器上之前,有很多工作要做。编译系统可以将Syntactically Awesome Stylesheets(SASS)文件(具有脚本功能的CSS)转换为CSS,同时可以缩小和压缩文件,还可以启动脚本的单元测试,并且可以分析JavaScript代码(例如, JSHint) - 有很多有用的任务可以做。
用npm添加gulp之后,可以使用Visual Studio项目模板添加"Gulp Configuration File"。此模板创建以下gulp文件(代码文件MVCSampleApp/gulpfile.js):
/*
This file is the main entry point for defining Gulp tasks and using Gulp plugins.
Click here to learn more. http://go.microsoft.com/fwlink/?LinkId=518007
*/
var gulp = require('gulp');
gulp.task('default', function () {
// place code for your default task here
});
带有gulp标志的编辑器如图40.7所示。
图40.7
现在在gulp文件中添加一些任务。 第一行定义此文件的所需库,并将变量分配给脚本。 这里已经添加了npm的库被会使用。 gulp.task函数创建gulp任务,可以使用Visual Studio任务运行器浏览器启动:
"use strict";
var gulp = require("gulp"),
rimraf = require("rimraf"),
concat = require("gulp-concat"),
cssmin = require("gulp-cssmin"),
uglify = require("gulp-uglify")
var paths = {
webroot:"./wwwroot/"
};
paths.js = paths.webroot +"js/**/*.js";
paths.minJs = paths.webroot +"js/**/*.min.js";
paths.css = paths.webroot +"css/**/*.css";
paths.minCss = paths.webroot +"css/**/*.min.css";
paths.concatJsDest = paths.webroot +"js/site.min.js";
paths.concatCssDest = paths.webroot +"css/site.min.css";
gulp.task("clean:js", function (cb) {
rimraf(paths.concatJsDest, cb);
});
gulp.task("clean:css", function (cb) {
rimraf(paths.concatCssDest, cb);
});
gulp.task("clean", ["clean:js","clean:css"]);
gulp.task("min:js", function () {
gulp.src([paths.js,"!" + paths.minJs], { base:"." })
.pipe(concat(paths.concatJsDest))
.pipe(uglify())
.pipe(gulp.dest("."));
});
gulp.task("min:css", function () {
gulp.src([paths.css,"!" + paths.minCss])
.pipe(concat(paths.concatCssDest))
.pipe(cssmin())
.pipe(gulp.dest("."));
});
gulp.task("min", ["min:js","min:css"]);
Visual Studio 2015为gulp文件提供了一个任务运行器浏览器(见图40.8)。双击任务以启动它。还可以将gulp任务映射到Visual Studio命令。这样,当打开项目时,在编译之前或之后,或者当在“编译”菜单中选择了“清理”菜单项时,gulp任务将自动启动。
图40.8
注意 Visual Studio支持的另一个JavaScript编译系统是Grunt。 Grunt的重点是通过配置来编译,而Gulp的重点是通过JavaScript代码编译。
使用Bower客户端库
大多数客户端的 JavaScript库都通过 Bower 使用。 Bower是一个像 npm 的软件包管理器。而 npm 项目从服务器端代码的JavaScript库开始(尽管许多客户端脚本库也可以使用npm),Bower提供了成千上万的JavaScript客户端库。Bower可以通过使用项目模板 “Bower Configuration File”添加到ASP.NET Web项目。该模板添加的文件bower.json如下所示:
{
"name":"ASP.NET",
"private": true,
"dependencies": {
}
}
向项目添加Bower还会添加配置Bower的.bowerrc文件。 默认情况下,使用目录设置时脚本文件(以及脚本库附带的CSS和HTML文件)将复制到wwwroot/lib目录:
{
"directory":"wwwroot/lib"
}
注意 与NPM类似,单击解决方案资源管理器中的“显示所有文件”按钮,才能查看与bower相关的文件。
Visual Studio 2015对Bower有特殊支持。 图40.9显示了编辑器中的Bower图标。
图40.9
向bower.json文件添加脚本库,可以通过键入库的名称和版本号获得IntelliSense。 与npm类似,保存文件时将从服务器检索库,并且可以在Dependencies文件夹中找到它们。 由于.bowerrc中的配置,脚本库中的文件被复制到wwwroot/lib文件夹(代码文件MVCSampleApp/.bowerrc):
{
"name":"ASP.NET",
"private": true,
"dependencies": {
"bootstrap":"3.3.5",
"jquery":"2.1.4",
"jquery-validation":"1.14.0",
"jquery-validation-unobtrusive":"3.2.5"
}
}
通过单击应用程序上下文菜单“Manage Bower Packages”,可以访问的“Manage Bower Packages”工具管理Bower软件包。这个工具非常类似于NuGet包管理器,使管理Bower软件包变得轻松(见图40.10)。
图40.10
基础设施已经就位,现在是时候进入HTTP请求与应答了。