ASP.NET Core Basic 1-1 WebHost与项目配置

2022-10-17,,,,

.net core asp.net core basic 1-1

本节内容为webhost与项目配置

项目配置文件

我们可以很清楚的发现在我们的文件中含有一个json文件——appsettings.json,实际上,这个文件就是我们项目的默认配置文件,它内部含有了默认的一些设置,当然你也可以自己进行添加或者修改。这里我们不展开讲述。我们会在本文的后部分进行讲解如何读取、操作配置文件。

项目主入口program

在asp.net core2.x的空项目中,你会发现有以下两个类存在——starup、program,其中program类里面就是我们asp.net core的入口(main函数)。我们可以看一下program类

namespace asp.net_core_study
{
    public class program
    {
        public static void main(string[] args)
        {
            createwebhostbuilder(args).build().run();
        }

        public static iwebhostbuilder createwebhostbuilder(string[] args) =>
            webhost.createdefaultbuilder(args)
                .usestartup<startup>();
    }
}

我们可以发现,program中使用了一个 createwebhostbuilder 函数进行程序的初始化,里面就涉及到了我们的webhost。

那么什么是webhost呢?你可以简单的理解为就是我们的web项目的服务主机,它是asp.net core的核心,它调用了createdefaultbuilder方法进行创建。而泛型函数使用的startup则是我们服务的配置类。

当然,webhost进行服务主机创建的时候你也可以使用 webhost.start() 进行手动的配置与创建。这里我们只针对官方默认的方法进行学习与分析。

首先看到createdefaultbuilder()的源码,这个你可以在github或者是resharp的反编译功能查看到,这里我是直接从github公开的源码复制

 /// <summary>
        /// initializes a new instance of the <see cref="webhostbuilder"/> class with pre-configured defaults.
        /// </summary>
        /// <remarks>
        ///   the following defaults are applied to the returned <see cref="webhostbuilder"/>:
        ///     use kestrel as the web server and configure it using the application's configuration providers,
        ///     set the <see cref="ihostingenvironment.contentrootpath"/> to the result of <see cref="directory.getcurrentdirectory()"/>,
        ///     load <see cref="iconfiguration"/> from 'appsettings.json' and 'appsettings.[<see cref="ihostingenvironment.environmentname"/>].json',
        ///     load <see cref="iconfiguration"/> from user secrets when <see cref="ihostingenvironment.environmentname"/> is 'development' using the entry assembly,
        ///     load <see cref="iconfiguration"/> from environment variables,
        ///     load <see cref="iconfiguration"/> from supplied command line args,
        ///     configure the <see cref="iloggerfactory"/> to log to the console and debug output,
        ///     and enable iis integration.
        /// </remarks>
        /// <param name="args">the command line args.</param>
        /// <returns>the initialized <see cref="iwebhostbuilder"/>.</returns>
        public static iwebhostbuilder createdefaultbuilder(string[] args)
        {
            var builder = new webhostbuilder();
            if (string.isnullorempty(builder.getsetting(webhostdefaults.contentrootkey)))
            {
                builder.usecontentroot(directory.getcurrentdirectory());
            }
            if (args != null)
            {
                builder.useconfiguration(new configurationbuilder().addcommandline(args).build());
            }
            builder.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();
                logging.addeventsourcelogger();
            }).
            usedefaultserviceprovider((context, options) =>
            {
                options.validatescopes = context.hostingenvironment.isdevelopment();
            });
            configurewebdefaults(builder);
            return builder;
        }

你在这里可以非常清楚的看到,这个函数他会取寻找appsettings.json以及appsettings.{env.environmentname}.json。因此在使用默认的方法进行项目实战时,我们不应该修改这个文件的文件名。并且我们可以发现,这个文件是分两部分的,一部分是我们的发布版本(publish),一部分是我们的开发版本。他们的文件名是不同的,在源码中我们也可以找到这些语句。同时我们的builder调用了useconfiguration方法,这是一个参数配置的方法,用于接收我们从控制台输入的一些参数。

并且,我们可以看到他还进行了服务的替换usedefaultserviceprovider以及根目录的设置usecontentroo,源码如下

