将 ASP.NET Framework Web Forms 应用升级到 ASP.NET Core MVC

本文介绍如何使用 Visual Studio .NET 升级助手增量更新方法将 ASP.NET Framework Web Forms 升级到 ASP.NET Core MVC。

如果 .NET Framework 项目在解决方案中具有所需的支持库,则应将其升级到 .NET Standard 2.0(如果可能)。 有关详细信息,请参阅升级支持库

  1. 安装 .NET 升级助手 Visual Studio 扩展。
  2. 在 Visual Studio 中打开 ASP.NET Web Forms 解决方案。
  3. 在“解决方案资源管理器”中,右键单击要升级的项目,然后选择“升级”。 选择“并行增量项目升级”,这是唯一的升级选项。
  4. 对于升级目标,请选择“新建项目”。
  5. 命名项目并选择 ASP.NET Core 模板,然后选择“下一步
  6. 选择目标框架版本,然后选择“下一步”。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略
  7. 选择“完成”,然后选择“完成”。
  8. 摘要”步骤显示“<Framework Project> 现在通过 Yarp 代理连接到 <Framework ProjectCore>”。
  9. 选择要升级的组件,然后选择“升级选择”。

增量更新

按照从 ASP.NET 到 ASP.NET Core 的增量迁移入门中的步骤继续更新过程。

本文介绍如何开始将 ASP.NET MVC 项目迁移到 ASP.NET Core MVC。 在此过程中,它会突出显示 ASP.NET MVC 中的相关更改。

从 ASP.NET MVC 迁移涉及多个步骤。 本文介绍:

  • 初始设置。
  • 基本控制器和视图。
  • 静态内容。
  • 客户端依赖项。

有关迁移配置和 Identity 代码,请参阅将配置迁移到 ASP.NET Core将身份验证和 Identity 迁移到 ASP.NET Core

先决条件

创建起始 ASP.NET MVC 项目

在 Visual Studio 中创建 ASP.NET MVC 项目示例来进行迁移:

  1. 从“文件”菜单中选择“新建”>“项目” 。
  2. 选择“ASP.NET Web 应用程序(.NET Framework)”,然后选择“下一步”。
  3. 将项目命名为 WebApp1,使命名空间与下一步中创建的 ASP.NET Core 项目相匹配。 选择创建
  4. 选择“MVC”,然后选择“创建”。

创建 ASP.NET Core 项目

使用新的 ASP.NET Core 项目创建要迁移到的新的解决方案:

  1. 启动 Visual Studio 的第二个实例。
  2. 从“文件”菜单中选择“新建”>“项目” 。
  3. 选择“ASP.NET Core Web 应用程序”,然后选择“下一步”
  4. 在“配置新项目”对话框中,将项目命名为“WebApp1”。
  5. 将位置设置为与上一个项目不同的目录,以使用相同的项目名称。 使用同一个命名空间可更轻松地在两个项目之间复制代码。 选择创建
  6. 在“创建新的 ASP.NET Core Web 应用程序”对话框中,确认选择“.NET Core”和“ASP.NET Core 3.1” 。 选择“Web 应用程序(模型-视图-控制器)”项目模板,然后选择“创建”。

将 ASP.NET Core 网站配置为使用 MVC

在 ASP.NET Core 3.0 及更高版本中,.NET Framework 不再是受支持的目标框架。 你的项目必须面向 .NET Core。 包含 MVC 的 ASP.NET Core 共享框架是 .NET Core 运行时安装的一部分。 使用项目文件中的 Microsoft.NET.Sdk.Web SDK 时,会自动引用共享框架:

<Project Sdk="Microsoft.NET.Sdk.Web">

有关详细信息,请查看框架参考

在 ASP.NET Core 中,Startup 类:

  • 替换 Global.asax。
  • 处理所有应用启动任务。

有关详细信息,请参阅 ASP.NET Core 中的应用启动

在 ASP.NET Core 项目中,打开 Startup.cs 文件:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

ASP.NET Core 应用必须选择使用包含中间件的框架功能。 上一个模板生成的代码会添加以下服务和中间件:

该现有配置包括迁移 ASP.NET MVC 项目示例迁移所需的信息。 若要详细了解 ASP.NET Core 中间件选项,请参阅 ASP.NET Core 中的应用启动

迁移控制器和视图

在 ASP.NET Core 项目中,会使用与要从中迁移的任何 ASP.NET MVC 项目中的控制器和视图类相同的名称添加新的空控制器和视图类来充当占位符。

ASP.NET Core WebApp1 项目已包含与 ASP.NET MVC 同名的最小示例控制器和视图。 因此,它们将用作要从 ASP.NET MVC WebApp1 项目迁移的 ASP.NET MVC 控制器和视图的占位符。

  1. 复制 ASP.NET MVC HomeController 中的方法来替换新的 ASP.NET Core HomeController 方法。 无需更改操作方法的返回类型。 ASP.NET MVC 内置模板的控制器操作方法返回类型为 ActionResult;在 ASP.NET Core MVC 中,操作方法改为返回 IActionResultActionResult 可实现 IActionResult
  2. 在 ASP.NET Core 项目中,右键单击 Views/Home 目录,然后选择“添加”>“现有项”。
  3. 在“添加现有项”对话框中,导航到 ASP.NET MVC WebApp1 项目的 Views/Home 目录。
  4. 选择 About.cshtmlContact.cshtmlIndex.cshtmlRazor 视图文件,然后选择“添加”,替换现有文件。

有关详细信息,请参阅使用 ASP.NET Core MVC 中的控制器处理请求ASP.NET Core MVC 中的视图

测试每个方法

可测试每个控制器终结点,不过本文档的稍后部分介绍了布局和样式。

  1. 运行 ASP.NET Core 应用。
  2. 通过将当前端口号替换为 ASP.NET Core 项目中使用的端口号,在运行 ASP.NET Core 应用的浏览器中调用呈现的视图。 例如 https://localhost:44375/home/about

迁移静态内容

在 ASP.NET MVC 5 及更早版本中,静态内容是从 Web 项目的根目录承载的,与服务器端文件混合。 在 ASP.NET Core 中,静态文件存储在项目的 Web 根目录中。 默认目录是 {content root}/wwwroot,但可更改它。 有关详细信息,请参阅 ASP.NET Core 中的静态文件

将 ASP.NET MVC WebApp1 项目中的静态内容复制到 ASP.NET Core WebApp1 项目中的 wwwroot 目录:

  1. 在 ASP.NET Core 项目中,右键单击 wwwroot 目录,然后选择“添加”>“现有项”。
  2. 在“添加现有项”对话框中,导航到 ASP.NET MVC WebApp1 项目。
  3. 选择 favicon.ico 文件,然后选择“添加”来替换现有文件。

迁移布局文件

将 ASP.NET MVC 项目布局文件复制到 ASP.NET Core 项目:

  1. 在 ASP.NET Core 项目中,右键单击 Views 目录,然后选择“添加”>“现有项”。
  2. 在“添加现有项”对话框中,导航到 ASP.NET MVC WebApp1 项目的 Views 目录。
  3. 选择 _ViewStart.cshtml 文件,然后选择“添加”。

将 ASP.NET MVC 项目共享布局文件复制到 ASP.NET Core 项目:

  1. 在 ASP.NET Core 项目中,右键单击 Views/Shared 目录,然后选择“添加”>“现有项”。
  2. 在“添加现有项”对话框中,导航到 ASP.NET MVC WebApp1 项目的 Views/Shared 目录。
  3. 选择 _Layout.cshtml 文件,然后选择“添加”来替换现有文件。

在 ASP.NET Core 项目中,打开 _Layout.cshtml 文件。 进行以下更改,使其与下述已补全的代码相匹配:

更新 Bootstrap CSS 包含项,使其与下面已补全的代码相匹配:

  1. @Styles.Render("~/Content/css") 替换为 <link> 元素以加载 bootstrap.css(请参阅下文)。
  2. 删除 @Scripts.Render("~/bundles/modernizr")

Bootstrap CSS 包含项已补全的替换标记:

<link rel="stylesheet"
    href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css"
    integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
    crossorigin="anonymous">

更新 jQuery 和 Bootstrap JavaScript 包含项,使其与下面已补全的代码相匹配:

  1. @Scripts.Render("~/bundles/jquery") 替换为 <script> 元素(见下文)。
  2. @Scripts.Render("~/bundles/bootstrap") 替换为 <script> 元素(见下文)。

JQuery 和 Bootstrap JavaScript 包含项已补全的替换标记:

<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"
    integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

更新的 _Layout.cshtml 文件如下所示:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    <link rel="stylesheet"
          href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
          crossorigin="anonymous">
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                </ul>
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>

    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"
            integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
    @RenderSection("scripts", required: false)
</body>
</html>

在浏览器中查看站点。 它应采用部署的预期样式进行呈现。

配置捆绑和缩小

ASP.NET Core 与若干开源捆绑和缩小解决方案(例如 WebOptimizer 和其他类似库)兼容。 ASP.NET Core 不提供本机捆绑和缩小解决方案。 若要了解如何配置捆绑和缩小,请参阅捆绑和缩小

解决 HTTP 500 错误

有许多问题可能会导致 HTTP 500 错误消息,该消息中不包含问题根源的相关信息。 例如,如果 Views/_ViewImports.cshtml 文件包含项目中没有的命名空间,则会生成 HTTP 500 错误。 默认情况下,在 ASP.NET Core 应用中,UseDeveloperExceptionPage 扩展会添加到 IApplicationBuilder 中,并在环境设为“开发”时执行。 详见以下代码:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

ASP.NET Core 会将未经处理的异常转换为 HTTP 500 错误响应。 通常,为防止泄露有关服务器的可能敏感信息,这些响应中不包含错误详细信息。 有关详细信息,请参阅开发人员异常页面

后续步骤

其他资源

本文介绍如何开始将 ASP.NET MVC 项目迁移到 ASP.NET Core MVC 2.2。 在此过程中,它突出显示了与 ASP.NET MVC 相比出现更改的很多内容。 从 ASP.NET MVC 迁移涉及多个步骤。 本文介绍:

  • 初始设置
  • 基本控制器和视图
  • 静态内容
  • 客户端依赖项。

有关迁移配置和 Identity 代码,请参阅将配置迁移到 ASP.NET Core将身份验证和 Identity 迁移到 ASP.NET Core

注意

示例中的版本号可能不是最新的,请相应地更新项目。

创建起始 ASP.NET MVC 项目

为了演示升级,我们首先创建一个 ASP.NET MVC 应用。 使用名称 WebApp1 来创建它,使命名空间与下一步中创建的 ASP.NET Core 项目相匹配。

Visual Studio New Project dialog

New Web Application dialog: MVC project template selected in ASP.NET templates panel

可选:将解决方案的名称从 WebApp1 更改为 Mvc5。 Visual Studio 会显示新的解决方案名称 (Mvc5),便于更轻松从下一项目告知此项目。

创建 ASP.NET Core 项目

使用与上一项目 (WebApp1) 相同的名称创建一个新的空 ASP.NET Core Web 应用,使两个项目中的命名空间匹配。 具有同一个命名空间可更轻松地在两个项目之间复制代码。 在与上一项目不同的目录中创建此项目来使用相同名称。

New Project dialog

New ASP.NET Web Application dialog: Empty project template selected in ASP.NET Core Templates panel

  • 可选:使用“Web 应用程序”项目模板创建新的 ASP.NET Core 应用。 将项目命名为 WebApp1,然后选择个人用户帐户的身份验证选项。 将该应用重命名为 FullAspNetCore。 创建此项目将在转换时节省时间。 可在模板生成的代码中查看最终结果,可将代码复制到转换项目,或者将代码与模板生成的项目进行比较。

将站点配置为使用 MVC

  • 在以 .NET Core 为目标时,默认引用 Microsoft.AspNetCore.App 元包。 此包中有 MVC 应用通常使用的包。 如果以 .NET Framework 为目标,则必须在项目文件中单独列出包引用。

