《Pro ASP.NET MVC 3 Framework》学习笔记之三十五 【部署】

准备要部署的应用程序

在正式进入部署MVC程序到IIS之前,会介绍一些关于应用程序迁移到生产环境之前探测错误以及一旦进入生产环境最大化性能的技术。同时也会展示关于流线型部署过程的有用的功能。

 

检测视图错误

Razor视图会在服务器需要的时候编译而不是在VS里面生成项目时编译,正常情况下,探测视图编译错误的方式是系统的访问每一个action,从而让每一个view都能够呈现。这显然是非常乏味而且不会一直成功的技术,特别是在基于不同的model状态呈现不同的view的时候。
我们可以启用一个特别的项目选项来启用我们的视图并且报告任何编译错误。我们可以编辑一个.csproj的文件,设置MvcBuildViews为true,如下:
...
  <PropertyGroup>
    .....
    <MvcBuildViews>true</MvcBuildViews>
  </PropertyGroup>
...
这样保存以后,任何编译错误都会显示出来了。注意,这种方式只是检查编译错误,不能检测逻辑错误并且不能用来替代严格的测试体制。

 

配置动态页编译(Configuring Dynamic Page Compilation)

Web.config里面一个重要的配置是compilation节,如下:
<configuration>
    <!-- other settings removed for clarity -->
    <system.web>
        <compilation debug="true" targetFramework="4.0">
        <assemblies>
            <add assembly="System.Web.Abstractions, Version=4.0 ...
            ...

在前面提到过,Razor视图是在运行时编译成.NET类的。这里的compilation配置节决定是在debug模式还是release模式执行,在开发过程中倾向于使用debug模式,该模式会让编译器做如下工作:
1.忽略代码优化以至于让编译器能够一行一行的进行编译。
2.编译请求的视图而不是在一个批次编译所有的视图
3.禁用请求超时,让我们可以长时间处于调试阶段
4.限制浏览器缓存的途径
这些都是在开发应用程序中非常有用的功能,但是这些功能会影响部署时的性能。解决的方法就是在部署时设置为:<compilation debug="true"  targetFramework="4.0">

 

准备一个Bin部署(Preparing for a Bin Deployment)

可以将程序部署到任何安装了ASP.NET4的IIS服务器上,即使是MVC 3的框架没有安装也可以。我们通过执行一个bin部署的操作来实现,MVC框架需要的程序集会包含在bin文件夹里面。具体操作如:在项目名称右键——>添加可部署的依赖项——>选中ASP.NET MVC——>确定,VS会自动添加一个名为  _bin_deployableAssemblies文件夹到项目里面,这里文件夹里面包含了MVC3和Razor需要的程序集。当我们编译程序时,这些程序集会拷贝到bin目录下,部署时就拷贝到服务器上。这意味着无论MVC3程序集是否在服务器的GAC里安装,我们的程序都会运行成功。

 

准备转换的Web.config(Preparing the Web.config  File for Transformation)

当我们部署一个应用时,通常会修改Web.config里面的部分配置节。VS提供了非常使用的功能让我们可以在不同的部署周期里生成不同版本的Web.config。在解决方案里面展开Web.config可以看到两个文件:Web.Debug.config和Web.Release.config,这两个文件对应Debug和Release两种配置。

View Code

<?xml version="1.0" encoding="utf-8"?>

<!-- 有关使用 web.config 转换的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=125889 -->

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--
    在下例中,“SetAttributes”转换将更改
    “connectionString”的值,仅在“Match”定位器
    查找到值为“MyDB”的特性“name”时使用“ReleaseSQLServer”。

    <connectionStrings>
      <add name="MyDB"
        connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
        xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
    </connectionStrings>
  -->
  <system.web>
    <compilation xdt:Transform="RemoveAttributes(debug)" />
    <!--
      在下例中,“Replace”转换将替换
      web.config 文件的整个 <customErrors> 节。
      请注意,由于
      在 <system.web> 节点下仅有一个 customErrors 节,因此不需要使用“xdt:Locator”特性。

      <customErrors defaultRedirect="GenericError.htm"
        mode="RemoteOnly" xdt:Transform="Replace">
        <error statusCode="500" redirect="InternalError.htm"/>
      </customErrors>
    -->
  </system.web>
</configuration>

上面的第二个转换是移除debug属性。这里我们实验一下,现在把上面的关于连接字符串的那部分注释去掉如下:

View Code

<?xml version="1.0" encoding="utf-8"?>

<!-- 有关使用 web.config 转换的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=125889 -->

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--
    在下例中,“SetAttributes”转换将更改
    “connectionString”的值,仅在“Match”定位器
    查找到值为“MyDB”的特性“name”时使用“ReleaseSQLServer”。
      -->
    <connectionStrings>
      <add name="conn"
        connectionString="server=localhost;uid=root;pwd=****;database=sportsstore;"
        xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
    </connectionStrings>

  <system.web>
    <compilation xdt:Transform="RemoveAttributes(debug)" />
    <!--
      在下例中,“Replace”转换将替换
      web.config 文件的整个 <customErrors> 节。
      请注意,由于
      在 <system.web> 节点下仅有一个 customErrors 节,因此不需要使用“xdt:Locator”特性。

      <customErrors defaultRedirect="GenericError.htm"
        mode="RemoteOnly" xdt:Transform="Replace">
        <error statusCode="500" redirect="InternalError.htm"/>
      </customErrors>
    -->
  </system.web>
</configuration>

然后把解决方案配置改成Release模式,然后发布。这时打开Web.config可以看到连接字符串已经替换了,而且<compilation/>里面的debug也移除了。如下:

ps:到现在才知道Web.Release.config和Web.Debug.config是这么用的,之前都是部署了以后再去改连接字符串(太土了~~)。
下面会接着介绍应用到web.config的其他转换。

 

理解转换结构(Understanding the Transformation Structure)

转换文件基本结构跟Web.config相似。我们定义配置元素然后替换想转换的。转换文件的大致结构如下:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings>
    ...字符串转换部分...
  </connectionStrings>
  <system.web>
    ...编译转换部分...
  </system.web>
</configuration>
对于每一个我们想要执行的转换,都定义了目标元素,必要的转换类型,以及任何转换需要的值。例如,要转换编译属性,那么就定义一个如下的转换:
<compilation xdt:Transform="RemoveAttributes(debug)" />
上面指明了我们想对Web.config里面的compilation节进行转换,使用的是RemoveAttributes转换并传入debug属性。
发布之前为<compilation debug="true" targetFramework="4.0">,发布之后为<compilation targetFramework="4.0">。下面的列表展示了支持的转换:

转换 描述
Insert 向Web.config插入元素
InsertBefore
InsertAfter
在指定的元素之前或之后插入
Remove 移除单个元素
RemoveAll 移除所有跟包含的元素同名的元素
RemoveAttributes 从包含的元素移除属性集合
SetAttributes 设置一个或多个属性的值
Replace 替换元素集合

 

 

 

 

 

 

 

 

 

下面对每一个转换进行介绍

 

插入配置元素

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings>
    <add name="NewConnection" connectionString="MyConnectionString" xdt:Transform="Insert"/>
  </connectionStrings>
</configuration> 

展示的结果为:

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <add name="SportsStoreEntities"
         connectionString="provider connection string=
         &quot;Data Source=xTITAN\SQLEXPRESS;User ID=adam;Password=adam;&quot;"
         providerName="System.Data.EntityClient" />
    <add name="NewConnection" connectionString="MyConnectionString"/>
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral" />
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral" />
      </assemblies>
    </compilation>
  </system.web>
</configuration> 

还可以使用InsertBefore和InsertAfter来控制插入的位置:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings> 

    <add name="NewConnection" connectionString="MyConnectionString"
       xdt:Transform
        ="InsertBefore(/configuration/connectionStrings/add[@name='SportsStoreEntities'])"/> 

    <add name="OtherConnection" connectionString="MyOtherConnectionString"
       xdt:Transform
        ="InsertAfter(/configuration/connectionStrings/add[@name='NewConnection'])"/> 

  </connectionStrings>
</configuration> 

InsertBefore和InsertAfter转换需要一个参数来指明插入的相对位置。参数使用了XPath语法,点这里了解XPath语法
展示执行结果:

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <add name="NewConnection" connectionString="MyConnectionString"/>
    <add name="OtherConnection" connectionString="MyOtherConnectionString"/>
    <add name="SportsStoreEntities"
         connectionString="provider connection string=
         &quot;Data Source=TITAN\SQLEXPRESS;User ID=adam;Password=adam;&quot;"
         providerName="System.Data.EntityClient" />
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral" />
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral" />
      </assemblies>
    </compilation>
  </system.web>