public static iwebhostbuilder usecontentroot(this iwebhostbuilder hostbuilder, string contentroot)
{
    if (contentroot == null)
    throw new argumentnullexception(nameof (contentroot));
    return hostbuilder.usesetting(webhostdefaults.contentrootkey, contentroot);
}

public iwebhostbuilder usesetting(string key, string value)
{
    this._config[key] = value;
    return (iwebhostbuilder) this;
}

说到这里,我需要引出我们asp.net core的两种启动方式。一种是使用我们微软官方的iis进行项目的部署,他的本质是将dll注入到iis服务中。当然,我们知道iis是windows上的web服务器,如果我们要进行跨平台的开发,我们可以使用微软开发的kestrel,源码中的configurewebdefaults函数的源码我们就可以看到相关的操作

internal static void configurewebdefaults(iwebhostbuilder builder)
        {
            builder.usekestrel((buildercontext, options) =>
            {
                options.configure(buildercontext.configuration.getsection("kestrel"));
            })
            .configureservices((hostingcontext, services) =>
            {
                // fallback
                services.postconfigure<hostfilteringoptions>(options =>
                {
                    if (options.allowedhosts == null || options.allowedhosts.count == 0)
                    {
                        // "allowedhosts": "localhost;127.0.0.1;[::1]"
                        var hosts = hostingcontext.configuration["allowedhosts"]?.split(new[] { ';' }, stringsplitoptions.removeemptyentries);
                        // fall back to "*" to disable.
                        options.allowedhosts = (hosts?.length > 0 ? hosts : new[] { "*" });
                    }
                });
                // change notification
                services.addsingleton<ioptionschangetokensource<hostfilteringoptions>>(
                            new configurationchangetokensource<hostfilteringoptions>(hostingcontext.configuration));

                services.addtransient<istartupfilter, hostfilteringstartupfilter>();

                services.addrouting();
            })
            .useiis()
            .useiisintegration();
        }

我们可以发现,在这里,它会从配置文件中读取相关的配置进行配置我们启动使用的服务选项。usekestrel函数对一些服务进行了注册,以便后续的使用。这里我不打算进行详细的讲解,因为这一节内容只是希望你能够对项目的启动有一个初步的认识,你需要知道的是,目前位置,我们发现了asp.net core程序会在实例化webhost之前配置好一切,并且我们可以使用一个开源跨平台的web服务器kestrel。

startup

startup类是一个配置性质的类,它里面有configure(iapplicationbuilder app, ihostingenvironment env)以及configureservices(iservicecollection services)方法,这两个方法中configureservices是我们的服务配置方法或者说是容器配置,它主要用于配置我们依赖注入的类,而configure方法是我们配置中间件的地方,这两个概念我会在后一两篇文章中进行非常详细的讲解。

总结

本篇文章内容并不是很多,主要是让你知道asp.net core其实只是一个简答的控制台程序,只是它调用了一些服务而已。

总体来说我们asp.net core的webhost创建的过程是

  • 配置好服务器usekestrel()
  • 配置好根目录usecontentroot()
  • 添加配置文件源configureappconfiguration((context, builder) => builder.addjsonfile("appsetting.json", true, true))
  • 注册日志记录到控制台configurelogging(builder => builder.addconsole())
  • 配置好startup类,进行依赖注入和中间件的配置usestartup()
  • 生成webhost,build()返回一个webhost对象
  • 运行webhost,run()将webhost启动

当然iwebhostbuilder接口也有一些其他的常见方法,这里我做一个简单的列举

  • useurls,配置启动的ip地址
  • usesetting,使用新的文件替换默认appsettings.json
  • useshutdowntimeout,自动关机
  • useenvironment,配置启动时的环境(生产or开发)

这几个是我经常使用的函数,其他的函数你可以在微软官方api文档或者是asp.net core的源码中进行学习,并不难。

reference

asp.netcore 运行

如果我的文章帮助了您,请您在github.netcoreguide项目帮我点一个star,在博客园中点一个关注和推荐。

github

bilibili主页

warrenryan'sblog

《ASP.NET Core Basic 1-1 WebHost与项目配置.doc》

下载本文的Word格式文档,以方便收藏与打印。