Microsoft.AspNetCore.Mvc 是 ASP.NET Core MVC 框架。 Microsoft.AspNetCore.StaticFiles 是静态文件处理程序。 ASP.NET Core 应用明确选择用于中间件,例如用于提供静态文件。 有关详细信息,请参阅静态文件

  • 打开 Startup.cs 文件,并更改代码来匹配以下内容:
public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

UseStaticFiles 扩展方法会添加静态文件处理程序。 有关详细信息,请参阅应用程序启动路由

添加控制器和视图

在本部分中,将添加最小控制器和视图,用作在下一部分中迁移的 ASP.NET MVC 控制器和视图的占位符。

  • 添加 Controllers 目录。

  • 将名为 HomeController.cs控制器类添加到 Controllers 目录中。

Add New Item dialog with MVC Controller Class selected

  • 添加 Views 目录。

  • 添加 Views/Home 目录。

  • 将名为 Index.cshtmlRazor 视图添加到 Views/Home 目录中。

Add New Item dialog with MVC View Page selected

项目结构如下所示:

Solution Explorer showing files and directories of WebApp1

Views/Home/Index.cshtml 文件的内容替换为以下标记:

<h1>Hello world!</h1>

运行应用。

Web app open in Microsoft Edge

有关详细信息,请参阅控制器视图

以下功能要求从 ASP.NET MVC 项目示例迁移到 ASP.NET Core 项目:

  • 客户端内容(CSS、字体和脚本)

  • 控制器

  • 视图

  • 模型

  • 捆绑

  • filters

  • 登录/注销,Identity(在下一教程中完成此操作。)

控制器和视图

  • 将 ASP.NET MVC HomeController 中的每个方法复制到新的 HomeController。 在 ASP.NET MVC 中,内置模板的控制器操作方法返回类型为 ActionResult;在 ASP.NET Core MVC 中,操作方法改为返回 IActionResultActionResult 会实现 IActionResult,因此无需更改操作方法的返回类型。

  • About.cshtmlContact.cshtmlIndex.cshtmlRazor 视图文件从 ASP.NET MVC 项目复制到 ASP.NET Core 项目。

测试每个方法

尚未迁移布局文件和样式,因此呈现的视图仅包含视图文件中的内容。 AboutContact 视图的布局文件生成的链接尚不可用。

通过将当前端口号替换为 ASP.NET Core 项目中使用的端口号,在运行 ASP.NET Core 应用的浏览器中调用呈现的视图。 例如:https://localhost:44375/home/about

Contact page

请注意缺少样式和菜单项。 下一部分将解决样式问题。

静态内容

在 ASP.NET MVC 5 及更早版本中,静态内容从 Web 项目的根目录承载,与服务器端文件混合。 在 ASP.NET Core 中,静态内容托管在 wwwroot 目录中。 将 ASP.NET MVC 应用中的静态内容复制到 ASP.NET Core 项目中的 wwwroot 目录。 在此示例转换中:

  • 将 ASP.NET MVC 项目中的 favicon.ico 文件复制到 ASP.NET Core 项目中的 wwwroot 目录。

ASP.NET MVC 项目使用 Bootstrap 进行样式设置,并且将 Bootstrap 文件存储在 Content 和 Scripts 目录中。 生成了 ASP.NET MVC 项目的模板会引用布局文件 (Views/Shared/_Layout.cshtml) 中的 Bootstrap。 可将 bootstrap.jsbootstrap.css 文件从 ASP.NET MVC 项目复制到新项目中的 wwwroot 目录。 本文档改为在下一部分中使用 CDN 添加对 Bootstrap(和其他客户端库)的支持。

