【续集】在 IIS 中部署 ASP.NET 5 应用程序遭遇的问题

针对 IIS 部署 ASP.NET 5 应用程序的问题,在上面博文中主要采用两种方式尝试:css

  1. VS2015 的 Publish 方式(成功)。web

  2. 手动复制文件的方式(失败)。json

本篇博文主题:

  1. 初步理解 ASP.NET 5 的编译及部署问题。bootstrap

  2. 解决 ASP.NET 5 预编译,并成功部署到 IIS 上。浏览器

先啰嗦两句:

首先,如今的 IIS 对于 ASP.NET 5 来讲,其实已经没有太大的关系了,用不用它都无所谓,ASP.NET 5 应用程序能够采用 Self-Hosting(自寄宿)的方式,也就是本身看成 Web 服务器,实现方式只要在 project.json 中添加 Microsoft.AspNet.Hosting 程序包就能够了,咱们知道,Web 服务器的做用其实就是监听请求,并分发请求给相应模块进行处理,最后再输出处理结果,若是咱们把这个请求处理过程进行分化,交给不一样的组件或模块进行处理,咱们就能够脱离集成化的 IIS,在 Owin 体系结构中,ASP.NET 5 应用程序部署到 IIS 上,这个 IIS 的做用就只是一个 Host(管理应用程序的线程,打开、关闭或加载组件),Server(如 Microsoft.AspNet.Server.WebListener)和 Middleware(如 Microsoft.AspNet.StaticFiles)都有相应的处理组件,不须要用到 IIS 的那一套东西,好比以前咱们须要在 IIS 中进行 HttpModule 配置等。服务器

既然咱们不使用 IIS 的那一套东西,若是将 ASP.NET 5 应用程序部署到 IIS 上,那就必须有个东西将 IIS 和 ASP.NET 5 独立运行时(KRE)之间的通道(Pipeline)打通,这个东西就是 AspNet.Loader.dll(位置:application/wwwroot/bin),使用它的条件是在 project.json 中添加 Microsoft.AspNet.Server.IIS 程序包,并且只在 IIS 中才会出现,若是采用的是 Self-Hosting 方式,这个程序集将会“消失”,关于 AspNet.Loader.dll,一篇很是好的解答文章:AspNet.Loader.dll – what is this for?app

另外,在 IIS 中部署 ASP.NET 5 应用程序,不像咱们以前的方式,直接把相应的文件和程序集拷贝到站点目录下,由于你会发现,在生成 ASP.NET 5 项目的时候没有生成对应的程序集,只是在 Bin 目录下有一个 AspNet.Loader.dll,dudu 已经试过在 ASP.NET 5 项目属性页的 Build 选项中,把“Produce outputs on build”选项打勾,就会生成相应的程序集文件(位置:../application/artifacts/bin),既然有了程序集,那是否是就能够像以前部署站点的方式进行操做呢?答案固然不是,这也就是为何手动复制文件会失败,由于 ASP.NET 5 并没想象中的那么简单,呵呵,采用 VS2015 的 Publish 方式部署是成功的,那咱们就从它下手,观察下它究竟是怎么回事,dudu 没作完这步,咱们下面接着作。asp.net

言归正传

用 VS2015 建立一个简单的 ASP.NET 5 项目:ide

142044235587081.png

project.json 配置:组件化

{
    "webroot": "wwwroot",
    "version": "1.0.0-*",
    "exclude": [
        "wwwroot"
    ],
    "dependencies": {
        "Microsoft.AspNet.Server.IIS": "1.0.0-beta1",
        "Microsoft.AspNet.Server.WebListener": "1.0.0-beta1",
        "HelloClassLibrary": "1.0.0-*"
    },
    "commands": {
        /* Change the port number when you are self hosting this application */
        "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000"
    },
    "frameworks": {
        "aspnet50": { },
        "aspnetcore50": { }
    }
}

Startup.cs 代码:

using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;

namespace HelloAspNet5
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            app.Run(context => context.Response.WriteAsync("Hello, ASP.NET 5 world! \{HelloClassLibrary.TestClass.testContent}"));
        }
    }
}

为了演示 ASP.NET 5 与依赖类库之间的关系,咱们还建立了一个 HelloClassLibrary 项目,并在 Startup 中进行调用。在 project.json 中配置 commands 是为了方便咱们经过 Publish 发布出来的程序检测是否能够正常运行。

Publish 发布文件结构:

142107056208797.png

approot 为程序文件及程序包目录,packages 下面是整个应用程序运行所须要的程序包,src 为程序源代码目录,wwwroot 为站点目录(咱们等下 IIS 部署的时候,就是指向的这个目录),里面有一个 bin 目录(只有一个 AspNet.Loader.dll)和一个 web.config 文件(里面主要配置一些地址路径,好比程序包的地址路径)。web.cmd 是批处理文件,它其实就是咱们在 commands 中制定的命令(还能够配置 EF 迁移的命令)。

142116091201222.png

上面是本地运行结果(注意,我并无安装 IIS),你也能够直接点击 web.cmd 来启动站点。

既然本机运行没问题,那咱们就把它发布到 IIS 上试试,可是却报下面的错误:

142126230899751.png

错误信息:Couldn't find package 'KRE-CLR-amd64.1.0.0-beta1'. Locations probed,什么意思?本机是 32 位系统,服务器是 64 位系统,发布设置咱们选的是“KRE-CLR-x86.1.0.0-beta1”,不报错才怪,从新更改发布设置为“KRE-CLR-amd64.1.0.0-beta1”:

142130181513804.png

而后把发布生成 HelloAspNet5.Web\approot\packages\KRE-CLR-amd64.1.0.0-beta1 下的文件,添加到服务器相应目录下,从新刷新浏览器,运行成功:

Hello, ASP.NET 5 world!  HeiHei

上面这些操做其实 dudu 已经完成了,而且也是成功的,但这并非咱们想要的,由于这时候,服务器运行的程序是“动态编译”的,程序代码地址就在 HelloAspNet5.Web\approot\src 目录下,里面直接是源代码,并非生成的程序集文件,那该如何“预编译”咱们的 ASP.NET 5 应用程序呢?

首先,咱们须要生成咱们的应用程序,就像咱们以前的 ASP.NET 应用程序同样,而 ASP.NET 5 默认是“动态编译”的,若是想设置成预编译,须要咱们手动设置一下:

142140003703300.png

在项目属性页的 Build 选择中,把“Produce outputs on build”打勾就能够了,HelloClassLibrary 类库项目一样这样设置,设置好了,从新生成项目,生成的程序集目录为:\HelloAspNet5\artifacts\bin\HelloAspNet5\Debug,在相应目录下,就会看到咱们想要的两个程序集文件:HelloAspNet5.dll 和 HelloClassLibrary.dll,既然项目程序集生成成功,那部署应该没有什么问题,但 dudu 已经尝试过,是失败的,问题出在哪?直接把相应的程序集文件拷贝过去不行吗?固然不行,由于咱们使用 VS2015 Publish 的时候,运行环境是“动态编译”,那怎么使 Pulish 的时候预编译呢?答案就在下面:

142150448392579.png

在 Publish 的时候,还有一个发布选项“Precompile during publishing”,就是配置预编译的,从新发布一下,你会发如今 packages 目录下多了两个文件夹:

142156570261772.png

这就是预编译生成的项目文件地址,咱们再来看下 HelloAspNet5 的文件目录:

142159322143029.png

一个是 lib 目录,里面就是生成的程序集文件,root 是程序的其余类型文件,好比 MVC Views 文件就在这里,而不是在 wwwroot 目录下。另一个很是重要的地方就是,wwwroot 下的 web.config 变成了:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="kpm-package-path" value="..\approot\packages" />
    <add key="bootstrapper-version" value="1.0.0-beta1" />
    <add key="kre-package-path" value="..\approot\packages" />
    <add key="kre-version" value="1.0.0-beta1" />
    <add key="kre-clr" value="CLR" />
    <add key="kre-app-base" />
  </appSettings>
</configuration>

好像也没怎么变化?跟以前的自习对比一下,会发现 key(kre-app-base)的 value 值不见了,以前的配置为

<add key="kre-app-base" value="..\approot\src\HelloAspNet5" />

看到这你应该懂了,没错,你能够把 approot\src 目录下的 HelloAspNet5 源代码文件删掉了,使用 k web 命令从新启用项目,运行成功:

Hello, ASP.NET 5 world!  HeiHei

接着咱们从新在服务器的 IIS 上也这样搞,可是却出现了下面的错误:

142211017293844.png

错误信息:Couldn't find package 'KRE-CLR-amd64.1.0.0-beta1',找不到“KRE-CLR-amd64.1.0.0-beta1”程序包,在 approot\packages 目录下明明就有啊,查看下面的提示发现 IIS 并无从这个目录下进行查找,怎么办?手动配置一下:

<add key="kre-app-base" value="..\approot\packages\HelloAspNet5\1.0.0\root"/>

须要注意的是,要配置到 root 目录下,从新启动项目,运行成功:

Hello, ASP.NET 5 world!  HeiHei

咱们接下来修改代码,而后经过编译程序集上传到 IIS 服务器。

app.Run(context => context.Response.WriteAsync("Hello, ASP.NET 5 world!!! \{HelloClassLibrary.TestClass.testContent}"));
public static string testContent = " HeiHeiHei";

能够看出,上面代码和以前的代码是有些不一样的,以前有说过使用 VS2015 编译的程序集地址为 artifacts,咱们把相应的程序集文件上传到服务器的 approot\packages 目录下,奇怪的事,我运行后发现改的代码并无效果,仍是以前的,这个问题搞了我好久,都快被搞死了,我觉得是生成的程序集文件有问题,没有生成最新的,就各类设置生成测试,最后仍是没有成功,而后无心间把 IIS 站点停掉,而后再进行上传程序集文件,最后再启动站点,刷新浏览器,你猜怎么着?Oh, My God !!!,竟然出现了:

Hello, ASP.NET 5 world!!!  HeiHeiHei

最后再啰嗦两句:

从上面整个配置过程当中能够看出,ASP.NET 5 是如何在 IIS 进行运行的(只是从 Publish 上来看),首先,站点目录为 wwwroot,包含一个 bin 目录的 AspNet.Loader.dll 文件(用来打通 IIS 和 Owin 组件之间的管道),还有一个 web.config 文件(主要配置程序包及应用程序路径地址),除此以外,还有一些静态文件(如 css、js 和图片文件),若是是动态编译站点,默认直接运行 approot\src 目录下的源代码文件,若是是预编译站点,根据 kre-app-base 的路径配置(如 approot\packages\HelloAspNet5\1.0.0\root),运行 ASP.NET 5 运行程序,注意在 root\project.json 文件中,有以下配置:"webroot": "..\..\..\..\..\wwwroot",这个指向的地址就是 IIS 站点。。。

其实,上面虽然只是一个简单的 IIS 部署过程,但涉及到很是多的东西,也有不少的感触,或许有些没表达出来,总的来讲,此次部署给我最重要的感觉是:ASP.NET 5 彻底的组件化,不仅是开发,部署也是如此,这样的结果就是充满着无限可能,看我七十二变!!!

相关文章
相关标签/搜索