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

初识项目

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

咱们能够看到,此时Web Forms\MVC\Web API复选框都选择不了,原有是由于在ASP.NET 5中作了大量更改,移除了Web Forms功能,将MVC、Web API、Web Pages这些功能合在了一块儿,因此天然就不须要这些复选框了。另外因为是CTP版,因此目前尚未提供单元测试项目的建立。css

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

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

两个图的差别很是大,咱们来一一分析一下这些差别。java

项目结构差别

经过图示,咱们能够看到,在根目录中,不只项目文件从从csproj变成了xproj,还少了不少以前的文件(如web.config),但也多了不少不一样的文件以及文件夹,咱们先列出这些不一样的文件盒文件夹,再来一一讲解这些内容。node

文件/文件夹 功能描述
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是项目的核心配置文件,示例以下:jquery

{
    "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个类型的内容。web

webroot

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

程序集管理

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

在一级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的显示,以下图所示:

以默认配置为例,该配置文件在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的显示,以下图所示:

以默认配置为例,该配置文件注册了一个名为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系列

相关文章
相关标签/搜索