迁移布局文件

  • _ViewStart.cshtml 文件从 ASP.NET MVC 项目的 Views 目录复制到 ASP.NET Core 项目的 Views 目录。 _ViewStart.cshtml 文件在 ASP.NET Core MVC 中保持不变。

  • 创建 Views/Shared 目录。

  • 可选:_ViewImports.cshtmlFullAspNetCore MVC 项目的 Views 目录复制到 ASP.NET Core 项目的 Views 目录中。 删除 _ViewImports.cshtml 文件中的任何命名空间声明。 _ViewImports.cshtml 文件提供所有视图文件的命名空间,并引入标记帮助程序。 标记帮助程序在新的布局文件中使用。 对于 ASP.NET Core 来说,_ViewImports.cshtml 文件是新文件。

  • _Layout.cshtml 文件从 ASP.NET MVC 项目的 Views/Shared 目录复制到 ASP.NET Core 项目的 Views/Shared 目录。

打开 _Layout.cshtml 文件并进行以下更改(补全的代码如下所示):

  • @Styles.Render("~/Content/css") 替换为 <link> 元素以加载 bootstrap.css(请参阅下文)。

  • 删除 @Scripts.Render("~/bundles/modernizr")

  • 注释掉 @Html.Partial("_LoginPartial") 行(在行两侧添加 @*...*@)。 有关详细信息,请参阅将身份验证和 Identity 迁移到 ASP.NET Core

  • @Scripts.Render("~/bundles/jquery") 替换为 <script> 元素(见下文)。

  • @Scripts.Render("~/bundles/bootstrap") 替换为 <script> 元素(见下文)。

Bootstrap CSS 包含项的替换标记:

<link rel="stylesheet"
    href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css"
    integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
    crossorigin="anonymous">

JQuery 和 Bootstrap JavaScript 包含项的替换标记:

<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"
    integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

更新的 _Layout.cshtml 文件如下所示:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    <link rel="stylesheet"
          href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
          crossorigin="anonymous">
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                </ul>
                @*@Html.Partial("_LoginPartial")*@
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>

    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"
            integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
            crossorigin="anonymous"></script>
    @RenderSection("scripts", required: false)
</body>
</html>

在浏览器中查看站点。 现在,它应会正确加载,预期样式部署到位。

  • 可选:尝试使用新的布局文件。 从 FullAspNetCore 项目复制布局文件。 新的布局文件使用标记帮助程序,并进行了其他改进。

配置捆绑和缩小

若要了解如何配置捆绑和缩小,请参阅捆绑和缩小

解决 HTTP 500 错误

有许多问题可能会导致 HTTP 500 错误消息,该消息中不包含问题根源的相关信息。 例如,如果 Views/_ViewImports.cshtml 文件包含项目中没有的命名空间,则会生成 HTTP 500 错误。 默认情况下,在 ASP.NET Core 应用中,UseDeveloperExceptionPage 扩展会添加到 IApplicationBuilder 中,并在配置设为“开发”时执行。 请参阅以下代码中的示例:

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

ASP.NET Core 会将未经处理的异常转换为 HTTP 500 错误响应。 通常,为防止泄露有关服务器的可能敏感信息,这些响应中不包含错误详细信息。 有关详细信息,请参阅开发人员异常页面

其他资源

本文介绍如何开始将 ASP.NET MVC 项目迁移到 ASP.NET Core MVC 2.1。 在此过程中,它突出显示了与 ASP.NET MVC 相比出现更改的很多内容。 从 ASP.NET MVC 迁移涉及多个步骤。 本文介绍:

  • 初始设置
  • 基本控制器和视图
  • 静态内容
  • 客户端依赖项。

有关迁移配置和 Identity 代码,请参阅将配置迁移到 ASP.NET Core将身份验证和 Identity 迁移到 ASP.NET Core

注意

示例中的版本号可能不是最新的,请相应地更新项目。

创建起始 ASP.NET MVC 项目

为了演示升级,我们首先创建一个 ASP.NET MVC 应用。 使用名称 WebApp1 来创建它,使命名空间与下一步中创建的 ASP.NET Core 项目相匹配。

Visual Studio New Project dialog

New Web Application dialog: MVC project template selected in ASP.NET templates panel

可选:将解决方案的名称从 WebApp1 更改为 Mvc5。 Visual Studio 会显示新的解决方案名称 (Mvc5),便于更轻松从下一项目告知此项目。

创建 ASP.NET Core 项目

