初探ASP.NET Core 3.x (4) - 项目的重要组成

本文地址:http://www.javashuo.com/article/p-orrcfkke-kb.html前端

O 前请提要

在第1期构建项目以后,咱们看到项目中有这样的组成结构:web

MyASPWebApplication/
├─obj/
│ └─/一些文件.../
├─Pages/
│ ├─Shared/
│ │ ├─_Layout.cshtml
│ │ └─_ValidationScriptsPartial.cshtml
│ ├─Error.cshtml
│ ├─Error.cshtml.cs
│ ├─Index.cshtml
│ ├─Index.cshtml.cs
│ ├─Privacy.cshtml
│ ├─Privacy.cshtml.cs
│ ├─_ViewImports.cshtml
│ └─_ViewStart.cshtml
├─Properties/
│ └─launchSettings.json
├─wwwroot/(empty)
├─appsettings.Development.json
├─appsettings.json
├─Program.cs
├─Startup.cs
└─MyASPWebApplication.csproj

这是初始生成项目所包含的目录结构,这里面包含了不少东西,可是,咱们还不清楚每一个部分能作些什么,充当怎样的一个角色,以及哪些东西是最基础的,这一节就来解决这些问题。
在第3期中咱们从原理层面上了解了ASP.NET Core Web项目的一个基本的工做流程以及所包含的部分。数据库

I 启动部分

I.1 Program

按照绝大部分C#开发框架的惯例,Program类通常是程序的入口,里面包含一个Main函数并被单独放置于Program.cs中。json

小提示:
尽管C#并不像Java那样强制要求必须将各个数据实体分放到不一样的文件中,但C#依然要求定义类的代码文件必须和该文件中所定义的类(若是多个则任取其一)相同。此外,如非必要,咱们仍然建议将各个类定义分离到不一样的文件中,除非:windows

  1. class Aclass B之间有比较大的实体关联,例如依赖关系。
  2. class B只是class A的一个辅助工具性的类,例如class B只是针对class A的一个异常类等

ASP.NET Core产生的Program类以下:后端

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace MyASPWebApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

固然了,这里public static void Main(string[] args)天然就是程序的入口了。里面调用了他的下一个成员函数:浏览器

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });

这个函数的定义方式很特别,它使用了λ推演=>)的方式作的函数定义,但这可有可无,实际上表达的是:app

public static IHostBuilder CreateHostBuilder(string[] args)
{
    IHostBuilder _ = Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults
    (
        webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        }
    )
}

这个函数主要调用了Host.CreateDefaultBuilder(args)静态函数使用程序的参数针对服务主机(Host)的进行一个默认配置。综上,Program类做为程序的入口,其所包含的配置内容大多面向于项目的顶层设施。框架

关于服务主机泛型主机Web主机)的相关概念以及配置过程,在之后期介绍。

I.2 Startup

在上面的结构中,咱们不得不注意的另外项目即是Startup.cs。固然了,本着C#的开发原则,咱们很容易了解到这个代码文件中应当包含一个名为Startup的类。

Startup类位于当前项目的命名空间下(也就是说类全称为MyASPWebApplication.Startup)。这个类在项目被构建时被生成为这个样子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace MyASPWebApplication
{
    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 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.AddRazorPages();
        }

        // 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("/Error");
            }

            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
    }
}

I.2.1 这个类干什么呢??

如你所见,这个类并不继承于任一个其余的现有类,就是一个很是中规中矩的C#类。但事实上,这个类包含了这个Web应用程序被启动时执行的配置行为。

为何一个普通的类就能够支配整个项目的配置呢?事实上,尽管被定义为一个普通的类,但Startup仍是有一些特征的。

I.2.2 特征??

很明显,这个类的定义至关简单,除了构造函数外只有两个函数和一个只读属性:

public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

这两个成员函数的内容,代表了Startup的配置主要是两个方面:

  1. ConfigureServices函数以控制反转(IOC)的方式依赖注入(DI)项目中的 服务
  2. Configure函数负责配置请求应用管道

这里面出现了不少概念,好比管道、控制反转、依赖注入之类的,这将在以后期中慢慢解释。总之,这些内容是在WebApp运行期间被动态加载的配置。

而这个类最大的玄机在于,它在Program类中被引用过:

//---- Program.cs(节选) ----//
public static IHostBuilder CreateHostBuilder(string[] args)
{
    IHostBuilder _ = Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults
    (
        webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        }
    )
}

第8行中,webBuilder.UseStartup<Startup>()就经过webBuilder加载了这个类做为默认的Host配置。这也正是为何Startup做为一个普通的类就可以做为配置类的缘由。

I.3 appsettings.json

终于,咱们聚焦于不是C#类的一个主要文件了。这是一个json表格式的配置文件。

固然,咱们实际上能看到两个文件:appsettings.jsonappsettings.Development.json。这两个文件的做用实际上没有什么实质性不一样,只是应用的场合并不相同。当项目的运行环境为开发态(Development)的时候,优先使用appsettings.Development.json,不然使用另一个。