</configuration> 

移除配置元素

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.web>
    <compilation>
      <assemblies>
        <add xdt:Transform="Remove"/>
      </assemblies>
    </compilation>
  </system.web>
</configuration> 

Remove转换会匹配集合区域的所有Add元素,当有一个或多个元素匹配时,仅仅第一个被移除。执行结果如下:

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
      <add name="conn" connectionString="server=localhost;uid=root;pwd=***;database=sportsstore;"/>
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>         //移除的add        <!--<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral" />-->
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral" />
      </assemblies>
    </compilation>
  </system.web>
</configuration> 

要移除多个元素,可以使用RemoveAll转换。

 

设置/移除属性

可以使用SetAttributes和RemoveAttributes两个转换来操作Web.config里面的属性:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings>
    <add name="SportStoreEntities" xdt:Transform="SetAttributes(connectionString)"
       connectionString="MyNewConnection"/>
  </connectionStrings>
  <system.web>
    <compilation xdt:Transform="RemoveAttributes(targetFramework)"  />
  </system.web>
</configuration> 

第一个转换会改变连接字符串的值,第二个转换会移除了targetFramework属性。结果如下:

View Code

<?xml version="1.0"?> 

<configuration>
  <connectionStrings>
    <add name="SportsStoreEntities"
         connectionString="MyNewConnection"
         providerName="System.Data.EntityClient" />
  </connectionStrings> 

  <system.web>
    <compilation debug="true">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral" />
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral" />
      </assemblies>
    </compilation>
  </system.web> 

</configuration> 

替换元素

可以使用Replace转换来替换Web.config整个节,如:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings xdt:Transform="Replace">
    <add name="MyFirstConnection" connectionString="MyConnection1"/>
    <add name="MySecondConnection" connectionString="MyConnection2"/>
    <add name="MyThirdConnection" connectionString="MyConnection2"/>
  </connectionStrings>
</configuration>

在上面的例子里,我们替换了包含了在connectionStrings元素里面的所有元素:结果如下

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <add name="MyFirstConnection" connectionString="MyConnection1"/>
    <add name="MySecondConnection" connectionString="MyConnection2"/>
    <add name="MyThirdConnection" connectionString="MyConnection2"/>
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral" />
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral" />
      </assemblies>
    </compilation>
  </system.web>
</configuration> 

 

使用定位属性

Locator属性让我们能够更加明确我们所感兴趣的一个或多个元素。下面是一个没有使用Locator属性例子:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add xdt:Transform="Remove"/>
      </assemblies>
    </compilation>
  </system.web>
</configuration> 

这里会从assemblies区域移除add。正如我们前面提到的,Remove转换会移除找到的第一个元素,如果使用RemoveAll又会移除所有的元素。如果我们想移除匹配的元素中的一个时,可以使用Locator属性。如:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
 <system.web>
   <compilation debug="true" targetFramework="4.0">
     <assemblies>
      <add xdt:Transform="Remove" xdt:Locator="Condition(contains(@assembly,'Helpers'))" />
     </assemblies>
   </compilation>
 </system.web>
</configuration> 

这里指定Locator的值就限制了转换的元素是包含了Helpers的assembly属性。我们指定的表达式是联合了转换元素的路径,转换路径为:/configuration/compilation/assemblies/add并且有一个匹配assembly属性。Locator提供了三种模式供我们选择:

模式 用法 描述
Condition xdt:Locator="Condition(相对XPath表达式)" 联合相对的XPath表达式隐含转换元素的路径来限制元素的筛选
XPath xdt:Locator="XPath(绝对XPath表达式)" 应用绝对的XPath表达式来限制元素的筛选
Match xdt:Locator="Match(属性名)" 限制具有跟转换元素属性值匹配的元素的筛选

 

 

 

当我们使用Condition模式时,可以使用XPath运算符如contains,starts-with来创建更加复杂的搜索模式,还可以使用or和and运算符来创建复合表达式。如:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings>
    <add xdt:Transform="SetAttributes(connectionString)" connectionString="MyConnection"
         xdt:Locator=
          "Condition(starts-with(@name, 'Sports') and contains(@providerName, 'Entity'))"/>
  </connectionStrings>
</configuration> 