使用与上一项目 (WebApp1) 相同的名称创建一个新的空 ASP.NET Core Web 应用,使两个项目中的命名空间匹配。 具有同一个命名空间可更轻松地在两个项目之间复制代码。 在与上一项目不同的目录中创建此项目来使用相同名称。

New Project dialog

New ASP.NET Web Application dialog: Empty project template selected in ASP.NET Core Templates panel

  • 可选:使用“Web 应用程序”项目模板创建新的 ASP.NET Core 应用。 将项目命名为 WebApp1,然后选择个人用户帐户的身份验证选项。 将该应用重命名为 FullAspNetCore。 创建此项目将在转换时节省时间。 可在模板生成的代码中查看最终结果,可将代码复制到转换项目,或者将代码与模板生成的项目进行比较。

将站点配置为使用 MVC

  • 在以 .NET Core 为目标时,默认引用 Microsoft.AspNetCore.App 元包。 此包中有 MVC 应用通常使用的包。 如果以 .NET Framework 为目标,则必须在项目文件中单独列出包引用。

Microsoft.AspNetCore.Mvc 是 ASP.NET Core MVC 框架。 Microsoft.AspNetCore.StaticFiles 是静态文件处理程序。 ASP.NET Core 应用明确选择用于中间件,例如用于提供静态文件。 有关详细信息,请参阅静态文件

  • 打开 Startup.cs 文件,并更改代码来匹配以下内容:
public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

UseStaticFiles 扩展方法会添加静态文件处理程序。 UseMvc 扩展方法会添加路由。 有关详细信息,请参阅应用程序启动路由

添加控制器和视图

在本部分中,将添加最小控制器和视图,用作在下一部分中迁移的 ASP.NET MVC 控制器和视图的占位符。

  • 添加 Controllers 目录。

  • 将名为 HomeController.cs控制器类添加到 Controllers 目录中。

Add New Item dialog with MVC Controller Class selected (prior to the release of ASP.NET Core 2.1)

  • 添加 Views 目录。

  • 添加 Views/Home 目录。

  • 将名为 Index.cshtmlRazor 视图添加到 Views/Home 目录中。

Add New Item dialog with MVC View Page selected (prior to the release of ASP.NET Core 2.1)

项目结构如下所示:

Solution Explorer showing files and directories of WebApp1

Views/Home/Index.cshtml 文件的内容替换为以下标记:

<h1>Hello world!</h1>

运行应用。

Web app open in Microsoft Edge

有关详细信息,请参阅控制器视图

以下功能要求从 ASP.NET MVC 项目示例迁移到 ASP.NET Core 项目:

  • 客户端内容(CSS、字体和脚本)

  • 控制器

  • 视图

  • 模型

  • 捆绑

  • filters

  • 登录/注销,Identity(在下一教程中完成此操作。)

控制器和视图

  • 将 ASP.NET MVC HomeController 中的每个方法复制到新的 HomeController。 在 ASP.NET MVC 中,内置模板的控制器操作方法返回类型为 ActionResult;在 ASP.NET Core MVC 中,操作方法改为返回 IActionResultActionResult 会实现 IActionResult,因此无需更改操作方法的返回类型。

  • About.cshtmlContact.cshtmlIndex.cshtmlRazor 视图文件从 ASP.NET MVC 项目复制到 ASP.NET Core 项目。

测试每个方法

尚未迁移布局文件和样式,因此呈现的视图仅包含视图文件中的内容。 AboutContact 视图的布局文件生成的链接尚不可用。

  • 通过将当前端口号替换为 ASP.NET Core 项目中使用的端口号,在运行 ASP.NET Core 应用的浏览器中调用呈现的视图。 例如:https://localhost:44375/home/about

Contact page

请注意缺少样式和菜单项。 下一部分将解决样式问题。

静态内容

在 ASP.NET MVC 5 及更早版本中,静态内容从 Web 项目的根目录承载,与服务器端文件混合。 在 ASP.NET Core 中,静态内容托管在 wwwroot 目录中。 将 ASP.NET MVC 应用中的静态内容复制到 ASP.NET Core 项目中的 wwwroot 目录。 在此示例转换中:

  • 将 ASP.NET MVC 项目中的 favicon.ico 文件复制到 ASP.NET Core 项目中的 wwwroot 目录。

