MVC6项目 初识项目 项目结构差异 project.json webroot 程序集管理 脚本事件 package.json bower.json gulpfile.js Grunt任务 config.json Startup.cs 其它 关于上述json配置文件的scheme介绍 同步与推荐

解读ASP.NET 5 & MVC6系列(2):初识项目

2015-05-14 09:08 by 汤姆大叔, 编辑

打开VS2015,创建Web项目,选择ASP.NET Web Application,在弹出的窗口里选择ASP.NET 5 Website模板创建项目,图示如下:

MVC6项目
初识项目
项目结构差异
project.json
webroot
程序集管理
脚本事件
package.json
bower.json
gulpfile.js
Grunt任务
config.json
Startup.cs
其它
关于上述json配置文件的scheme介绍
同步与推荐

我们可以看到,此时Web FormsMVCWeb API复选框都选择不了,原有是因为在ASP.NET 5中做了大量更改,移除了Web Forms功能,将MVC、Web API、Web Pages这些功能合在了一起,所以自然就不需要这些复选框了。另外由于是CTP版,所以目前还没有提供单元测试项目的创建。

新创建的项目在VS的解决方案目录结构和实际文件夹的目录结构分别如下:

MVC6项目
初识项目
项目结构差异
project.json
webroot
程序集管理
脚本事件
package.json
bower.json
gulpfile.js
Grunt任务
config.json
Startup.cs
其它
关于上述json配置文件的scheme介绍
同步与推荐

MVC6项目
初识项目
项目结构差异
project.json
webroot
程序集管理
脚本事件
package.json
bower.json
gulpfile.js
Grunt任务
config.json
Startup.cs
其它
关于上述json配置文件的scheme介绍
同步与推荐

注意:上图是在VS 预览版中的截图,在新版的RC版本中,默认的客户端构建工具变成了gulp(即配置文件是gulpfile.js),而非原来的grunt了。

两个图的差异非常大,我们来一一分析一下这些差异。

项目结构差异

通过图示,我们可以看到,在根目录中,不仅项目文件从从csproj变成了xproj,还少了很多之前的文件(如web.config),但也多了很多不同的文件以及文件夹,我们先列出这些不同的文件盒文件夹,再来一一讲解这些内容。

文件/文件夹 功能描述
config.json 程序的配置文件,类似于web.config。
project.json 该项目的主要配置,主要是负责程序集、项目部署等方面。部分功能类似于之前的package.config。
package.json npm的配置文件,npm是基于Nodejs的包管理器。
bower.json Bower管理器的配置文件,Bower是专门用于管理前端项目的包管理器。
gulpfile.js 是gulp的配置文件,gulp是基于Nodejs的Javascript任务管理器,在ASP.NET5中主要是用于管理NPM和Bower中的内容。
Stratup.cs 程序启动入口,类似于Global.asax。
Project_Readme.html 项目说明文件,没啥用。
wwwroot 静态资源文件(如css、图片、js)的存放目录。
Dependencies Bower和NPM的依赖管理包。
References 程序集引用,和以前的类似,但现在有了版本之分(如ASP.NET 5.0和ASP.NET Core 5.0)。

project.json

project.json是项目的核心配置文件,示例如下:

{
    "webroot": "wwwroot",
    "version": "1.0.0-*",
    "dependencies": {
        "Microsoft.AspNet.Diagnostics": "1.0.0-beta4",
        "Microsoft.AspNet.Mvc": "6.0.0-beta4",
        "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-beta4",
        "Microsoft.AspNet.Server.IIS": "1.0.0-beta4",
        "Microsoft.AspNet.Server.WebListener": "1.0.0-beta4",
        "Microsoft.AspNet.StaticFiles": "1.0.0-beta4",
        "Microsoft.AspNet.Tooling.Razor": "1.0.0-beta4",
        "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4",
        "Microsoft.Framework.CodeGenerators.Mvc": "1.0.0-beta4",
        "Microsoft.Framework.Logging": "1.0.0-beta4",
        "Microsoft.Framework.Logging.Console": "1.0.0-beta4",
        "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta4",
        "Microsoft.Framework.ConfigurationModel.UserSecrets": "1.0.0-beta4"
    },
    "commands": {
        "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000",
        "gen": "Microsoft.Framework.CodeGeneration"
    },
    "frameworks": {
        "dnx451": { },
        "dnxcore50": { }
    },
    "exclude": [
        "wwwroot",
        "node_modules",
        "bower_components"
    ],
    "publishExclude": [
        "node_modules",
        "bower_components",
        "**.xproj",
        "**.user",
        "**.vspscc"
    ],
    "scripts": {
        "postrestore": [ "npm install", "bower install" ],
        "prepare": [ "gulp copy" ]
    }
}

由于该文件的详细参数非常多,具体详细内容请参考http://go.microsoft.com/fwlink/?LinkID=517074 ,在这里我们主要讲解如下3个类型的内容。

webroot

webroot是指定该web项目的静态文件存放地址,目前是用于在发布的时候讲该目录中的内部发布的正确的位置(详细内容可以在部署发布章节中找到)。注意BookStore解决方案中带有地球图标的wwwroot目录是真实的文件夹路径,我们可以对其进行修改,比如将其修改为wwwroot1,那么相应的webroot的值也应该修改为wwwroot1,因为gulpfile.js里代码要通过project.webroot来使用该目录,以便能够将bower管理的前端库都复制到正确的目录。

