本文地址:https://www.cnblogs.com/oberon-zjt0806/p/12225807.html

O 前请提要

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

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中。

小提示:

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

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

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

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

这个函数主要调用了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 ...

初探ASP.NET Core 3.x (4) - 项目的重要组成的更多相关文章

  1. ASP.NET CORE MVC 2.0 项目中引用第三方DLL报错的解决办法 - InvalidOperationException: Cannot find compilation library location for package

    目前在学习ASP.NET CORE MVC中,今天看到微软在ASP.NET CORE MVC 2.0中又恢复了允许开发人员引用第三方DLL程序集的功能,感到甚是高兴!于是我急忙写了个Demo想试试,我 ...

  2. ASP.NET Core 2.0 : 三. 项目结构

    本章我们一起来对比着ASP.NET Framework版本看一下ASP.NET Core 2.0的项目结构.(此后的文章也尽量这样对比着, 方便学习理解.) 关注差异, 也为项目迁移做准备. 新建项目 ...

  3. ASP.NET Core Web多语言项目

    公司效益好了,准备和国外做生意,这个时候就需要多语言了. > 1. 这是一个ASP.NET Core Web多语言项目,主要展示项目的不同: > 2. 第一种:www.xxx.com/en ...

  4. Taurus.MVC 微服务框架 入门开发教程:项目集成:2、客户端:ASP.NET Core(C#)项目集成:应用中心。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...

  5. 简读《ASP.NET Core技术内幕与项目实战》之3:配置

    特别说明:1.本系列内容主要基于杨中科老师的书籍<ASP.NET Core技术内幕与项目实战>及配套的B站视频视频教程,同时会增加极少部分的小知识点2.本系列教程主要目的是提炼知识点,追求 ...

  6. 快读《ASP.NET Core技术内幕与项目实战》EFCore2.5:集合查询原理揭秘(IQueryable和IEnumerable)

    本节内容,涉及4.6(P116-P130).主要NuGet包:如前述章节 一.LINQ和EFCore的集合查询扩展方法的区别 1.LINQ和EFCore中的集合查询扩展方法,虽然命名和使用完全一样,都 ...

  7. 快读《ASP.NET Core技术内幕与项目实战》WebApi3.1:WebApi最佳实践

    本节内容,涉及到6.1-6.6(P155-182),以WebApi说明为主.主要NuGet包:无 一.创建WebApi的最佳实践,综合了RPC和Restful两种风格的特点 1 //定义Person类 ...

  8. 《ASP.NET Core技术内幕与项目实战》精简集-目录

    本系列是杨中科2022年最新作品<ASP.NET Core技术内幕与项目实战>及B站配套视频(强插点赞)的精简集,是一个读书笔记.总结和提炼了主要知识点,遵守代码优先原则,以利于快速复习和 ...

  9. ASP.NET Core 2.0 MVC项目实战

    一.前言 毕业后入职现在的公司快有一个月了,公司主要的产品用的是C/S架构,再加上自己现在还在学习维护很老的delphi项目,还是有很多不情愿的.之前实习时主要是做.NET的B/S架构的项目,主要还是 ...

随机推荐

  1. 【mac】Mac 终端如何切换成管理员用户

    方法1.打开终端输入 sudo su  然后回车 Password:  ------(输入root密码即可) sh-3.2# --------    (输入执行的命令即可,例如 npm i -g np ...

  2. 打地鼠游戏(2)之定义地鼠函数及函数原型 prototype

    在JavaScript中,prototype对象是实现面向对象的一个重要机制. 每个函数就是一个对象(Function),函数对象都有一个子对象 prototype对象,类是以函数的形式来定义的.pr ...

  3. 基于JWT的Token登录认证(一)

    1.JWT简介 JSON Web Token(缩写 JWT),是目前最流行的跨域认证解决方案. session登录认证方案:用户从客户端传递用户名.密码等信息,服务端认证后将信息存储在session中 ...

  4. python调用另一个文件中的代码,pycharm环境下:同文件夹下文件(.py)之间的调用,出现红线问题

    如何调用另一个python文件中的代码无论我们选择用何种语言进行程序设计时,都不可能只有一个文件(除了“hello world”),通常情况下,我们都需要在一个文件中调用另外一个文件的函数呀数据等等, ...

  5. Codeforces 837D 动态规划

    Codeforces 837D 动态规划 传送门:https://codeforces.com/contest/837/problem/D 题意: 给你n个数,问你从这n个数中取出k个数,这k个数的乘 ...

  6. 【Docker Compose】简介与安装

    1.简介 Compose 是一个用户定义和运行多个容器的 Docker 应用程序.在 Compose 中你可以使用 YAML 文件来配置你的应用服务.然后,只需要一个简单的命令,就可以创建并启动你配置 ...

  7. unsupported jsonb version number 123

    PostgreSQL  jsonb 入库时遇到   unsupported jsonb version number 123 变通方法 insert into  htclanedata (laneda ...

  8. Visio日程安排图

    黄日历: 怎么创建呢? 首先找到日程安排图表 然后找到日历 这就是日历的形状模块 拖动“日”日历形状进行创建 创建好的日历通过右键单击选择"配置"来修改日期 这是周日历 与日日历不 ...

  9. 如何看Crash 文件

    如何查看崩溃日志 好了,获得是人类可读语言的崩溃日志后,或者是从别人手机到处崩溃日志后,下一步就是查看了.下面就正对一个程序猿该如何看稍微说说. 崩溃日志头     1 2 3 4 5 6 7 8 9 ...

  10. $loj530\ [LibreOJ\ \beta\ Round \#5]$ 最小倍数 数论

    正解:数论 解题报告: 传送门$QwQ$! 不想做题,来水点儿简单点的$QwQ$. 一个显然的点在于可以直接对不同质因子分别算$n_{min}$最后取$max$. 这个正确性还是蛮显然的?因为只要有$ ...