[VS2010 Online]解析Multi-Target與ASP.NET版本轉移的秘密

[VS2010 Online]解析Multi-Target與ASP.NET版本轉移的秘密

image

在Visual Studio 2008中, 就已經提供了Multi-Target的技術, 什麼是Multi-Target? 它又能做什麼呢?

 

在先前的Visual Studio 2005中, 因為不支援先前的版本, 這樣會對Visual Studio的使用者造成很大的困擾,

像是版本的相容性, 如果使用者不能夠拿新版的Visual Studio開發過去的.NET 2.0~ 3.5的專案, 這樣會讓多

少人跳腳呢?(我就會是其中之一), 因此, 根據這個需求才延伸出這個技術.

 

image

  • 圖1: .NET Framework 歷程.

 

過去, 你應該聽過.NET 3.0, 3.5, 3.5 SP1都是基於.NET 2.0, 這是什麼意思? 你有沒有發現IIS上的Framework設定

怎麼只有.NET Framework 2.0以及4.0(如果你有裝VS2010的話)?

 

讓我們來看看Multi-Target是怎麼處理的?

1. 首先,我們在VS2010中, 選擇C#的Web類型專案, 你會發現當你切換Framework版本時, 底下的專案樣板會有所不同.

(Framework 2.0)

image

 

 

 

 

 

(Framework 3.0), 這裡多出了WCF Service Application專案類型.

image

 

(Framework 3.5), 這裡多出了更多的專案類型.

image

 

(Framework 4.0), 跟3.5差不多, 只有多出一個Empty ASP.NET Web Application(這個專案類型只有在2.0跟4.0出現).

image

 

 

2. 我們新增一個Framework 2.0的Web Application的專案看看:

image

 

Web.Config: (看起來很清新阿)

   1: <?xml version="1.0"?>
   2: <configuration>
   3:     <appSettings/>
   4:     <connectionStrings/>
   5:     <system.web>
   6:         <!-- 
   7:             Set compilation debug="true" to insert debugging 
   8:             symbols into the compiled page. Because this 
   9:             affects performance, set this value to true only 
  10:             during development.
  11:         -->
  12:         <compilation debug="true">
  13:             <assemblies>
  14:             </assemblies>
  15:         </compilation>
  16:         <!--
  17:             The <authentication> section enables configuration 
  18:             of the security authentication mode used by 
  19:             ASP.NET to identify an incoming user. 
  20:         -->
  21:         <authentication mode="Windows"/>
  22:         <!--
  23:             The <customErrors> section enables configuration 
  24:             of what to do if/when an unhandled error occurs 
  25:             during the execution of a request. Specifically, 
  26:             it enables developers to configure html error pages 
  27:             to be displayed in place of a error stack trace.
  28: 
  29:         <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
  30:             <error statusCode="403" redirect="NoAccess.htm" />
  31:             <error statusCode="404" redirect="FileNotFound.htm" />
  32:         </customErrors>
  33:         -->
  34:         <pages/></system.web>
  35:     <system.codedom>
  36:     </system.codedom>
  37:     <!-- 
  38:         The system.webServer section is required for running ASP.NET AJAX under Internet
  39:         Information Services 7.0.  It is not necessary for previous version of IIS.
  40:     -->
  41:     <system.webServer>
  42:     </system.webServer>
  43: </configuration>

 

當你變更為.NET Framework版本時, 會出現:

image

 

當變更為3.0時, 參考的類別都與2.0相同.

image

 

Web.Config: (跟2.0一樣清新)

   1: <?xml version="1.0"?>
   2: <configuration>
   3:     <appSettings/>
   4:     <connectionStrings/>
   5:     <system.web>
   6:         <!-- 
   7:             Set compilation debug="true" to insert debugging 
   8:             symbols into the compiled page. Because this 
   9:             affects performance, set this value to true only 
  10:             during development.
  11:         -->
  12:         <compilation debug="true">
  13:             <assemblies>
  14:             </assemblies>
  15:         </compilation>
  16:         <!--
  17:             The <authentication> section enables configuration 
  18:             of the security authentication mode used by 
  19:             ASP.NET to identify an incoming user. 
  20:         -->
  21:         <authentication mode="Windows"/>
  22:         <!--
  23:             The <customErrors> section enables configuration 
  24:             of what to do if/when an unhandled error occurs 
  25:             during the execution of a request. Specifically, 
  26:             it enables developers to configure html error pages 
  27:             to be displayed in place of a error stack trace.
  28: 
  29:         <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
  30:             <error statusCode="403" redirect="NoAccess.htm" />
  31:             <error statusCode="404" redirect="FileNotFound.htm" />
  32:         </customErrors>
  33:         -->
  34:         <pages/></system.web>
  35:     <system.codedom>
  36:     </system.codedom>
  37:     <!-- 
  38:         The system.webServer section is required for running ASP.NET AJAX under Internet
  39:         Information Services 7.0.  It is not necessary for previous version of IIS.
  40:     -->
  41:     <system.webServer>
  42:     </system.webServer>
  43: </configuration>

 

 

