65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET Core 入门 - 一个示例的最小 MVC 应用程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (26投票s)

2016年10月25日

CPOL

12分钟阅读

viewsIcon

44556

downloadIcon

391

在本文中,我将尝试介绍创建可移植的 (Windows, Mac 和 Linux) ASP.NET Core 应用程序的大部分基础知识,并讨论使用 ASP.NET Core 的 Web 应用程序的可能用例。

引言

.NET Core 已经发布,目前关于它的内容还不多。在本文中,我将尝试介绍创建可移植的 (Windows, Mac 和 Linux) ASP.NET Core 应用程序的大部分基础知识,并讨论使用 ASP.NET Core 的 Web 应用程序的可能用例。

背景

如果您真的要阅读本文,您需要基本了解 .NET Core 是什么,以及它与经典 (“真正”的) .NET Framework 有何不同。

我为您搜集了一些关于这个主题的资源

最后,Scott 像往常一样很好地总结了这一点

Scott Hanselmann:

我觉得这是多年来在 .NET 和开源方面工作的结晶。这就是我来微软工作的原因;我们希望尽可能多地开源,并在微软的 .NET 和开源周围建立一个社区。15 年后,经过成千上万人的努力,今天我们发布了 .NET Core 1.0

[...]

.NET Core 的主要优点是

  • 跨平台: 运行于 Windows、macOS 和 Linux。
  • 灵活部署: 可以包含在您的应用程序中,也可以按用户或按计算机侧边栏安装。
  • 命令行工具: 所有产品场景都可以通过命令行执行。
  • 兼容: .NET Core 与 .NET Framework、Xamarin 和 Mono 兼容,通过 .NET 标准库
  • 开源: .NET Core 平台是开源的,使用 MIT 和 Apache 2 许可证。文档的许可协议为 CC-BY。.NET Core 是一个 .NET 基金会项目。
  • 由微软支持: .NET Core 由微软支持,根据 .NET Core 支持

.NET Core 由以下部分组成

  • 一个 .NET 运行时,它提供类型系统、程序集加载、垃圾回收器、原生互操作和其他基本服务。
  • 一组 框架库,它们提供基本数据类型、应用程序组合类型和基本实用工具。
  • 一套 SDK 工具语言编译器,它们支持基本的开发体验,可在 .NET Core SDK 中获得。
  • ‘dotnet’ 应用程序宿主,用于启动 .NET Core 应用程序。它选择并托管运行时,提供程序集加载策略并启动应用程序。相同的宿主也用于以相同方式启动 SDK 工具。

现在,您为什么要优先选择 ASP.NET Core 而不是经典的 ASP.NET 应用程序?

或者更重要的是:什么时候?
似乎有无数种用例可以同时使用两者。我将专注于那些明确的。以下列表绝不完整,但这在 IT 领域很多事情上都是如此。

何时使用 ASP.NET Core?我无法给出“永远如此”的答案。但让我们看一个例子

佳能 Scanfront 400 是佳能开发的小型工业扫描仪。它可以扫描任何类型的文档,甚至护照和信用卡。他们发布了一个 视频 演示了酒店前台的用法。

OMR 应用程序(可用于处理扫描的图像)可以用来解释图像中的某些值(例如护照或信用卡号),并在扫描仪屏幕上显示需要验证的图像片段。设备本身运行在 Linux 上,可以使用 Eclipse/Java 进行编程,但这可能会很繁琐。与其编写一个特定的程序,不如在它后面放一个 ASP.NET Core 网页,显示片段并要求用户进行验证操作。这一点的最大优点是:您无需安装另一个 SDK。一个自托管的 ASP.NET Core 应用程序甚至可以在医疗应用中使用(例如,读取实验室订单并将其输入到实验室信息系统中),而无需实际安装(甚至更昂贵:维护)IIS 服务器 - 任何系统管理员告诉他“嘿,我们需要另一个服务器/另一个应用程序实例”时都会持怀疑态度。

这一点已经提出了要点:如果您有一个小型 Web 应用程序并将其开发为不依赖 IIS 的独立应用程序,那么将其销售给没有现场 IIS 的客户的机会将大大增加。

总之:ASP.NET Core 是一种可能的解决方案,无论/何时 Web 应用程序将运行的环境是

  1. 平台无关(客户 A 在 Linux 上运行,客户 B 在 Windows 上运行)或
  2. 严格监管(国防、医疗或金融环境)或
  3. 根本没有维护 IIS 实例的专业知识(或者相应地缺乏时间来维护)

我们开始吧

但首先,检查您是否已准备就绪。ASP.NET Core 需要一些先决条件才能运行 - 在 .NET Core 页面 上查看。该页面会自动显示您使用浏览网站的系统开发 ASP.NET Core 所需的内容。

如果您已从 .NET Core 页面安装了所有必需的工具,请打开 Visual Studio 并创建一个新的 .NET Core 控制台应用程序

如果一切设置正确,您将在“创建项目”向导的“模板树视图”中看到“.NET Core”子部分。

