本文介绍如何开始将 ASP.NET MVC 项目迁移到 ASP.NET Core MVC。 在此过程中,它会突出显示 ASP.NET MVC 中的相关更改。
从 ASP.NET MVC 迁移涉及多个步骤。 本文介绍:
- 初始设置。
- 基本控制器和视图。
- 静态内容。
- 客户端依赖项。
如需迁移配置和 Identity 代码,请参阅Identity 和Migrate Authentication and Identity to ASP.NET Core。
先决条件
- 具有“ASP.NET 和 Web 开发”工作负载的 Visual Studio 2019 16.4 或更高版本
- .NET Core 3.1 SDK
创建起始 ASP.NET MVC 项目
在 Visual Studio 中创建 ASP.NET MVC 项目示例来进行迁移:
- 从“文件”菜单中选择“新建”“项目”。
- 选择“ASP.NET Web 应用程序(.NET Framework)”,然后选择“下一步”。
- 将项目命名为 WebApp1,使命名空间与下一步中创建的 ASP.NET Core 项目相匹配。 选择“创建”。
- 选择“MVC”,然后选择“创建”。
创建 ASP.NET Core 项目
使用新的 ASP.NET Core 项目创建要迁移到的新的解决方案:
- 启动 Visual Studio 的第二个实例。
- 从“文件”菜单中选择“新建”“项目”。
- 选择“ASP.NET Core Web 应用程序”,然后选择“下一步” 。
- 在“配置新项目”对话框中,将项目命名为“WebApp1”。
- 将位置设置为与上一个项目不同的目录,以使用相同的项目名称。 使用同一个命名空间可更轻松地在两个项目之间复制代码。 选择“创建”。
- 在“创建新的 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 时,会自动引用共享框架:XML复制
<Project Sdk="Microsoft.NET.Sdk.Web">
有关详细信息,请查看框架参考。
在 ASP.NET Core 中,Startup
类:
- 替换 Global.asax。
- 处理所有应用启动任务。
有关详细信息,请参阅 ASP.NET Core 中的应用启动。
在 ASP.NET Core 项目中,打开 Startup.cs 文件:C#复制
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 应用必须选择使用包含中间件的框架功能。 上一个模板生成的代码会添加以下服务和中间件:
- AddControllersWithViews 扩展方法为控制器、API 相关功能和视图注册 MVC 服务支持。 若要详细了解 MVC 服务注册选项,请参阅 MVC 服务注册
- UseStaticFiles 扩展方法会添加静态文件处理程序
Microsoft.AspNetCore.StaticFiles
。 在UseRouting
之前,必须先调用UseStaticFiles
扩展方法。 有关详细信息,请参阅 ASP.NET Core 中的静态文件。 - UseRouting 扩展方法会添加路由。 有关详细信息,请参阅 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 控制器和视图的占位符。
- 复制 ASP.NET MVC
HomeController
中的方法来替换新的 ASP.NET CoreHomeController
方法。 无需更改操作方法的返回类型。 ASP.NET MVC 内置模板的控制器操作方法返回类型为 ActionResult;在 ASP.NET Core MVC 中,操作方法改为返回IActionResult
。ActionResult
可实现IActionResult
。 - 在 ASP.NET Core 项目中,右键单击 Views/ 目录,然后选择“添加”“现有项”。
- 在“添加现有项”对话框中,导航到 ASP.NET MVC WebApp1 项目的 Views/ 目录。
- 选择 About.cshtml、Contact.cshtml 和 Index.cshtml 视图文件,然后选择“添加”,替换现有文件。
有关详细信息,请参阅使用 ASP.NET Core MVC 中的控制器处理请求和 ASP.NET Core MVC 中的视图。
测试每个方法
可测试每个控制器终结点,不过本文档的稍后部分介绍了布局和样式。
- 运行 ASP.NET Core 应用。
- 通过将当前端口号替换为 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 目录:
- 在 ASP.NET Core 项目中,右键单击 wwwroot 目录,然后选择“添加”“现有项”。
- 在“添加现有项”对话框中,导航到 ASP.NET MVC WebApp1 项目。
- 选择 favicon.ico 文件,然后选择“添加”来替换现有文件。
迁移布局文件
将 ASP.NET MVC 项目布局文件复制到 ASP.NET Core 项目:
- 在 ASP.NET Core 项目中,右键单击 Views 目录,然后选择“添加”“现有项”。
- 在“添加现有项”对话框中,导航到 ASP.NET MVC WebApp1 项目的 Views 目录。
- 选择 _ViewStart.cshtml 文件,然后选择“添加”。
将 ASP.NET MVC 项目共享布局文件复制到 ASP.NET Core 项目:
- 在 ASP.NET Core 项目中,右键单击 Views/Shared 目录,然后选择“添加”“现有项”。
- 在“添加现有项”对话框中,导航到 ASP.NET MVC WebApp1 项目的 Views/Shared 目录。
- 选择 _Layout.cshtml 文件,然后选择“添加”来替换现有文件。
在 ASP.NET Core 项目中,打开 _Layout.cshtml 文件。 进行以下更改,使其与下述已补全的代码相匹配:
更新 Bootstrap CSS 包含项,使其与下面已补全的代码相匹配:
- 将
@Styles.Render("~/Content/css")
替换为<link>
元素来加载 bootstrap.css(见下文)。 - 删除
@Scripts.Render("~/bundles/modernizr")
。
Bootstrap CSS 包含项已补全的替换标记:HTML复制
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
更新 jQuery 和 Bootstrap JavaScript 包含项,使其与下面已补全的代码相匹配:
- 将
@Scripts.Render("~/bundles/jquery")
替换为<script>
元素(见下文)。 - 将
@Scripts.Render("~/bundles/bootstrap")
替换为<script>
元素(见下文)。
JQuery 和 Bootstrap JavaScript 包含项已补全的替换标记:HTML复制
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
更新后的 _Layout.cshtml 文件如下所示: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.min.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>© @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.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
中,并在环境设为“开发”时执行。 详见以下代码:C#复制
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 错误响应。 通常,为防止泄露有关服务器的可能敏感信息,这些响应中不包含错误详细信息。