當變更為3.5時, 參考的dll增加了System.Data.DataSetExtensions, System.Web.Extensions以及System.Xml.Linq.

執行的Framework runtime是2.0, 但是上述的三個dll是屬於3.5的版本.

image

 

Web.Config: (有沒有發現參考的dll中, 多出了四個, 除了剛剛上述的三個之外, 還包含了一個System.Core.dll, 這個dll內含了Linq的相關類別)

除此之外, web.config中也包含了一些extensions的設定.

   1: <?xml version="1.0"?>
   2: <configuration>
   3:     <configSections>
   4:         <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
   5:             <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
   6:                 <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
   7:                 <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
   8:                     <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
   9:                     <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
  10:                     <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
  11:                     <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/></sectionGroup></sectionGroup></sectionGroup></configSections><appSettings/>
  12:     <connectionStrings/>
  13:     <system.web>
  14:         <!-- 
  15:             Set compilation debug="true" to insert debugging 
  16:             symbols into the compiled page. Because this 
  17:             affects performance, set this value to true only 
  18:             during development.
  19:         -->
  20:         <compilation debug="true">
  21:             <assemblies>
  22:                 <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
  23:                 <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
  24:                 <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
  25:                 <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/></assemblies>
  26:         </compilation>
  27:         <!--
  28:             The <authentication> section enables configuration 
  29:             of the security authentication mode used by 
  30:             ASP.NET to identify an incoming user. 
  31:         -->
  32:         <authentication mode="Windows"/>
  33:         <!--
  34:             The <customErrors> section enables configuration 
  35:             of what to do if/when an unhandled error occurs 
  36:             during the execution of a request. Specifically, 
  37:             it enables developers to configure html error pages 
  38:             to be displayed in place of a error stack trace.
  39: 
  40:         <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
  41:             <error statusCode="403" redirect="NoAccess.htm" />
  42:             <error statusCode="404" redirect="FileNotFound.htm" />
  43:         </customErrors>
  44:         -->
  45:         <pages>
  46:             <controls>
  47:                 <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
  48:                 <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></controls></pages>
  49:         <httpHandlers>
  50:             <remove verb="*" path="*.asmx"/>
  51:             <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
  52:             <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
  53:             <add verb="GET,HEAD" path="ScriptResource.axd" validate="false" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></httpHandlers>
  54:         <httpModules>
  55:             <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></httpModules></system.web>
  56:     <system.codedom>
  57:             <compilers>
  58:                 <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" warningLevel="4">
  59:                     <providerOption name="CompilerVersion" value="v3.5"/>
  60:                     <providerOption name="WarnAsError" value="false"/></compiler></compilers></system.codedom>
  61:     <!-- 
  62:         The system.webServer section is required for running ASP.NET AJAX under Internet
  63:         Information Services 7.0.  It is not necessary for previous version of IIS.
  64:     -->
  65:     <system.webServer>
  66:             <validation validateIntegratedModeConfiguration="false"/>
  67:         <modules>
  68:             <remove name="ScriptModule"/>
  69:             <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></modules>
  70:         <handlers>
  71:             <remove name="WebServiceHandlerFactory-Integrated"/>
  72:             <remove name="ScriptHandlerFactory"/>
  73:             <remove name="ScriptHandlerFactoryAppServices"/>
  74:             <remove name="ScriptResource"/>
  75:             <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
  76:             <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
  77:             <add name="ScriptResource" verb="GET,HEAD" path="ScriptResource.axd" preCondition="integratedMode" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/></handlers></system.webServer>
  78:     <runtime>
  79:         <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
  80:             <dependentAssembly>
  81:                 <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
  82:                 <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/></dependentAssembly>
  83:             <dependentAssembly>
  84:                 <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
  85:                 <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/></dependentAssembly></assemblyBinding></runtime></configuration>

 

