把ASP.NET MVC 3整合到现行的升级后的ASP.NET 4 Web Forms应用程序中

[原文发表地址] Integrating ASP.NET MVC 3 into existing upgraded ASP.NET 4 Web Forms applications

[原文发表时间] 2011-01-06 12:19 AM

我最近从一位先生那得到了一个有趣的问题,他有一个现行的运行良好的ASP.NET WebForms 2.0 application 。他将之升级到ASP.NET 4后依然运行良好,但如今他想要增加一些ASP.NET MVC页面进去。但他并不想重写这个应用。

几年前我发过一个关于 混合的”ASP.NET应用程序的帖子。其目的是强调这一点:你可以拥有既是WebForms又是MVC的ASP.NET应用程序(以及WCF和 ASMX网页服务等等)。虽然File|New Project对话框给了你一个可在This 和 That之间进行的选择,事实上这都是由ASP.NET所支配的。你尽可以混合及搭配"自助餐厅风格"且以任何你喜欢的组合来创建应用程序。

把ASP.NET MVC 3添加至升级过的ASP.NET 2.0 WebForms应用程序最简单的方法是:

·运行Upgrade Wizard(在Visual Studio 2010中打开Visual Studio2008 Web Application)

·创建一个供参考的默认ASP.NET MVC应用程序(不久你就可将之置之一边)

·使用诸如Beyond Compare的差分工具从ASP.NET MVC单元中把新的web.config条目整合到升级后的 ASP.NET WebForms应用程序中去

·运行成功

如下为上述的更长更为详细的版本。

升级ASP.NET 2.0 WebForms

应用

我创建了一个在.NET 2下运行的简易的Visual Studio 2008 ASP.NET WebForms Application。这是一个简易的计算器。

它运行良好。现在,在Visual Studio 2010里打开这个应用程序。你会看到Conversion/Upgrade Wizard。

依次点击“Next, Next, Yada, Yada, Yada, Finish”。你会得到一个将2.0 application升级.NET Framework 4的提示。点击Yes。

这是同样的、现在已经在Visual Studio 2010里升级过的WebForms应用程序。它依旧运行且仍然是WebForms。或者,更准确地说,它仍是ASP.NET。

我会采用一个新的ASP.NET MVC 3默认应用程序和Beyond Compare并将升级过的应用程序与默认应用程序进行比较。

我会复制这些文件和文件夹:

Content

Controllers

Models

Scripts

Views

Global.asax, Global.asax.cs

现在,这里是升级过后的程序里先前和之后的引用。左边的是旧的右边的是新的引用。

References

New References

这是我添加的引用。

Microsoft.CSharp

o (as this was a C# app)

System.Web.Mvc

o From \Program Files (x86)\Microsoft ASP.NET\ASP.NET MVC 3\Assemblies

System.Web.WebPages and System.Web.Razor

o From \Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies

System.ComponentModel.DataAnnotations

接下来,把这些单元添加至 Web.config。再次,使用拆分工具会更加容易一些,你可能会遇到一些困难和错误。

思考:这可能是一个不错的、可供人制作的NuGet程序包…

在 appSettings里添加这些设置:

<appSettings>

 

  <add key="ClientValidationEnabled" value="true"/>

 

  <add key="UnobtrusiveJavaScriptEnabled" value="true"/>

 

</appSettings>

 

把这些 assembly 元素添加至 compilation 下面:

<compilation debug="true" targetFramework="4.0">

 

  <assemblies>

 

    <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

 

    <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

 

    <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

 

    <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

 

    <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

 

  </assemblies>

 

</compilation >

 

把这些 namespaces添加到页面里:

<system.web>

 

  <pages>

 

    <namespaces>

 

      <add namespace="System.Web.Helpers" />

 

      <add namespace="System.Web.Mvc" />

 

      <add namespace="System.Web.Mvc.Ajax" />

 

      <add namespace="System.Web.Mvc.Html" />

 

      <add namespace="System.Web.Routing" />

 

      <add namespace="System.Web.WebPages"/>

 

    </namespaces>

 

  </pages>

 

</system.web>

 

如果你在某种情况下运行 IIS7,我确信你会的,请添加这些:

<system.webServer>

 

  <validation validateIntegratedModeConfiguration="false"/>

 

  <modules runAllManagedModulesForAllRequests="true"/>

 

</system.webServer>

 

最后添加assembly 绑定重定向,以防你在 Global Assembly Cache (GAC)里有 ASP.NET MVC 1 or 2 assemblies。

<configuration>

 

  <runtime>

 

    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

 

      <dependentAssembly>

 

        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />

 

        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />

 

      </dependentAssembly>

 

    </assemblyBinding>

 

  </runtime>

 

</configuration>

 

而且,确保你在 Global.asax.cs中合并以便使你的 Routes在应用程序启动中(被)注册。

public class SomeHybrid : System.Web.HttpApplication

{

 

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)

    {

 

        filters.Add(new HandleErrorAttribute());

 

    }

 

    public static void RegisterRoutes(RouteCollection routes)

    {

 

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

 

        routes.MapRoute(

 

        "Default", // Route name

 

        "{controller}/{action}/{id}", // URL with parameters

 

        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults

 

        );

 

    }

 

    protected void Application_Start()

    {

 

        AreaRegistration.RegisterAllAreas();

 

        RegisterGlobalFilters(GlobalFilters.Filters);

 

        RegisterRoutes(RouteTable.Routes);

 

    }

 

}

 

现在,基于这点两种页面我都可以访问。 WebForms页面是磁盘上的文件,因此当我访问 /default.aspx时,ASP.NET就会直接向这个页面发送请求。 ASP.NET 路由引擎已经启用,所以我也可以访问/Home/Index。

如果想做一些花样,我可以添加一个PageRoute,当访问我的 WebForms页面时也有漂亮的 URLs。就像这样,仅仅在 Global.asax里增加一个Route。确保这些简单Route会被首先考虑,因为默认 ASP.NET MVC Route非常地“贪婪”,它会抓住像 /calculator这样的简易 URL。

1

routes.MapPageRoute("WebFormThing", "Calculator", "~/Default.aspx");

现在我可以访问/Calculator,并且请求被发送到/Default.aspx。当然,我的 ASP.NET MVC 3 Razor页面同样喜欢/Home/Index工作。

最后,只是想指出,靠近一个Razor 页面源的是从我的新应用程序的WebForms部分来的Default.aspx。

您可以拥有这一切,亲爱的读者们。用得开心!