从那里,选择 控制台应用程序 (.NET Core)
侧边提示:本文是关于 ASP.Net Core 的入门指南,如果您真的想亲身体验,您可能会选择 ASP.Net Core Web 应用程序

创建项目后,您可以在解决方案资源管理器中看到项目结构,如下图所示。首先,我们必须将注意力放在 project.json 文件上。开始时,文件如下所示

{
  "version": "1.0.0-*",
  "buildOptions": {
    "emitEntryPoint": true
  },

  "dependencies": {
    "Microsoft.NETCore.App": {
      "type": "platform",
      "version": "1.0.1"
    },
  },

  "frameworks": {
    "netcoreapp1.0": {
      "imports": "dnxcore50"
    }
  }
}

该文件由 .NET Core 工具用于确定程序集元数据、依赖项和其他内容。它能做的事情很多,详细解释将超出本文的范围。如果您有兴趣了解更多信息,请查阅 文档

无论如何,将我们的控制台应用程序转换为 ASP.NET Core 应用程序的第一步是设置到 Microsoft.AspNetCore.Server.Kestrel 命名空间的依赖项。只需将粗体行粘贴到下面的代码片段中

{
  "version": "1.0.0-*",
  "buildOptions": {
    "emitEntryPoint": true
  },

  "dependencies": {
    "Microsoft.NETCore.App": {
      "type": "platform",
      "version": "1.0.1"
    },
    "Microsoft.AspNetCore.Server.Kestrel":"1.0.0"
  },

  "frameworks": {
    "netcoreapp1.0": {
      "imports": "dnxcore50"
    }
  }
}

Kestrel 是什么?来自 Microsoft Docs

docs.asp.net:

Kestrel 是一个基于 libuv(一个跨平台异步 I/O 库)的跨平台 Web 服务器。

本质上:ASP.NET Core 可以托管在 IIS 或 IIS Express 中,但并不依赖于它们。这就是 Kestrel 发挥作用的地方:它不是替代品,而是一个可行的选择,如果您无法在 IIS 或 IIS Express 中托管应用程序。尽管文档提到了将它们用作反向代理。我不会提供更多细节,如果您想深入了解,ASP.NET Core 的 服务器文档页面 是一个很好的知识来源。

来自 Kestrel 的问候

现在我们已经添加了对 Kestrel 的依赖项,我们可以继续让它运行起来(虽然只是勉强运行)。首先,向控制台应用程序添加一个名为 Startup 的类。将它的 using 指令替换为这两个

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;

然后,将类替换为以下代码片段

public void Configure(IApplicationBuilder app)
        {
            app.Run(context => {
                return context.Response.WriteAsync("Hello from Kestrel");
            });
        }

代码片段所做的只是非常简单的事情:回复“来自 Kestrel 的问候”到您的 Web 应用程序收到的任何请求。Web 应用程序现在知道如何响应,但此时,我们仍然只是一个简单的控制台应用程序。为了将其转换为 Web 应用程序(好吧,至少是一个非常基础的),我们需要修改 Program.cs 文件

将以下代码片段添加到您的 Main 方法中

Console.WriteLine("A moment please - Preparing the Kestrel Host");

var host = new WebHostBuilder()
            .UseKestrel()
            .UseStartup<Startup>()
            .Build();

Console.WriteLine("Ready to go");
host.Run();

为了让它工作,您需要将……

using Microsoft.AspNetCore.Hosting;

…放在 Program.cs 的顶部。这些行告诉我们的控制台应用程序使用 Kestrel 启动一个 Web 主机,它使用我们的 Startup 类作为入口点(索引页面)。一旦我们构建了项目,所有这些看起来就是这样

一旦您看到“应用程序已启动”,请访问 https://:5000 来查看它是否按预期工作,以及 Startup 类是否返回了您告诉它的内容

恭喜!您已经创建了一个 ASP.NET Core Web 应用程序的基础,并从控制台托管。它仍然很简单,要真正利用它,我们需要引入 MVC。继续阅读。

需要 MVC 吗?

到目前为止我们创建的示例充其量只是一个可行性研究(最多算上一点点),它显示了 ASP.NET Core 返回基本字符串给请求的能力。在当今的网络时代,这算不上什么大事,甚至没有构成如今 Web 应用程序基础的根本。MVC 是正确的方法 - 跟我来!

回到我们之前在本文中修改过的 project.json 文件。

{
  "version": "1.0.0-*",
  "buildOptions": {
    "emitEntryPoint": true
  },

  "dependencies": {
    "Microsoft.NETCore.App": {
      "type": "platform",
      "version": "1.0.1"
    },
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
    "Microsoft.AspNetCore.Mvc": "1.0.0"
  },

  "frameworks": {
    "netcoreapp1.0": {
      "imports": "dnxcore50"
    }
  }
}

在 Kestrel 依赖项的正下方,添加行 "Microsoft.AspNetCore.Mvc": "1.0.0" (在上面的示例中用粗体显示)。别忘了在上一行末尾添加逗号。一旦您保存了 project.json,Visual Studio 就会为您还原依赖项。现在依赖项已在 project.json 中设置好,我们需要关注我们的 Startup 类,因为所有的 MVC 初始化都将在那里完成。