程序集管理

在解决方案的References节点点,我们看到有两个分类,分别是:DNX 4.5.1和DNX Core 5.0,其中DNX Core 5.0就是我们所说的云优化版(即可以在其它操作系统下部署的跨平台版),而DNX 4.5.1则是和之前版本一样的全功能版,这两个版本的程序集是通过dependencies节点进行管理的。

在一级dependencies节点,主要是定义该项目的通用程序集引用以及版本,而不同的版本的程序集则在framworks下的各版本下的dependencies节点进行维护,比如:

"frameworks": {
    "dnx451": {
        "dependencies": {"log4net": "2.0.3"} /* 只在全功能版中引入log4net程序集*/

    },
    "dnxcore50": { }
}

上述两种类型的程序集在维护的时候,都有智能提示(包括程序集名称以及版本号),在当定义完自己要用的程序集并保持之后,系统会自动从Nuget上下载所需要的程序集,你也可以通过右键References选择Restore Packages来更新所有的程序集引用。同时你依然可以通过右键References的形式通过Nuget来管理这些程序集。

脚本事件

新版的VS2015允许我们在build解决方案之前、之后、过程;下载程序集之前、之后;更新程序集之前、之后自定义一些基于Nodejs的自定义事件来执行。该事件在project.json中的定义节点是scripts,示例如下:

"scripts": {
    "postrestore": [ "npm install" ],  // 在更新所有的程序集之前执行npm install事件
    "prepare": [ "gulp copy" ]
    // 在打开解决方案之前,执行gulp任务,调用bower的install方法。
}

具体的事件名称如下:

时机 描述
prebuild 构建之前执行
postbuild 构建之后执行
prepack packing之前执行
postpack packing之后执行
prerestore restoring packages之前执行
postrestore restoring packages之后执行

package.json

package.jsonNPM管理器的配置文件,由于在VS2015默认就深度集成了Nodejs,而NPM又是Nodejs的默认包管理器,所以所有基于Nodejs的包都要在这里进行配置。该配置文件的默认配置如下:

{
    "name": "ASP.NET",
    "version": "0.0.0",
    "devDependencies": {
        "gulp": "3.8.11",//gulp任务管理器
        "rimraf": "2.2.8" // 递归删除文件的nodejs包
    }
}

上述代码中的rimraf是一个递归删除文件的nodejs包,我们也可以引用其他插件,像project.json文件中管理程序集一样,在package.json文件中来管理前端程序的各种包,例如jquery,bootstrap等等,比如我们要安装一个express包,只需要在json文件中添加一个express字符串键,并选择器版本就可以了,系统会自动下载该NPM包并显示在解决方案的Dependencies->NPM节点下。

注意:已经安装的包不能自动移除(即不能通过在JSON中移除配置),需要右键执行该包,并手工卸载。

bower.json

所有的前端包都配置子bower.json文件中,比如你需要的jquery、bootstrap、angular等等,其管理方式与project.json里的程序集和package.json里的npm包一样,都是通过在dependencies节点下声明包的名称和版本来实现的。

我们可以在此声明一个angular包,保存以后就可以看到在解决方案Dependencie->Bower节点下该angular已经自动下载好了,编译项目,就可以看到在wwroot/lib也可以看到angular文件夹以及相应的文件了。

在bower.json还有一个exportsOverride节点非常重要,他扩展了原来bower的前端文件copy机制,默认情况下bower只会复制main节点定义的文件。但有时候我们要复制的文件可能不止这些,所以grunt-bower-task插件就扩展了该功能,定义了这个exportsOverride节点,其使用规则如下:

  1. 如果Bower包定义了main文件节点,就将其复制到wwwroot/lib下。
  2. 如果Bower包定义了的main节点为空,则将整个包的目录都复制到wwwroot/lib下。
  3. 如果定义了exportsOverride节点,则只会把该节点指定的文件复制到wwwroot/lib下。

注意,exportsOverride节点中定义的key/value,其中key表示要文件复制目标(即wwwroot/lib下)对应包名下的子目录,value表示源文件目录或文件。例如:

"bootstrap": {
    "js": "dist/js/*.*", //将dist/js/下的所有文件,复制到wwwroot/lib/bootstrap/js目录下
    "css": "dist/css/*.*",
    "fonts": "dist/fonts/*.*"
},
"jquery": {
    "": "jquery.{js,min.js,min.map}" // 将jquery.js,jquery.min.js,jquery.min.map文件复制到wwwroot/lib/jquery目录下
},

注意:和NPM类似,bower.json里的配置的包,不能自动移除,需要从Bower里卸载该包,并将相关的文件从wwwroot/lib中移除。

gulpfile.js

gulpfile.js是gulp任务管理器的配置文件,默认情况下,该配置文件会把wwwroot/lib目录下的所有文件清除(clean任务),然后重新从bower_components目录中复制一份(copy任务)。

该文件配置的修改会影响到VS里的Task Runner Explorer的显示,如下图所示:

MVC6项目
初识项目
项目结构差异
project.json
webroot
程序集管理
脚本事件
package.json
bower.json
gulpfile.js
Grunt任务
config.json
Startup.cs
其它
关于上述json配置文件的scheme介绍
同步与推荐