初始状态下,appsettings.json的内容为:

{
  "Logging": 
  {
    "LogLevel": 
    {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

这种文件里配置的内容多和数据有关。好比初始状态下有的"Logging"子表包含了对日志记录的配置信息。固然,又如当该WebApp使用数据库时,有关数据库的链接信息(链接字符串、超时等)也会被配置到这个json表中。

固然,在这张表中,咱们也能够加入本身的配置信息,在程序中能够经过Microsoft.Extensions.Configuration.IConfiguration对象读取这个文件里的配置信息。

关于此文件中包含的配置项和配置方法也会在之后详细探索。

I.4 launchSettings.json

这个文件存在于Properties文件夹下,定义了项目的属性:

{
  "iisSettings": {
    "windowsAuthentication": false, 
    "anonymousAuthentication": true, 
    "iisExpress": {
      "applicationUrl": "http://localhost:64571",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "MyASPWebApplication": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

这个也属于配置文件,主要配置的是项目的运行环境,例如侦听端口等、环境模式、是否运行浏览器以及IIS反向代理的转发端口等。

好比,在这个配置模式下,当项目以IIS Express反向代理的方式运行时,就会访问http://localhost:64571,但若是不使用IIS而直接使用Kestrel来启动,那么项目地址就是http://localhost:5000

II wwwroot目录

另一个比较显著的目录是wwwroot。若是使用Visual Studio建立项目,咱们可以看到,这个wwwroot目录和Properties目录相似,有个特别的图标:

这里面目前是空的,不过这里通常用于放置静态文件(Static Files)。

II.1 静态文件??

说白了,就是在运行期间不会发生变化的,通常是指资源文件。
好比:静态网页(HTML)、静态样式表(CSS)、静态浏览器脚本(JS)、图片、音频等等等等。
wwwroot这个目录就是放这些东西进去的。

服务端处理这些静态文件是经过StaticFiles这一中间件组成的。

// ---- Startup.cs(节选) ---- //

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthorization();
            
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }

第14行就是Startup类中对此中间件的注册。

III 常规目录

为了使项目更为有序的组织,一些文件会被存放于一些目录(文件夹)中,而这些目录在ASP.NET Core下有约定的名称。

III.1 Pages目录和Views目录

Pages文件夹存放的内容被称为页面,这里用于存放Razor Pages开发模式下的Razor页面。

Razor Pages是ASP.NET Core 2.x中提出的一种新的开发模式,聚焦于页面,并以页面为中心。

MVC开发模式下,这个部分被替换为视图,存放于Views文件夹中。尽管二者之间有所不一样,但咱们目前要知道的是,这个文件夹里的东西聚焦于前端。

III.1.1 页面??可是wwwroot里不是也存放页面了么??

是的,可是wwwroot里面存放的是静态页面,而这里面存放的页面被称为Razor页面,是一种动态页面

III.1.2 有什么区别么??

固然有区别。虽说这二者到浏览器客户端都会被解析为一样的东西,可是对于服务端而言,这二者有很大的区别。

存放于wwwroot中的页面简单来讲就是写死的页面,这种页面不管运行多少次,服务端数据如何变化,其页面结果是不变的。

但动态页面是不同的,动态页面是保留了必定不变内容基础之上又根据后端数据变化而被从新生成的。在浏览器上就被体现为,随着后台数据的变化,页面的显示结果会有所不一样

III.1.3 Shared子文件夹

不管是Pages仍是Views,由于都存放带有Razor标记的页面,因此这两个目录下每每还有一个子目录,称为Shared。这个目录主要存放的是共享的分部标记元素(我知道听不明白,之后会解释的)。

III.2 Controller文件夹

这个文件夹仅存在于MVC模式下,存放MVC模式当中的控制器(Controller,MVC中的C)。

控制器是一种特殊的类,ASP.NET Core中约定控制器类以Controller结尾。

在MVC中,控制器主要用于处理请求(Request)和路由(Routing)并提供响应。做用有些相似于Java中的Servlet。(具体内容和其余概念的之后介绍,之后介绍)

III.3 Models文件夹

若是WebApp关联了数据库,那么数据库中的数据必然存在一种数据模型,这种数据模型在关系理论中称为关系模式,它实际上与面向对象理论中的是对应的。

通常来讲由于数据库的数据组织方式和应用中组织方式的这种不一样,所以在项目中处理这些数据就必须本身编写数据访问(DA)功能将数据库中的关系元组转化成应用可使用的类对象,可是一个Web项目中的数据门类很是的多,这也就形成了关系模式也很是的多,要编写的内容也就很是的多,那么为了统一地、自动地处理和显示这些数据,减轻重复编码的负担,一种称为对象关系映射(ORM)的数据开发模式就产生了。

ORM的机制使得咱们只须要在程序中写出数据模型(类定义),而无需提供存取方法(这个由ORM提供,这个过程也被称为数据绑定)。那么Models目录就是为了存放这些数据模型的。

IV 其余

除了上面这些以外,还有其余的东西,遇到再说。

To be continued ...

相关文章
相关标签/搜索