首先,添加……

using Microsoft.Extensions.DependencyInjection;

……到 using 指令。为什么?.NET Core 将自动使用最新的 Microsoft Framework 来执行依赖项注入,因此需要 using 指令。现在将类的内部替换为以下内容(与之前类内容相比的更改以粗体标出)

public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseMvc();

            app.Run(context =>
            {
                return context.Response.WriteAsync("Hello world");
            });
        }
    }

ConfigureServices 为您提供了注册应用程序所需的任何服务或依赖项的机会。在这种情况下,services.AddMvc() 是一个简写,用于配置 Microsoft .NET Framework 实现提供的所有服务。

控制器

现在我们已经为应用程序使用 MVC 添加了基本先决条件,让我们添加一个控制器。ASP.NET Core 不强制您将控制器保留在 Controllers 文件夹中,但为了避免重复造轮子,我将坚持使用它。

我在 ContactApp 项目中创建了一个名为 HelloController 的类。

现在要将这个类转换为一个 Controller,我需要派生自 Controller 类(显然)。

using Microsoft.AspNetCore.Mvc;
using System;

namespace ContactApp.Controllers
{
    public class HelloController:Controller
    {
        [Route("hello/index")]
        public IActionResult Index()
        {
            return Ok($"Hello there. It's {DateTime.Now}.");
        }
    }
}

现在编译您的应用程序,然后访问 https://:5000/hello/index。您将看到下面的问候消息,由您的第一个 ASP.NET Core 控制器生成。

数据?视图?您要得到什么?

事实上 - 任何东西。ASP.NET Core 不关心您返回的是视图还是数据。对它而言,一切都是 IActionResult。如果我们修改上面的示例以返回一个类,IActionResult 将是 JSON 数据。酷吧?

public class HelloController:Controller
    {
        [Route("hello/index")]
        public IActionResult Index()
        {
            return Ok(new TestClass("Hi there", "It's after 10 PM here"));
        }
    }

    public class TestClass
    {
        public TestClass(string s1, string s2)
        {
            S1 = s1;
            S2 = s2;
        }

        public string S1 { get; set; }
        public string S2 { get; set; }
    }

结果输出将是一个 JSON 字符串,格式如下

{"s1":"Hi there","s2":"It's after 10 PM here"}

当然,并非每个人都熟悉 JSON,而普通用户肯定不熟悉。为了让普通用户能够看到我们的数据,别无选择,只能创建一个视图。为了创建您的第一个视图,请在 ContactApp 项目中创建 Views/Hello 文件夹。ASP.Net Core 将在预定义的放置位置查找视图,而 Views 文件夹是最常见的。

之后,修改您的 HelloController 以在路由 hello/greet 上返回一个视图,并带有可选参数 username。

public class HelloController:Controller
    {
        [Route("hello/index")]
        public IActionResult Index()
        {
            return Ok(new TestClass("Hi there", "It's after 10 PM here"));
        }

        [Route("hello/greet/{username?}")]
        public IActionResult UserName(string username = "you over there")
        {
            return View(new TestClass (username, DateTime.Now.ToString()));
        }
    }

如果未设置 username 参数,则使用“您那边的人”作为默认用户名。现在继续在 ContactApp 项目的 Views/Hello 文件夹中添加一个名为 UserName.cshtml 的文件。

<div>
    <h1>Hello @Model.S1</h1>
    <h3>It's @Model.S2</h3>
</div>

现在,在我们创建的示例运行之前,我们需要调整一些事情。首先,添加行

preserveCompilationContext”: true,在您的 project.json 文件中的 buildOptions 正下方

{
  "version": "1.0.0-*",
  "buildOptions": {
    "preserveCompilationContext": true,
    "emitEntryPoint": true
  },

之后,切换到 Program.cs,在 UseKestrel 之后添加 UseContentRoot(Directory.GetCurrentDirectory())

var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseStartup<Startup>()
            .Build();

为什么我们需要进行此调整?project.json 中的更改是为了告诉编译器保留某些引用的程序集(例如 System),以便 Razor 能够在运行时编译您的视图。我们需要在 Program.cs 中进行的更改告诉 Web 服务器在哪里查找内容文件(例如视图)。

现在,在我们完成所有这些之后,让我们运行项目并查看结果

左侧显示了使用 Marco 作为 username 参数的视图的输出。

下方显示了来自同一控制器的输出,但没有用户名参数。因此,它使用了“您那边的人”作为默认值。

延伸阅读

虽然我尽力为您提供了对 ASP.NET Core 是什么、它如何工作以及何时可能有用性有一个基本了解,但我没有过于详细,以使整篇文章保持主题。如果您在阅读完我的文章后需要进一步阅读,您可以在下面的链接中找到更多内容。我在研究这篇文章时使用了它们,它们是知识的重要来源。愿它们对您像对我一样有用。

此刻,我只能推荐阅读 Scott Hanselmann 关于 ASP.NET Core 的任何帖子。
他不仅在推广新技术方面做得很好,而且在解释其原因方面也做得很好。

© . All rights reserved.