以默认配置为例,该配置文件在Task目录下注册了两个任务,分别是clean和copy,并默认在VS解决方案清除编译以后重新执行clean任务,但我们也可以给该任务绑定任何一个执行时间点,我们可以右键该任务->绑定->在构建之前,然后在点击面板左边的刷新按钮,这时候该绑定内容就会同步保存在gulpfile.js的第一行,代码如下:

/// <binding BeforeBuild='copy' Clean='clean' />

此时,删除wwwroot/lib目录下所有的文件,然后重新编译BookStore项目,就会自动在wwwroot/lib目录下生成所有需要的文件,即将Bower.json里定义的各种包按照配置需求复制到该目录下。

clean任务

clean任务的主要作用,是在编译之前或清理解决方案是,将lib目录下的前端文件全部删除,以便重新copy新的文件。具体分析如下:

var gulp = require("gulp"), // 引用gulp
  rimraf = require("rimraf"),// 引用rimraf
  fs = require("fs");  //引用文件系统

eval("var project = " + fs.readFileSync("./project.json"));  //读取project.json配置文件

var paths = {
  bower: "./bower_components/",
  lib: "./" + project.webroot + "/lib/"
};

gulp.task("clean", function (cb) {  //注册clean任务
  rimraf(paths.lib, cb);  // 递归删除lib目录下的所有文件
});

copy任务

copy任务则很简单,将bower_components目录下符合条件的文件复制lib目录下,分析如下:

gulp.task("copy", ["clean"], function () {  // 注册copy任务
  var bower = { // 目录对应关系
    "bootstrap": "bootstrap/dist/**/*.{js,map,css,ttf,svg,woff,eot}",
    "bootstrap-touch-carousel": "bootstrap-touch-carousel/dist/**/*.{js,css}",
    "hammer.js": "hammer.js/hammer*.{js,map}",
    "jquery": "jquery/jquery*.{js,map}",
    "jquery-validation": "jquery-validation/jquery.validate.js",
    "jquery-validation-unobtrusive": "jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"
  }

  for (var destinationDir in bower) {
    gulp.src(paths.bower + bower[destinationDir])  // 读取源目录
      .pipe(gulp.dest(paths.lib + destinationDir));  //复制到目标文件夹
  }
});

Grunt任务

VS2015中,虽然默认支持的是Gulp构建工具,但其实还支持Grunt构建工具,使用方式和Gulp类似,要使用Grunt,也需要引用类似的依赖包,示例如下:

{
    "version": "0.0.0",
    "name": "",
    "devDependencies": {
        "grunt": "0.4.5", //grunt任务管理器
        "grunt-bower-task": "0.4.0" // 基于grunt的bower管理插件
    }
}

上述代码中的grunt-bower-task是一个基于gruntbower管理插件,用于自动执行bowerinstall命令来安装Bower包。

注意:已经安装的包不能自动移除(即不能通过在JSON中移除配置),需要右键执行该包,并手工卸载。