當變更為4.0時, 參考的dll增加了System.Web.DynamicData, System.Web.ApplicationServices以及System.Web.Entity.

從執行的Framework runtime是4.0看來, 很明顯的Framework 4.0是一個全新改寫的.Net Framework. (驗證了圖1的說明)

image

 

Web.Config: (看起來也清新多了, 但是你有沒有注意到兩個關鍵點- targetFramework以及controlRenderingCompatibilityVersion.

targetFramework: 預設值為「Null」, 可以填的值包含"2.0|3.0|3.5|4.0"(這部分是錯誤的, 請見註解1), 如果在Web.config省略這個屬性, 專案得執行就

會透過Web.config的其他設定或是專案所在的IIS的application pool決定.

 

controlRenderingCompatibilityVersion: Visual Studio會自動設定這個屬性為3.5, 如果你要利用ASP.NET 4.0對於XHTML改進的功能, 就可以移除這個屬性.

這個屬性主要是用來預防一些CSS或是Script的非預期行為, 讓它們能和先前版本相容.

   1: <?xml version="1.0"?>
   2: <configuration>
   3:     <appSettings/>
   4:     <connectionStrings/>
   5:     <system.web>
   6:         <!-- 
   7:             Set compilation debug="true" to insert debugging 
   8:             symbols into the compiled page. Because this 
   9:             affects performance, set this value to true only 
  10:             during development.
  11:         -->
  12:         <compilation debug="true" targetFramework="4.0">
  13:             <assemblies>
  14:                 
  15:                 
  16:                 
  17:                 </assemblies>
  18:         </compilation>
  19:         <!--
  20:             The <authentication> section enables configuration 
  21:             of the security authentication mode used by 
  22:             ASP.NET to identify an incoming user. 
  23:         -->
  24:         <authentication mode="Windows"/>
  25:         <!--
  26:             The <customErrors> section enables configuration 
  27:             of what to do if/when an unhandled error occurs 
  28:             during the execution of a request. Specifically, 
  29:             it enables developers to configure html error pages 
  30:             to be displayed in place of a error stack trace.
  31: 
  32:         <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
  33:             <error statusCode="403" redirect="NoAccess.htm" />
  34:             <error statusCode="404" redirect="FileNotFound.htm" />
  35:         </customErrors>
  36:         -->
  37:         <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/></system.web>
  38:     <system.codedom>
  39:     </system.codedom>
  40:     <!-- 
  41:         The system.webServer section is required for running ASP.NET AJAX under Internet
  42:         Information Services 7.0.  It is not necessary for previous version of IIS.
  43:     -->
  44:     <system.webServer>
  45:     </system.webServer>
  46: </configuration>

 

註解1:從compilation Element (ASP.NET Settings Schema), 我們可以看到可以填的值包含了"2.0|3.0|3.5|4.0", 但是事實上, 這部分是錯誤的,

當你把targetFramework的值改變為3.0, 當執行時, 你會看到下列訊息:

The 'targetFramework' attribute in the <compilation> element of the Web.config file is used only to target version 4.0 and later of the .NET Framework (for example, '<compilation targetFramework="4.0">'). If you are compiling this Web application for a version of the .NET Framework earlier than 4.0, remove the 'targetFramework' attribute from the <compilation> element of the Web.config file.

這說明這個屬性只能使用在4.0之後的版本.

 

 

Multi-Target技術是怎樣實作?

接下來, 讓我們來看看Multi-Target技術是怎樣實作的:

以2.0為例, 會使用到System.IO這個類別:

image

 

但是切換到3.5時, 因為System.IO功能上有所新增, MS將這些新增的功能放到System.Core.dll內.

image

 

 

 

所以在作Multi-Target切換時, 當你選擇2.0, 就不會引用到Syetem.Core.dll.

透過這樣的方式, 很容易地可以做到切換版本的功能, 而且也不會讓某一個dll變得臃腫肥大而難以切割.

 

 

當你有一個.Net 2.0~3.5的網站要轉換成.Net Framework 4.0的網站, 該怎麼做?

當你直接開啟一個4.0之前版本的Web Application專案時(我以2.0為例)

 

1. 出現轉換精靈.

image

 

2. 轉換時要不要備份?

image

 

3. 轉換前的一些summary.

image

 

4. 如果你在轉換的電腦上沒有安裝.Net Framework 3.5, 會跳出Project Target Framework Not Installed視窗, 你可以選擇

   Retarget the project to .NET Framework 4選項來繼續轉換的作業.

image

 

5. 問你是不是下定決心要轉換成.Net Framework 4.0?

image

 

 

 

6. 轉換完畢.

image

 

7. 轉換後的Web.config以及dll refrence都會被改成4.0版本.

 

 

然後記得IIS上的application pool也要改成指向.Net Framework 4.0:

1. 在網站上按滑鼠右鍵, 選擇Manage Application->Advanced Settings

 

image

 

2. 選擇Application Pool.

image

 

3. 選擇4.0版本的Application Pool.

image

 

這樣網頁就可以從4.0之前的版本轉換成4.0版本的網站.

 

 

 

隨文Tips:

在Visual Studio中, 我們可以看到很多快速鍵, 身為一個阿宅工程師, 每天都希望能增加自己的生產力, 背的越多, 寫的越快.

於是瘋狂快捷鍵魔人就這樣誕生了.

 

使用下列方法可以快速的產生快捷鍵列表:

1. 到Visual Studio 2010的功能表中的Tools, 選擇Macros, 然後選Macros IDE.

2. 然後你可以看到一個Visual Studio Macro Shell視窗出現.

3. 在視窗中填入下列程式碼:

   1: Imports System
   2: Imports EnvDTE
   3: Imports EnvDTE80
   4: Imports EnvDTE90
   5: Imports EnvDTE100
   6: Imports System.Diagnostics
   7: Imports System.IO
   8:  
   9: Public Module Module1
  10:  
  11:     Public Sub ListShortcutsInHTML()
  12:  
  13:         'Declare a StreamWriter
  14:         Dim sw As System.IO.StreamWriter
  15:         sw = New StreamWriter("d:\\Shortcuts.html")
  16:  
  17:         'Write the beginning HTML
  18:         WriteHTMLStart(sw)
  19:  
  20:         ' Add a row for each keyboard shortcut
  21:         For Each c As Command In DTE.Commands
  22:             If c.Name <> "" Then
  23:                 Dim bindings As System.Array
  24:                 bindings = CType(c.Bindings, System.Array)
  25:                 For i As Integer = 0 To bindings.Length - 1
  26:                     sw.WriteLine("<tr>")
  27:                     sw.WriteLine("<td>" + c.Name + "</td>")
  28:                     sw.WriteLine("<td>" + bindings(i) + "</td>")
  29:                     sw.WriteLine("</tr>")
  30:                 Next
  31:  
  32:             End If
  33:         Next
  34:  
  35:         'Write the end HTML
  36:         WriteHTMLEnd(sw)
  37:  
  38:         'Flush and close the stream
  39:         sw.Flush()
  40:         sw.Close()
  41:     End Sub
  42:     Public Sub WriteHTMLStart(ByVal sw As System.IO.StreamWriter)
  43:         sw.WriteLine("<html>")
  44:         sw.WriteLine("<head>")
  45:         sw.WriteLine("<title>")
  46:  
  47:         sw.WriteLine("Visual Studio Keyboard Shortcuts")
  48:         sw.WriteLine("</title>")
  49:         sw.WriteLine("</head>")
  50:  
  51:         sw.WriteLine("<body>")
  52:         sw.WriteLine("<h1>Visual Studio 2010 Keyboard Shortcuts</h1>")
  53:         sw.WriteLine("<font size=""2"" face=""Verdana"">")
  54:         sw.WriteLine("<table border=""1"">")
  55:         sw.WriteLine("<tr BGCOLOR=""#018FFF""><td align=""center""><b>Command</b></td><td align=""center""><b>Shortcut</b></td></tr>")
  56:  
  57:  
  58:     End Sub
  59:  
  60:     Public Sub WriteHTMLEnd(ByVal sw As System.IO.StreamWriter)
  61:         sw.WriteLine("</table>")
  62:         sw.WriteLine("</font>")
  63:         sw.WriteLine("</body>")
  64:         sw.WriteLine("</html>")
  65:     End Sub
  66:  
  67: End Module
  68:  

 

4. 執行這個macro shell, 然後你就可以發現在D槽下出現Shortcuts.html這個快捷鍵列表.

image

Enjoy it.

 

 

試煉大會, 下次見.

 

 

 

如果您有微軟技術開發的問題,可以到MSDN Forum發問。

如果您有微軟IT管理的問題,可以到TechNet Forum發問喔。