XPath模式允许我们指定一个绝对XPath表达式,如:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings>
    <add xdt:Transform="SetAttributes(connectionString)" connectionString="MyConnection"
         xdt:Locator=
          "XPath(/configuration/connectionStrings/add[starts-with(@name, 'Sports') and
              contains(@providerName, 'Entity')])"/>
  </connectionStrings>
</configuration> 

如果我们的目标是匹配具体的属性值,那么我们能使用Match模式,如下:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings>
    <add xdt:Transform="SetAttributes(connectionString)" connectionString="MyConnection"
         xdt:Locator="Match(name, providerName)"
         name="SportsStoreEntities"
         providerName="System.Data.EntityClient"/>
  </connectionStrings>
</configuration> 

Match模式需要一个或多个属性名作为参数,匹配Web.config中具有同样属性名和相同路径的元素。本例中,指定name和providerName,这意味着转换会对具有路径
/configuration/connectionStrings/add,并且具有一个值为SportsStoreEntities的name属性以及具有值为System.Data.EntityClient的providerName属性执行。

 

准备项目的数据库部署

另一个非常出色的部署功能是把数据库部署作为项目的一部分。我们可以选择从我们开发的数据库复制架构和/或数据到生产环境。
开始,设置项目为Release模式。接着在项目右键——>Properties——>Package/Publish Web并选中Include all databases configures in Package/Publish SQL如下:

然后转向Package/Publish SQL属性页,点击Import from  Web.config按钮,导入数据库连接字符串:


然后输入目标数据库连接字符串,然后选择部署什么,如下:

理解IIS基本原理
IIS是内置在Windows操作系统里的应用程序服务器,下面会介绍IIS的运行的背景。

理解Web站点
IIS能够同时寄宿多个独立的Web站点,对每一个站点必须指定根路径,这样IIS就会找到该文件下的无论是静态的还是动态的内容。为了将实际的请求导向一个实际的站点,IIS允许我们配置绑定,每一个绑定为IP地址,TCP端口映射所有的请求

理解虚拟目录
作为一个额外的配置级别,我们可以在一个web站点文件夹层级下的任何位置添加虚拟目录。每一个虚拟目录可以让IIS从一些其他的文件或网络路径获取内容并且就像这些内容是实际的在web站点的根文件夹下的虚拟目录呈现一样。如下:


每一个虚拟目录被标记为一个独立的应用,获取各自的配置和状态。相比它的父站点,它能够运行不同版本的ASP.NET.

 

理解应用程序池

IIS支持应用程序池的机制将运行在同一服务器的web应用程序隔离开,每一个程序启动一个独立的进程(包括具有不同的进程标识,最大内存使用,最大CPU使用,处理回收计划等等)。每一个站点被指派到应用程序池中的一个,如果其中一个应用崩溃了,其他的应用不会受到影响。由于同一台服务器可能寄宿多个站点,这就需要分派请求到正确的站点:我们可以绑定站点到一个或多个由下面三个部分构成的组合:
1.端口号(大多数都是80)  2.Hostname   3.IP地址

 

后续的对IIS的操作均跟之前在Webform里面的操作一样,安装部署Webform的方式就行了。所以后面的笔记略去,如果大家在实际的操作有什么问题,欢迎留言讨论!
今天特意看了第一篇笔记的时间2011-11-30,整个笔记到今天为止近7个月的时间,现在告于段落。感谢园友的支持,谢谢!接下来我打算学习nopcommerce这个开源项目来加深MVC的学习。希望已经接触了该开源项目的同学能够提供资源或学习建议,谢谢!

时间: 2024-08-23 01:18:03

《Pro ASP.NET MVC 3 Framework》学习笔记之三十五 【部署】的相关文章

ASP.NET MVC 3 Framework学习笔记之Model Templates

.使用模板化的视图Helpers(Using Templated View Helpers) 模版化视图helpers的创意就是它们更加灵活.我们不用自己去指定应该用什么HTML元素来呈现一个模型的属性,MVC自己会搞定,在我们更新了视图模型时,也不用手动的更新视图.下面是一个例子:  代码如下 复制代码 //在Models里面添加Persons.cs using System; using System.Collections.Generic; using System.Linq; using

《Pro ASP.NET MVC 3 Framework》学习笔记目录

