×

ASP.NET Core 知多少(1):从官方模板开始

96
圣杰
2017.09.09 11:29* 字数 1847

ASP.NET Core知多少系列:总体介绍及目录

1. 模板项目一览

如果创建ASP.NET Core Web Application,目前官方预置了7种模板项目供我们选择。从中我们可以看出,既有我们熟悉的MVC、WebAPI,又新添加了Razor Page,以及结合比较流行的Angular、React前端框架的模板项目。基于给出的模板,我们可以根据自己的需求选择合适的模板搭建项目框架着手开发。同时,我们也可以基于提供的结合Angular、React客户端的模板项目来实施前后端分离的开发策略。


web application templates
web application templates

2. Empty 模板项目

我们先来看看创建的Empty模板项目结构:


Empty Template Project Structure
Empty Template Project Structure

从图中可以得知主要由以下几个部分组成:

  1. Dependencies:组织项目的依赖关系。从图中我们可以看到依赖被细化为三个类别:Analyzers、NuGet、SDK。其中NuGet是专门为.net设计的包管理器,组织从NuGet上安装的依赖项;SDK主要是Microsoft底层的系列依赖;其实还有另外几个类别:Projects、Bower、npm。Projects就是直接的项目依赖;Bower是专门为web设计的包管理器,用来组织web前端依赖;npm是专门为javascript设计的包管理器,用来组织javascript的相关依赖。
  2. Properties:其中仅包含launchSettings.json文件,该文件用于指定应用程序的启动设置。
  3. wwwroot:根目录,一般用来定义静态文件,如js、css、html、img、ico等等。
  4. Program:程序入口,其中定义了Main函数作为入口函数。从这一点可以看出,其实质是控制台应用。
  5. Startup:程序启动类。

2.1. 启动设置之launchSettings.json

首先该json文件中配置的属性可以参考launchSettings.json


2.2. 入口函数之Main函数

public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
}

ASP.NET Core应用程序需要由Host(宿主)进行管理,宿主为其提供运行环境并负责启动。所以Main函数主要是用来初始化宿主环境,而宿主环境的初始化需要借助WebHostBuilder。初始化完毕后,调用Run()方法来启动应用程序。

  1. WebHost.CreaateDefaultBuilder():创建WebHostBuilder
  2. UseStartup<Startup>():指定启动类,用于依赖注入和中间件注册。
  3. Build():返回初始化完毕的IWebHost宿主。
  4. Run():启动WebHost。

2.3. 宿主构造器之WebHostBuilder

以上Program的简单几行代码,完成了一个应用程序的配置和启动。但简洁的代码不见得简单。我们结合源码来看一看。

public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
    var builder = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            var env = hostingContext.HostingEnvironment;

            config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);

            if (env.IsDevelopment())
            {
                var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
                if (appAssembly != null)
                {
                    config.AddUserSecrets(appAssembly, optional: true);
                }
            }

            config.AddEnvironmentVariables();

            if (args != null)
            {
                config.AddCommandLine(args);
            }
        })
        .ConfigureLogging((hostingContext, logging) =>
        {
            logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
            logging.AddConsole();
            logging.AddDebug();
        })
        .UseIISIntegration()
        .UseDefaultServiceProvider((context, options) =>
        {
            options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
        });
    return builder;
}

主要包含以下几个部分:

  1. UseKestrel:使用Kestrel作为Web server。
  2. UseContentRoot:指定Web host使用的content root(内容根目录),比如Views。默认为当前应用程序根目录。
  3. ConfigureAppConfiguration:设置当前应用程序配置。主要是读取 appsettinggs.json 配置文件、开发环境中配置的UserSecrets、添加环境变量和命令行参数 。
  4. ConfigureLogging:读取配置文件中的Logging节点,配置日志系统。
  5. UseIISIntegration:使用IISIntegration 中间件。
  6. UseDefaultServiceProvider:设置默认的依赖注入容器。

2.4. 启动类之Startup

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

    // 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.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    }
}

该类主要包括两个方法:

  1. ConfigureService:用于依赖服务注册。
  2. Configure:用于指定应用程序将如何响应每一个 HTTP 请求。一般用于注册中间件。

其中涉及到下以下几个可用服务:

  1. IServiceCollection:当前容器中各服务的配置集合,ASP.NET Core内置的依赖注入容器。
  2. IApplicationBuilder:用于构建应用程序的请求管道。
  3. IHostingEnvironment :提供了当前的 EnvironmentName、WebRootPath 以及 ContentRoot等。

2.5. 启动流程

首先我们需要明白,我们创建的.net core web application其实质是一个独立的控制台应用程序,不能直接处理Http请求,需要借助Web Server向外提供服务。.net core中默认使用支持跨平台的Kestrel作为web server(当然还有其他web server可供选择,比如WebListener、Http.sys等等)。Web server是需要宿主环境来承载它。比如:Windows 上的IIS、Windows Services,Linux上的Apache、Nginx,或者Docker都可以作为Web Server的宿主。

而宿主就是用来负责启动我们的.net core 应用程序的。比如:IIS新增了一个 AspNetCoreModule 模块,它负责 ASP.NET Core 程序的启动与停止,并能监听 ASP.NET Core 程序的状态,在我们的应用程序意外崩溃时重新启动。

IIS作为宿主启动 .net core application
IIS作为宿主启动 .net core application

当仅仅是在内网中暴露服务的话,可以直接使用Kestrel处理http请求。否则,还是借助反向代理服务器(IIS、Nginx、Apache等)来转发http请求。但一般我们建议结合使用反向代理服务器来处理http请求,因为反向代理服务器可以在Kestrel之前做一些额外的处理(了解更多,可参考Introduction to Kestrel web server implementation in ASP.NET Core)。

Http请求示意图
Http请求示意图

通过以上的描述我们引入了Host与Server的概念。我们可以简单理解为host是一个进程用来管理应用程序,而server是用来暴露应用程序服务的。也可以理解为host是对server的一层包装。

3. MVC vs Razor Page

ASP.NET MVC 是一套基于Microsoft .NET Framework的用来开发web应用程序的开源框架。其基于关注点分离的思想将应用程序主要分为三个部分:Model、View、Controller。在ASP.NET Core中同样延续了MVC的优良设计。
ASP.NET MVC中Razor作为一个高级视图引擎存在,Razor提供了一种新的标记语义,其大大减少了用户输入且具有表现力,主要的特点是使用@符号去书写标记。
而在ASP.NET Core中Razor不仅仅是一种视图引擎,其提供了一种新的页面设计方式——Razor Page。其主要的特点在于:

  1. 基于文件路径的路由系统;
  2. Razor Page类似于WebForm,一种MVVM的架构,支持双向绑定;
  3. Razor Page符合单一职责原则,每个页面独立存在,视图和代码紧密组织在一起。
MVC与Razor Page模板项目结构差异
MVC与Razor Page模板项目结构差异

4. MVC vs WebAPI

本质上的区别在于:ASP.NET MVC 用来创建web应用返回视图和数据;但是ASP.NET WEB API 是用来创建完整的HTTP服务,仅返回数据无视图返回。

就项目结构而言,差别如下:



5. Angualr 模板项目

我们可以借助Angular来开发SPA web应用,其结构就与MVC相比,主要多了ClientApp文件夹。其代码结构如下图所示:

Angular Template Project
Angular Template Project

6. 最后

关于模板项目的介绍就简要介绍到这里,我们后续在结合实际运用继续深入探讨!

ASP.NET
Web note ad 1