gruntfile.js是grunt任务管理器的配置文件,要使用grunt,就需要创建gruntfile.js文件,默认情况下,该配置文件只配置了grunt-bower-task插件的任务执行,该插件会读取bower.json配置信息,将相关的包通过bower:install命令都安装到指定的目录下(默认是通过targetDir设置的wwwroot/lib目录。

该文件配置的修改会影响到VS里的Task Runner Explorer的显示,如下图所示:

MVC6项目
初识项目
项目结构差异
project.json
webroot
程序集管理
脚本事件
package.json
bower.json
gulpfile.js
Grunt任务
config.json
Startup.cs
其它
关于上述json配置文件的scheme介绍
同步与推荐

以默认配置为例,该配置文件注册了一个名为default的任务在该面板里(Alias Tasks列表中)显示,该任务也是Grunt的默认任务名称,但并没有定义该任务在什么时候执行,所以这时候我们可以给该任务绑定一个执行时间点,我们可以右键该任务->绑定->在构建之前,然后在点击面板左边的刷新按钮,这时候该绑定内容就会同步保存在gruntfile.js的第一行,代码如下:

/// <binding BeforeBuild='default' />

此时,删除wwwroot/lib目录下所有的文件,然后重新编译BookStore项目,就会自动在wwwroot/lib目录下生成所有需要的文件,即将Bower.json里定义的各种包按照配置需求复制到该目录下。而Tasks中的任务,则是从grunt.loadNpmTasks里加载的包里分析出来的任务,如bower。
我们再来练习一个例子,假设我们编译之前要对wwwroot/css/目录下的site.css文件进行压缩(压缩成site.min.css),我们则可以安装如下方式进行操作:

首先,在package.json里定义一个可以压缩CSS代码的grunt插件:

{
  "version": "0.0.0",
  "name": "",
  "devDependencies": {
    "grunt": "0.4.5",
    "grunt-bower-task": "0.4.0",
    "grunt-contrib-cssmin": "0.12.2"  /*新的插件*/
  }
}

然后在grunt.initConfig下的bower同级节点下面,添加如下内容:

/*压缩css*/
cssmin: {
    target: {
        options: {
            sourceMap: true,
        },
        files: {
            /*输出文件路径:原始文件路径*/
            'wwwroot/css/site.min.css': 'wwwroot/css/site.css'
        }
    }
}

最后再注册此插件,代码如下:

grunt.loadNpmTasks('grunt-contrib-cssmin'); /*压缩css*/

这样,你就可以在Task Runner Explorer面板中看到cssmin任务,然后运行它了,当然你也可以将该任务和default任务一起添加到编译构建之前进行执行。代码如下:

/// <binding BeforeBuild='default, cssmin' />

另外,在给一些例子,一个是用于js压缩,一个是用于less编译,代码如下:

/*package.json*/
"grunt-contrib-uglify": "0.9.1",
"grunt-contrib-less": "1.0.1"

/*gruntfile.js*/
/*压缩js*/
uglify: {
    target: {
        options: {
            sourceMap: true,
        },
        files: {
            'wwwroot/Scripts/site.min.js': 'wwwroot/Scripts/site.js'
        }
    }
},
/*编译less*/
less: {
    //开发版(无压缩)
    development: {
        options: {
            sourceMap: true
        },
        files: {
            'wwwroot/Styles/site.css': 'wwwroot/Lesses/site.less'
        }
    },
    //生产版(压缩)
    production: {
        options: {
            compress: true
        },
        files: {
            'wwwroot/Styles/site.min.css': 'wwwroot/Lesses/site.less'
        }
    }
}
/*...*/
grunt.loadNpmTasks('grunt-contrib-uglify');  /*压缩js*/
grunt.loadNpmTasks('grunt-contrib-less');   /*编译less*/

建议:不要在多个时期都绑定同一种任务。
推荐:grunt还有一个插件用于监控文件的修改,比如兼容css文件的修改,一旦修改了就调用css的压缩命令,详情请参考grunt-contrib-watch插件。

config.json

config.json就是以前的web.config,但是没有web.config拥有各种类型的配置那么强大,其中各种功能的配置都以代码的形式转移到Startup.cs文件中了;另外一部分信息配置内容,则放在config.json文件中以json的格式进行保存。

注意,该文件的信息默认并没有自动加载,而是需要自己手工加载该配置信息,代码如下:

//Startup.cs类的构造函数中
Configuration = new Configuration()
                .AddJsonFile("config.json")
                .AddEnvironmentVariables();

通过Configuration实例加载该配置文件,保存在Configuration属性中,以便可以在其它地方进行使用,而使用时候的key值,则是按照层级来定义的,以如下默认内容来说:

{
    "AppSettings": {
        "SiteTitle": "WebDemo01"
    }
}

要获取链接字符串,则需要使用如下key值:

var connString = Configuration.Get("AppSettings:SiteTitle");

使用起来,没有web.config方便了,但是为了兼容其它操作系统,只能这样了。

注意:在ASP.NET5中,配置信息不仅支持json格式,还支持ini、xml等格式,具体详细请参考后续的配置信息管理章节。

Startup.cs

Startup.cs是整个程序的启动入口,类似于Global.asax,和Global.asax文件一样,起到全局配置信息的作用。我们来分析一下该文件的几个重要作用。

首先在构造函数中初始化基础配置信息(关于详细的配置信息内容请参考配置信息管理章节),注意这里的初始化后的配置信息绑定到一个Configuration属性上了,以便另外两个方法在后期进行使用,如果你要在其它类中进行使用,则需要将该实例保存到其它地方(如静态变量)。

ConfigureServices方法是依赖注入的核心,在方法的传入参数services中,首先保存了默认依赖注入里定义的类型定义,然后我们在这个方法里,可以继续注册依赖注入的类型定义,关于依赖注入的详细内容,可以阅读依赖注入章节。

同时一些重要的功能需要开启的话,也需要在这里开启,比如添加Mvc模块,就需要使用如下调用语句:

services.AddMvc();

原因是因为,在新版的ASP.NET 5中,除了最基础的模块以外,绝大部分模块都是纯组件化的,这里称为Middleware,而组件在使用的时候首先需要先添加该模块才能使用。再比如,添加EF模块的话,需要调用

services.AddEntityFramework()方法。

而另外一个Configure方法,顾名思义是对各种Middleware组件进行配置的地方,一般来说,配置模块的方法都是调用类似app.UseXXX()这样的方法,如使用静态文件处理流程,则调用如下语句即可:

app.UseStaticFiles();

如果要使用Mvc的功能,则需要使用app.UseMvc方法,在调用这些方法时,可以配置并传入响应的参数。

注意,ConfigureServices里用到的services.AddXXX()类型的方法和Configure方法里用到的app.UseXXX()类型的方法都是扩展方法,AddXXX()方法是在IServiceCollection接口上进行扩展的,而UseXXX()方法则是在IApplicationBuilder接口上扩展的。

关于该文件中提到的依赖注入、以及Configure方法中的3个类型的参数:IApplicationBuilder、IHostingEnvironment、ILoggerFactory;我们会在后续的章节中进行详细讲解。

其它

通过查看,可以发现,Views目录下的web.config也被移除了,在RC版中,要统一引用命名空间,需要在ViewStart.cshtml 或者 GlobalImport.cshtml 文件中,后续章节我们会讲到。

我们不用做任何修改,F5运行项目即可运行,由于默认使用的是IIS Express,所以会自动打开新网站首页。如果不是IIS Express,请阅读后续的编译与部署章节。

关于上述json配置文件的scheme介绍

关于上述配置文件(含global.json、project.json、config.json、package.json、bower.json)的scheme定义,以及js参数配置的定义,请访问http://schemastore.org/json/进行查看。

推荐资料:

  1. beiyuu.com/grunt-in-action/
  2. http://www.it165.net/pro/html/201503/35652.html

同步与推荐

本文已同步至目录索引:解读ASP.NET 5 & MVC6系列

打开VS2015,创建Web项目,选择ASP.NET Web Application,在弹出的窗口里选择ASP.NET 5 Website模板创建项目,图示如下:

MVC6项目
初识项目
项目结构差异
project.json
webroot
程序集管理
脚本事件
package.json
bower.json
gulpfile.js
Grunt任务
config.json
Startup.cs
其它
关于上述json配置文件的scheme介绍
同步与推荐

我们可以看到,此时Web FormsMVCWeb API复选框都选择不了,原有是因为在ASP.NET 5中做了大量更改,移除了Web Forms功能,将MVC、Web API、Web Pages这些功能合在了一起,所以自然就不需要这些复选框了。另外由于是CTP版,所以目前还没有提供单元测试项目的创建。

新创建的项目在VS的解决方案目录结构和实际文件夹的目录结构分别如下:

MVC6项目
初识项目
项目结构差异
project.json
webroot
程序集管理
脚本事件
package.json
bower.json
gulpfile.js
Grunt任务
config.json
Startup.cs
其它
关于上述json配置文件的scheme介绍
同步与推荐

MVC6项目
初识项目
项目结构差异
project.json
webroot
程序集管理
脚本事件
package.json
bower.json
gulpfile.js
Grunt任务
config.json
Startup.cs
其它
关于上述json配置文件的scheme介绍
同步与推荐

注意:上图是在VS 预览版中的截图,在新版的RC版本中,默认的客户端构建工具变成了gulp(即配置文件是gulpfile.js),而非原来的grunt了。

两个图的差异非常大,我们来一一分析一下这些差异。

项目结构差异

通过图示,我们可以看到,在根目录中,不仅项目文件从从csproj变成了xproj,还少了很多之前的文件(如web.config),但也多了很多不同的文件以及文件夹,我们先列出这些不同的文件盒文件夹,再来一一讲解这些内容。

文件/文件夹 功能描述
config.json 程序的配置文件,类似于web.config。
project.json 该项目的主要配置,主要是负责程序集、项目部署等方面。部分功能类似于之前的package.config。
package.json npm的配置文件,npm是基于Nodejs的包管理器。
bower.json Bower管理器的配置文件,Bower是专门用于管理前端项目的包管理器。
gulpfile.js 是gulp的配置文件,gulp是基于Nodejs的Javascript任务管理器,在ASP.NET5中主要是用于管理NPM和Bower中的内容。
Stratup.cs 程序启动入口,类似于Global.asax。
Project_Readme.html 项目说明文件,没啥用。
wwwroot 静态资源文件(如css、图片、js)的存放目录。
Dependencies Bower和NPM的依赖管理包。
References 程序集引用,和以前的类似,但现在有了版本之分(如ASP.NET 5.0和ASP.NET Core 5.0)。

project.json

project.json是项目的核心配置文件,示例如下:

{
    "webroot": "wwwroot",
    "version": "1.0.0-*",
    "dependencies": {
        "Microsoft.AspNet.Diagnostics": "1.0.0-beta4",
        "Microsoft.AspNet.Mvc": "6.0.0-beta4",
        "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-beta4",
        "Microsoft.AspNet.Server.IIS": "1.0.0-beta4",
        "Microsoft.AspNet.Server.WebListener": "1.0.0-beta4",
        "Microsoft.AspNet.StaticFiles": "1.0.0-beta4",
        "Microsoft.AspNet.Tooling.Razor": "1.0.0-beta4",
        "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4",
        "Microsoft.Framework.CodeGenerators.Mvc": "1.0.0-beta4",
        "Microsoft.Framework.Logging": "1.0.0-beta4",
        "Microsoft.Framework.Logging.Console": "1.0.0-beta4",
        "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta4",
        "Microsoft.Framework.ConfigurationModel.UserSecrets": "1.0.0-beta4"
    },
    "commands": {
        "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000",
        "gen": "Microsoft.Framework.CodeGeneration"
    },
    "frameworks": {
        "dnx451": { },
        "dnxcore50": { }
    },
    "exclude": [
        "wwwroot",
        "node_modules",
        "bower_components"
    ],
    "publishExclude": [
        "node_modules",
        "bower_components",
        "**.xproj",
        "**.user",
        "**.vspscc"
    ],
    "scripts": {
        "postrestore": [ "npm install", "bower install" ],
        "prepare": [ "gulp copy" ]
    }
}

由于该文件的详细参数非常多,具体详细内容请参考http://go.microsoft.com/fwlink/?LinkID=517074 ,在这里我们主要讲解如下3个类型的内容。

webroot

webroot是指定该web项目的静态文件存放地址,目前是用于在发布的时候讲该目录中的内部发布的正确的位置(详细内容可以在部署发布章节中找到)。注意BookStore解决方案中带有地球图标的wwwroot目录是真实的文件夹路径,我们可以对其进行修改,比如将其修改为wwwroot1,那么相应的webroot的值也应该修改为wwwroot1,因为gulpfile.js里代码要通过project.webroot来使用该目录,以便能够将bower管理的前端库都复制到正确的目录。

程序集管理

在解决方案的References节点点,我们看到有两个分类,分别是:DNX 4.5.1和DNX Core 5.0,其中DNX Core 5.0就是我们所说的云优化版(即可以在其它操作系统下部署的跨平台版),而DNX 4.5.1则是和之前版本一样的全功能版,这两个版本的程序集是通过dependencies节点进行管理的。

在一级dependencies节点,主要是定义该项目的通用程序集引用以及版本,而不同的版本的程序集则在framworks下的各版本下的dependencies节点进行维护,比如:

"frameworks": {
    "dnx451": {
        "dependencies": {"log4net": "2.0.3"} /* 只在全功能版中引入log4net程序集*/

    },
    "dnxcore50": { }
}

上述两种类型的程序集在维护的时候,都有智能提示(包括程序集名称以及版本号),在当定义完自己要用的程序集并保持之后,系统会自动从Nuget上下载所需要的程序集,你也可以通过右键References选择Restore Packages来更新所有的程序集引用。同时你依然可以通过右键References的形式通过Nuget来管理这些程序集。

脚本事件

新版的VS2015允许我们在build解决方案之前、之后、过程;下载程序集之前、之后;更新程序集之前、之后自定义一些基于Nodejs的自定义事件来执行。该事件在project.json中的定义节点是scripts,示例如下:

"scripts": {
    "postrestore": [ "npm install" ],  // 在更新所有的程序集之前执行npm install事件
    "prepare": [ "gulp copy" ]
    // 在打开解决方案之前,执行gulp任务,调用bower的install方法。
}

具体的事件名称如下:

时机 描述
prebuild 构建之前执行
postbuild 构建之后执行
prepack packing之前执行
postpack packing之后执行
prerestore restoring packages之前执行
postrestore restoring packages之后执行

package.json

package.jsonNPM管理器的配置文件,由于在VS2015默认就深度集成了Nodejs,而NPM又是Nodejs的默认包管理器,所以所有基于Nodejs的包都要在这里进行配置。该配置文件的默认配置如下:

{
    "name": "ASP.NET",
    "version": "0.0.0",
    "devDependencies": {
        "gulp": "3.8.11",//gulp任务管理器
        "rimraf": "2.2.8" // 递归删除文件的nodejs包
    }
}

上述代码中的rimraf是一个递归删除文件的nodejs包,我们也可以引用其他插件,像project.json文件中管理程序集一样,在package.json文件中来管理前端程序的各种包,例如jquery,bootstrap等等,比如我们要安装一个express包,只需要在json文件中添加一个express字符串键,并选择器版本就可以了,系统会自动下载该NPM包并显示在解决方案的Dependencies->NPM节点下。

注意:已经安装的包不能自动移除(即不能通过在JSON中移除配置),需要右键执行该包,并手工卸载。

bower.json

所有的前端包都配置子bower.json文件中,比如你需要的jquery、bootstrap、angular等等,其管理方式与project.json里的程序集和package.json里的npm包一样,都是通过在dependencies节点下声明包的名称和版本来实现的。

我们可以在此声明一个angular包,保存以后就可以看到在解决方案Dependencie->Bower节点下该angular已经自动下载好了,编译项目,就可以看到在wwroot/lib也可以看到angular文件夹以及相应的文件了。

在bower.json还有一个exportsOverride节点非常重要,他扩展了原来bower的前端文件copy机制,默认情况下bower只会复制main节点定义的文件。但有时候我们要复制的文件可能不止这些,所以grunt-bower-task插件就扩展了该功能,定义了这个exportsOverride节点,其使用规则如下:

  1. 如果Bower包定义了main文件节点,就将其复制到wwwroot/lib下。
  2. 如果Bower包定义了的main节点为空,则将整个包的目录都复制到wwwroot/lib下。
  3. 如果定义了exportsOverride节点,则只会把该节点指定的文件复制到wwwroot/lib下。

注意,exportsOverride节点中定义的key/value,其中key表示要文件复制目标(即wwwroot/lib下)对应包名下的子目录,value表示源文件目录或文件。例如:

"bootstrap": {
    "js": "dist/js/*.*", //将dist/js/下的所有文件,复制到wwwroot/lib/bootstrap/js目录下
    "css": "dist/css/*.*",
    "fonts": "dist/fonts/*.*"
},
"jquery": {
    "": "jquery.{js,min.js,min.map}" // 将jquery.js,jquery.min.js,jquery.min.map文件复制到wwwroot/lib/jquery目录下
},

注意:和NPM类似,bower.json里的配置的包,不能自动移除,需要从Bower里卸载该包,并将相关的文件从wwwroot/lib中移除。

gulpfile.js

gulpfile.js是gulp任务管理器的配置文件,默认情况下,该配置文件会把wwwroot/lib目录下的所有文件清除(clean任务),然后重新从bower_components目录中复制一份(copy任务)。

该文件配置的修改会影响到VS里的Task Runner Explorer的显示,如下图所示:

MVC6项目
初识项目
项目结构差异
project.json
webroot
程序集管理
脚本事件
package.json
bower.json
gulpfile.js
Grunt任务
config.json
Startup.cs
其它
关于上述json配置文件的scheme介绍
同步与推荐

以默认配置为例,该配置文件在Task目录下注册了两个任务,分别是clean和copy,并默认在VS解决方案清除编译以后重新执行clean任务,但我们也可以给该任务绑定任何一个执行时间点,我们可以右键该任务->绑定->在构建之前,然后在点击面板左边的刷新按钮,这时候该绑定内容就会同步保存在gulpfile.js的第一行,代码如下:

/// <binding BeforeBuild='copy' Clean='clean' />

此时,删除wwwroot/lib目录下所有的文件,然后重新编译BookStore项目,就会自动在wwwroot/lib目录下生成所有需要的文件,即将Bower.json里定义的各种包按照配置需求复制到该目录下。

clean任务

clean任务的主要作用,是在编译之前或清理解决方案是,将lib目录下的前端文件全部删除,以便重新copy新的文件。具体分析如下:

var gulp = require("gulp"), // 引用gulp
  rimraf = require("rimraf"),// 引用rimraf
  fs = require("fs");  //引用文件系统

eval("var project = " + fs.readFileSync("./project.json"));  //读取project.json配置文件

var paths = {
  bower: "./bower_components/",
  lib: "./" + project.webroot + "/lib/"
};

gulp.task("clean", function (cb) {  //注册clean任务
  rimraf(paths.lib, cb);  // 递归删除lib目录下的所有文件
});

copy任务

copy任务则很简单,将bower_components目录下符合条件的文件复制lib目录下,分析如下:

gulp.task("copy", ["clean"], function () {  // 注册copy任务
  var bower = { // 目录对应关系
    "bootstrap": "bootstrap/dist/**/*.{js,map,css,ttf,svg,woff,eot}",
    "bootstrap-touch-carousel": "bootstrap-touch-carousel/dist/**/*.{js,css}",
    "hammer.js": "hammer.js/hammer*.{js,map}",
    "jquery": "jquery/jquery*.{js,map}",
    "jquery-validation": "jquery-validation/jquery.validate.js",
    "jquery-validation-unobtrusive": "jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"
  }

  for (var destinationDir in bower) {
    gulp.src(paths.bower + bower[destinationDir])  // 读取源目录
      .pipe(gulp.dest(paths.lib + destinationDir));  //复制到目标文件夹
  }
});

Grunt任务

VS2015中,虽然默认支持的是Gulp构建工具,但其实还支持Grunt构建工具,使用方式和Gulp类似,要使用Grunt,也需要引用类似的依赖包,示例如下:

{
    "version": "0.0.0",
    "name": "",
    "devDependencies": {
        "grunt": "0.4.5", //grunt任务管理器
        "grunt-bower-task": "0.4.0" // 基于grunt的bower管理插件
    }
}

上述代码中的grunt-bower-task是一个基于gruntbower管理插件,用于自动执行bowerinstall命令来安装Bower包。

注意:已经安装的包不能自动移除(即不能通过在JSON中移除配置),需要右键执行该包,并手工卸载。

gruntfile.js是grunt任务管理器的配置文件,要使用grunt,就需要创建gruntfile.js文件,默认情况下,该配置文件只配置了grunt-bower-task插件的任务执行,该插件会读取bower.json配置信息,将相关的包通过bower:install命令都安装到指定的目录下(默认是通过targetDir设置的wwwroot/lib目录。

该文件配置的修改会影响到VS里的Task Runner Explorer的显示,如下图所示:

MVC6项目
初识项目
项目结构差异
project.json
webroot
程序集管理
脚本事件
package.json
bower.json
gulpfile.js
Grunt任务
config.json
Startup.cs
其它
关于上述json配置文件的scheme介绍
同步与推荐

以默认配置为例,该配置文件注册了一个名为default的任务在该面板里(Alias Tasks列表中)显示,该任务也是Grunt的默认任务名称,但并没有定义该任务在什么时候执行,所以这时候我们可以给该任务绑定一个执行时间点,我们可以右键该任务->绑定->在构建之前,然后在点击面板左边的刷新按钮,这时候该绑定内容就会同步保存在gruntfile.js的第一行,代码如下:

/// <binding BeforeBuild='default' />

此时,删除wwwroot/lib目录下所有的文件,然后重新编译BookStore项目,就会自动在wwwroot/lib目录下生成所有需要的文件,即将Bower.json里定义的各种包按照配置需求复制到该目录下。而Tasks中的任务,则是从grunt.loadNpmTasks里加载的包里分析出来的任务,如bower。
我们再来练习一个例子,假设我们编译之前要对wwwroot/css/目录下的site.css文件进行压缩(压缩成site.min.css),我们则可以安装如下方式进行操作:

首先,在package.json里定义一个可以压缩CSS代码的grunt插件:

{
  "version": "0.0.0",
  "name": "",
  "devDependencies": {
    "grunt": "0.4.5",
    "grunt-bower-task": "0.4.0",
    "grunt-contrib-cssmin": "0.12.2"  /*新的插件*/
  }
}

然后在grunt.initConfig下的bower同级节点下面,添加如下内容:

/*压缩css*/
cssmin: {
    target: {
        options: {
            sourceMap: true,
        },
        files: {
            /*输出文件路径:原始文件路径*/
            'wwwroot/css/site.min.css': 'wwwroot/css/site.css'
        }
    }
}

最后再注册此插件,代码如下:

grunt.loadNpmTasks('grunt-contrib-cssmin'); /*压缩css*/

这样,你就可以在Task Runner Explorer面板中看到cssmin任务,然后运行它了,当然你也可以将该任务和default任务一起添加到编译构建之前进行执行。代码如下:

/// <binding BeforeBuild='default, cssmin' />

另外,在给一些例子,一个是用于js压缩,一个是用于less编译,代码如下:

/*package.json*/
"grunt-contrib-uglify": "0.9.1",
"grunt-contrib-less": "1.0.1"

/*gruntfile.js*/
/*压缩js*/
uglify: {
    target: {
        options: {
            sourceMap: true,
        },
        files: {
            'wwwroot/Scripts/site.min.js': 'wwwroot/Scripts/site.js'
        }
    }
},
/*编译less*/
less: {
    //开发版(无压缩)
    development: {
        options: {
            sourceMap: true
        },
        files: {
            'wwwroot/Styles/site.css': 'wwwroot/Lesses/site.less'
        }
    },
    //生产版(压缩)
    production: {
        options: {
            compress: true
        },
        files: {
            'wwwroot/Styles/site.min.css': 'wwwroot/Lesses/site.less'
        }
    }
}
/*...*/
grunt.loadNpmTasks('grunt-contrib-uglify');  /*压缩js*/
grunt.loadNpmTasks('grunt-contrib-less');   /*编译less*/

建议:不要在多个时期都绑定同一种任务。
推荐:grunt还有一个插件用于监控文件的修改,比如兼容css文件的修改,一旦修改了就调用css的压缩命令,详情请参考grunt-contrib-watch插件。

config.json

config.json就是以前的web.config,但是没有web.config拥有各种类型的配置那么强大,其中各种功能的配置都以代码的形式转移到Startup.cs文件中了;另外一部分信息配置内容,则放在config.json文件中以json的格式进行保存。

注意,该文件的信息默认并没有自动加载,而是需要自己手工加载该配置信息,代码如下:

//Startup.cs类的构造函数中
Configuration = new Configuration()
                .AddJsonFile("config.json")
                .AddEnvironmentVariables();

通过Configuration实例加载该配置文件,保存在Configuration属性中,以便可以在其它地方进行使用,而使用时候的key值,则是按照层级来定义的,以如下默认内容来说:

{
    "AppSettings": {
        "SiteTitle": "WebDemo01"
    }
}

要获取链接字符串,则需要使用如下key值:

var connString = Configuration.Get("AppSettings:SiteTitle");

使用起来,没有web.config方便了,但是为了兼容其它操作系统,只能这样了。

注意:在ASP.NET5中,配置信息不仅支持json格式,还支持ini、xml等格式,具体详细请参考后续的配置信息管理章节。

Startup.cs

Startup.cs是整个程序的启动入口,类似于Global.asax,和Global.asax文件一样,起到全局配置信息的作用。我们来分析一下该文件的几个重要作用。

首先在构造函数中初始化基础配置信息(关于详细的配置信息内容请参考配置信息管理章节),注意这里的初始化后的配置信息绑定到一个Configuration属性上了,以便另外两个方法在后期进行使用,如果你要在其它类中进行使用,则需要将该实例保存到其它地方(如静态变量)。

ConfigureServices方法是依赖注入的核心,在方法的传入参数services中,首先保存了默认依赖注入里定义的类型定义,然后我们在这个方法里,可以继续注册依赖注入的类型定义,关于依赖注入的详细内容,可以阅读依赖注入章节。

同时一些重要的功能需要开启的话,也需要在这里开启,比如添加Mvc模块,就需要使用如下调用语句:

services.AddMvc();

原因是因为,在新版的ASP.NET 5中,除了最基础的模块以外,绝大部分模块都是纯组件化的,这里称为Middleware,而组件在使用的时候首先需要先添加该模块才能使用。再比如,添加EF模块的话,需要调用

services.AddEntityFramework()方法。

而另外一个Configure方法,顾名思义是对各种Middleware组件进行配置的地方,一般来说,配置模块的方法都是调用类似app.UseXXX()这样的方法,如使用静态文件处理流程,则调用如下语句即可:

app.UseStaticFiles();

如果要使用Mvc的功能,则需要使用app.UseMvc方法,在调用这些方法时,可以配置并传入响应的参数。

注意,ConfigureServices里用到的services.AddXXX()类型的方法和Configure方法里用到的app.UseXXX()类型的方法都是扩展方法,AddXXX()方法是在IServiceCollection接口上进行扩展的,而UseXXX()方法则是在IApplicationBuilder接口上扩展的。

关于该文件中提到的依赖注入、以及Configure方法中的3个类型的参数:IApplicationBuilder、IHostingEnvironment、ILoggerFactory;我们会在后续的章节中进行详细讲解。

其它

通过查看,可以发现,Views目录下的web.config也被移除了,在RC版中,要统一引用命名空间,需要在ViewStart.cshtml 或者 GlobalImport.cshtml 文件中,后续章节我们会讲到。

我们不用做任何修改,F5运行项目即可运行,由于默认使用的是IIS Express,所以会自动打开新网站首页。如果不是IIS Express,请阅读后续的编译与部署章节。

关于上述json配置文件的scheme介绍

关于上述配置文件(含global.json、project.json、config.json、package.json、bower.json)的scheme定义,以及js参数配置的定义,请访问http://schemastore.org/json/进行查看。

推荐资料:

  1. beiyuu.com/grunt-in-action/
  2. http://www.it165.net/pro/html/201503/35652.html

同步与推荐

本文已同步至目录索引:解读ASP.NET 5 & MVC6系列