从 ASP.NET MVC 和 Web API 升级到 ASP.NET Core MVC

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

使用 .NET 升级助手进行升级

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

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

增量更新

请按照 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 核心项目

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

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

将 ASP.NET 核心站点配置为使用 MVC

在 ASP.NET Core 3.0 或更高版本项目中,.NET Framework 不再是受支持的目标框架。 项目必须面向 .NET Core。 ASP.NET Core 共享框架(包括 MVC)是 .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 核心应用必须选择使用中间件加入框架功能。 上一个模板生成的代码添加以下服务和中间件:

此现有配置包括迁移示例 ASP.NET MVC 项目所需的内容。 有关 ASP.NET 核心中间件选项的详细信息,请参阅 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 核心项目中,右键单击 视图/Home 目录,选择“ 添加>现有项”。
  3. “添加现有项 ”对话框中,导航到 ASP.NET MVC WebApp1 项目的 视图/Home 目录。
  4. 选择 About.cshtml“, Contact.cshtml然后 Index.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 核心项目中,右键单击 wwwroot 目录,选择“ 添加>现有项”。
  2. “添加现有项 ”对话框中,导航到 ASP.NET MVC WebApp1 项目。
  3. 选择 favicon.ico 文件,然后选择 “添加”,替换现有文件。

迁移布局文件

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

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

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

  1. 在 ASP.NET 核心项目中,右键单击 视图/共享 目录,选择“ 添加>现有项”。
  2. “添加现有项 ”对话框中,导航到 ASP.NET MVC WebApp1 项目的 视图/共享 目录。
  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“新建项目”对话框

“新建 Web 应用程序”对话框:在 ASP.NET 模板面板中选择的 MVC 项目模板

自选: 将解决方案的名称从 WebApp1 更改为 Mvc5。 Visual Studio 显示新的解决方案名称(Mvc5),使得更容易区分这个项目和下一个项目。

创建 ASP.NET 核心项目

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

“新建项目”对话框

“新建 ASP.NET Web 应用程序”对话框:在“ASP.NET 核心模板”面板中选择的空项目模板

  • 自选: 使用 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 控制器和视图的占位符。

  • 添加 控制器 目录。

  • 添加一个名为 HomeController.csControllers 目录的控制器类

“添加新项”对话框中选择了 MVC 控制器类

  • 添加 视图 目录。

  • 添加 视图/Home 目录。

  • 将一个名为 Index.cshtml 的视图添加到 Views/Home 目录中。

“添加新项”对话框,其中已选择“MVC 视图”页

项目结构如下所示:

解决方案资源管理器显示 WebApp1 的文件和目录

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

<h1>Hello world!</h1>

运行应用。

在 Microsoft Edge 中打开 Web 应用

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

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

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

  • 控制器

  • 观看次数

  • 模型

  • 捆绑

  • 筛选器

  • 登录/注销, 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 核心项目中使用的端口号,从浏览器调用正在运行的 ASP.NET 核心应用上的呈现视图。 例如: https://localhost:44375/home/about

“联系人”页

请注意样式和菜单项的缺失。 下一部分将改进样式。

静态内容

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

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

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

迁移布局文件

  • _ViewStart.cshtml 文件从 ASP.NET MVC 项目的 Views 目录复制到 ASP.NET 核心项目的 “视图 ”目录中。 文件 _ViewStart.cshtml 在 ASP.NET Core MVC 中未更改。

  • 创建 视图/共享 目录。

  • 自选:FullAspNetCore MVC 项目的“视图”目录复制到 _ViewImports.cshtml ASP.NET 核心项目的“视图”目录中。 删除文件中的任何命名空间声明 _ViewImports.cshtml 。 该文件 _ViewImports.cshtml 提供所有视图文件的命名空间,并引入 标记帮助程序。 标签助手被用于新布局文件中。 该文件 _ViewImports.cshtml 是 ASP.NET Core 中的新文件。

  • _Layout.cshtml 文件从 ASP.NET MVC 项目的 Views/Shared 目录复制到 ASP.NET 核心项目的 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“新建项目”对话框

“新建 Web 应用程序”对话框:在 ASP.NET 模板面板中选择的 MVC 项目模板

自选: 将解决方案的名称从 WebApp1 更改为 Mvc5。 Visual Studio 显示新的解决方案名称(Mvc5),使得更容易区分这个项目和下一个项目。

创建 ASP.NET 核心项目

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

“新建项目”对话框

“新建 ASP.NET Web 应用程序”对话框:在“ASP.NET 核心模板”面板中选择的空项目模板

  • 自选: 使用 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 控制器和视图的占位符。

  • 添加 控制器 目录。

  • 添加一个名为 HomeController.csControllers 目录的控制器类

选择了 MVC 控制器类的“添加新项”对话框(在 ASP.NET Core 2.1 发布之前)

  • 添加 视图 目录。

  • 添加 视图/Home 目录。

  • 将一个名为 Index.cshtml 的视图添加到 Views/Home 目录中。

在“添加新项”对话框中,选择了“MVC 视图页面”(ASP.NET Core 2.1 发布之前)

项目结构如下所示:

解决方案资源管理器显示 WebApp1 的文件和目录

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

<h1>Hello world!</h1>

运行应用。

在 Microsoft Edge 中打开 Web 应用

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

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

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

  • 控制器

  • 观看次数

  • 模型

  • 捆绑

  • 筛选器

  • 登录/注销, 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 核心项目中使用的端口号,从浏览器调用正在运行的 ASP.NET 核心应用上的呈现视图。 例如: https://localhost:44375/home/about

“联系人”页

请注意样式和菜单项的缺失。 下一部分将改进样式。

静态内容

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

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

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

迁移布局文件

  • _ViewStart.cshtml 文件从 ASP.NET MVC 项目的 Views 目录复制到 ASP.NET 核心项目的 “视图 ”目录中。 文件 _ViewStart.cshtml 在 ASP.NET Core MVC 中未更改。

  • 创建 视图/共享 目录。

  • 自选:FullAspNetCore MVC 项目的“视图”目录复制到 _ViewImports.cshtml ASP.NET 核心项目的“视图”目录中。 删除文件中的任何命名空间声明 _ViewImports.cshtml 。 该文件 _ViewImports.cshtml 提供所有视图文件的命名空间,并引入 标记帮助程序。 标签助手被用于新布局文件中。 该文件 _ViewImports.cshtml 是 ASP.NET Core 中的新文件。

  • _Layout.cshtml 文件从 ASP.NET MVC 项目的 Views/Shared 目录复制到 ASP.NET 核心项目的 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 错误响应。 通常,错误详细信息不包括在这些响应中,以防止泄露有关服务器的潜在敏感信息。 有关详细信息,请参阅 开发人员异常页

其他资源