<Pro ASP.NET MVC 3 Framework>简介: 作者: Adam Freeman 和 Steven Sanderson 出版社: Apress; New 平装: 820页 语种: 英语 ISBN: 1430234040 声明:笔记里面按我自己的理解翻译了大部分内容,写这个笔记的目的:为了方便自己查阅,也为园友提供学习的方便. 我无意侵犯作者的任何权利,仅仅为了自己学习.也希望路过的朋友不要用于任何商业目的. 第一部分 ASP.NET MVC3介绍   <Pro ASP.

《Pro ASP.NET MVC 3 Framework》学习笔记之一【MVC的历程,优点,HelloWorld】

序论:asp.net mvc出现已经有两三年的时间了(2009开始1.0版本),但是这么方面的中文学习资料仍然非常少,特别是asp.net mvc3,几乎就没有中文的学习书籍.在英文的书籍中有两本是非常经典的mvc3教程:<Professional ASP.NET MVC 3>--作者:Jon Galloway , Phil Haack, Brad Wilson , K. Scott Allen和<Pro ASP.NET MVC 3 Framework>--作者:Steven Sa

ASP.NET MVC Web API 学习笔记----HttpClient简介

  1. HttpClient简单介绍  依稀还记得那个时候用WebClient,HttpWebRequest来发送一个请求,现在ASP.NET MVC4中自带了一个类HttpClient,用于接收HttpResponseMessage和发送HttpRequestMesssage. 问题在于既然WebClient,HttpWebRequest可以完成相应的功能,为什么还要使用HttpClient类,.NET Framework中既然提出了这样一个类肯定是有其特别之处的,这里罗列几个不同之处: (

ASP.NET MVC Web API 学习笔记---联系人增删改查

本章节简单介绍一下使用ASP.NET MVC Web API 做增删改查.目前很多Http服务还是通过REST或者类似RESP的模型来进行数据操作的.下面我们通过创建一个简单的Web API来管理联系人          说明:为了方便数据不使用真正的数据库,而是通过内存数据模拟    1.       Web API中包含的方法 Action HTTP method Relative URI GetAllContact GET /api/contact GetContact GET /api/

《Pro ASP.NET MVC 3 Framework》学习笔记之九【Ninject的使用-下】

接着上次的Ninject的笔记,如果你是初次路过,可以先看看我前面的笔记. 一,创建依赖链(Chains of Dependency) 当我们向Ninject请求创建一个类型时,Ninject会去检查该类型和其他类型之间的耦合关系.如果有额外的依赖,Ninject也会解析它们并创建我们需要的所有类的实例.为了进一步说明,我们创建一个新的接口和一个实现该接口的类.请注意我们的例子是跟前面的笔记衔接的,所以如果你打算跟着一起操作的话,最好能够去看看前面的笔记. 创建一个IDiscountHelper

《Pro ASP.NET MVC 3 Framework》学习笔记之四【领域模型介绍】

主题:应用领域驱动开发(Applying Domain-Driven Development) Domain Model是MVC程序的"心脏",其他的一切,包括Controllers和Views仅仅是用来跟Domain Model交互的一种方式,ASP.NET MVC并没有限制使用在Domain Model上面的技术,我们可以自由的选择跟.net framework交互的技术,并且这样的选择是非常多的.不仅如此,ASP.NET MVC为我们提供了基础的架构和约定来帮助Domain Mo

《Pro ASP.NET MVC 3 Framework》学习笔记之五【依赖注入及ninject工具使用】

一,创建松耦合的组件 1."分解关注点"是MVC模式里面一个非常重要的特性.我们想要在应用程序里面创建的组件尽可能的独立,这样我们就能管理比较少的依赖关系.理想情况下,每个组件都是孤立的,不知道其他组件的存在,处理应用程序的其他领域仅仅通过抽象接口,这就是所谓的松耦合,它让我们的应用程序更加容易测试和修改.通过一个简单的例子可以帮助我们理解,假如我们想写一个发邮件的组件,暂且就把这个组件命名为MyEmailSender,接着我们实现一个接口,这个接口定义了所有需要发送邮件的功能,也暂且

《Pro ASP.NET MVC 3 Framework》学习笔记之十五【示例项目SportsStore】

绑定Shopping Cart 定义购物车Cart的实体,购物车是我们程序业务领域的一个部分,所以在我们领域模型(Domain Model)里面添加一个cart的实体是合理的.在SportsStore.Domain的Entities文件夹下添加一个Cart的实体类,如下所示: View Code public class Cart {private List<CartLine> lineCollection = new List<CartLine>();//添加 public vo