ASP.NET MVC 项目使用 Bootstrap 进行样式设置,并且将 Bootstrap 文件存储在 Content 和 Scripts 目录中。 生成了 ASP.NET MVC 项目的模板会引用布局文件 (Views/Shared/_Layout.cshtml) 中的 Bootstrap。 可将 bootstrap.jsbootstrap.css 文件从 ASP.NET MVC 项目复制到新项目中的 wwwroot 目录。 本文档改为在下一部分中使用 CDN 添加对 Bootstrap(和其他客户端库)的支持。

迁移布局文件

  • _ViewStart.cshtml 文件从 ASP.NET MVC 项目的 Views 目录复制到 ASP.NET Core 项目的 Views 目录。 _ViewStart.cshtml 文件在 ASP.NET Core MVC 中保持不变。

  • 创建 Views/Shared 目录。

  • 可选:_ViewImports.cshtmlFullAspNetCore MVC 项目的 Views 目录复制到 ASP.NET Core 项目的 Views 目录中。 删除 _ViewImports.cshtml 文件中的任何命名空间声明。 _ViewImports.cshtml 文件提供所有视图文件的命名空间,并引入标记帮助程序。 标记帮助程序在新的布局文件中使用。 对于 ASP.NET Core 来说,_ViewImports.cshtml 文件是新文件。

  • _Layout.cshtml 文件从 ASP.NET MVC 项目的 Views/Shared 目录复制到 ASP.NET Core 项目的 Views/Shared 目录。

打开 _Layout.cshtml 文件并进行以下更改(补全的代码如下所示):

  • @Styles.Render("~/Content/css") 替换为 <link> 元素以加载 bootstrap.css(请参阅下文)。

  • 删除 @Scripts.Render("~/bundles/modernizr")

  • 注释掉 @Html.Partial("_LoginPartial") 行(在行两侧添加 @*...*@)。 有关详细信息,请参阅将身份验证和 Identity 迁移到 ASP.NET Core

  • @Scripts.Render("~/bundles/jquery") 替换为 <script> 元素(见下文)。

  • @Scripts.Render("~/bundles/bootstrap") 替换为 <script> 元素(见下文)。

Bootstrap CSS 包含项的替换标记:

<link rel="stylesheet"
    href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css"
    integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
    crossorigin="anonymous">

JQuery 和 Bootstrap JavaScript 包含项的替换标记:

<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"
    integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

更新的 _Layout.cshtml 文件如下所示:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    <link rel="stylesheet"
          href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
          crossorigin="anonymous">
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                </ul>
                @*@Html.Partial("_LoginPartial")*@
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>

    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js"
            integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
            crossorigin="anonymous"></script>
    @RenderSection("scripts", required: false)
</body>
</html>

在浏览器中查看站点。 现在,它应会正确加载,预期样式部署到位。

  • 可选:尝试使用新的布局文件。 从 FullAspNetCore 项目复制布局文件。 新的布局文件使用标记帮助程序,并进行了其他改进。

配置捆绑和缩小

若要了解如何配置捆绑和缩小,请参阅捆绑和缩小

解决 HTTP 500 错误

有许多问题可能会导致 HTTP 500 错误消息,该消息中不包含问题根源的相关信息。 例如,如果 Views/_ViewImports.cshtml 文件包含项目中没有的命名空间,则会生成 HTTP 500 错误。 默认情况下,在 ASP.NET Core 应用中,UseDeveloperExceptionPage 扩展会添加到 IApplicationBuilder 中,并在配置设为“开发”时执行。 请参阅以下代码中的示例:

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

ASP.NET Core 会将未经处理的异常转换为 HTTP 500 错误响应。 通常,为防止泄露有关服务器的可能敏感信息,这些响应中不包含错误详细信息。 有关详细信息,请参阅开发人员异常页面

其他资源