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

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

1. 模板项目一览

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


web application templates

2. Empty 模板项目

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


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

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

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模板项目结构差异

4. MVC vs WebAPI

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

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


5. Angualr 模板项目

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

Angular Template Project

6. 最后

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容