【C#】.Net Core基础入门到实例部署

一.安装

直接使用Visual Studio的新建项目–Web–Net

二.基础概念

.net core
跨平台,跨架构(X86/X64/ARM),支持命令行,部署灵活,兼容性强(向下),开源

.net framework
.net core 3.1是FW4.8的下一代,3.1的下一版是 .NET 5.0

.net core 3.X
支持winform和WPF(不是很完善)
ASP.NET CORE 3.0
EF CORE 3.0
云原生和微服务 NC的核心
体积小,速度快,占用少,水平扩展

3.1:
适合WEB开发

ASP.NET CORE 3.1
启动流程,主机配置,依赖注入,服务,中间件,应用配置,多环境,日志,路由,异常处理,静态文件,部署等。
是ASP.NET的重新设计,体系结构已经改变,是以后的核心。

新功能:
Blazor
gRPC,高性能远程过程调用框架,微服务间的内部调用

开发环境 VS2019 16.4

ASP.NET CORE 空项目,CORE 3.1
在这里插入图片描述

启动:
自宿主启动
wwwroot文件夹,静态文件
在这里插入图片描述

主机:
负责web应用程序的启动和生产周期管理,配置服务器和请求处理
主机配置日志
主机是封装了应用资源的对象

创建主机生产器>配置主机>创建主机>运行主机

HOST有2种:
通用:
webhost:
在这里插入图片描述

Kestrel:
跨平台的适用与ASP.NET的WEB服务器,角色类似IIS,但不是IIS
HTTP/HTTPS
功能少,不支持反向代理

反向代理:额外的安全配置,HTTPS比较好配置
在这里插入图片描述

配置主机:
组件配置

微服务架构:

在这里插入图片描述

三.知识讲解

Program.cs

public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }
        
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            // 配置web主机
            // 启用Kestrel
            // 启用IIS集成
            // 环境变量(DOTNET开头)
            // 加载命令行参数
            // 加载应用配置
            // 配置默认的日志组件
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    //组件配置 Config开头
                    webBuilder.ConfigureKestrel((context,options)=>options.Limits.MaxRequestBodySize=20480000);//20M
                    //webBuilder.ConfigureLogging((context, builder) => { builder.});
                    // 主机配置项,Use开头的函数
                    webBuilder.UseStartup<Startup>();
                    // 环境变量<硬编码<应用配置<命令行
                    webBuilder.UseUrls("http://*:8081"); // 硬编码
                });
    }

Kestrel的URL配置的优先级 低-高:

环境变量:

配置文件内 "ASPNETCORE"开头
在这里插入图片描述

在这里插入图片描述

硬编码:

Program.cs

webBuilder.UseUrls("http://*:8081"); // 硬编码
应用配置:

在这里插入图片描述

命令行:

运行程序时 配置URL参数:
在这里插入图片描述

在这里插入图片描述

Startup.cs

// 配置WEB应用所需要的服务和中间件
    public class Startup
    {
        // 可选的, 可注册的 服务
        public void ConfigureServices(IServiceCollection services)
        {
            // 服务容器
            // IoC容器【控制反转Inversion of Control】【升级版的工厂模式,映射依赖/管理对象的生成和生存周期】
            // 注册类型,请求实例,功能解析【类所依赖的对象】
            // 目的为了:依赖注入【一系列的工具和手段,目的是松耦合,可维护/可测试的代码和程序】
            
            // 默认已经为我们注册了一些服务,所以称为服务容器
            // 添加对控制器和API相关功能的支持,但是不支持视图和页面
            services.AddControllers();
            // 添加对控制器/API/视图相关功能的支持 ASP.NET CORE 3.X MVC模板默认使用
            services.AddControllersWithViews();
            // 这里是APS.NET CORE 2.X
            services.AddMvc();
            //跨域
            services.AddCors();
            // 以上都是内置的服务,还可以添加第三方的 EF CORE/日志框架/Swagger
            // 注册自定义服务
            // 服务生存期 类型生成期
            // 注册自定义的服务时,必须要选择一个生存周期
            // 有几种生存周期,瞬时/作用域/线程单例/全局单例
            // services.AddSingleton<IMyEmail,MyEmail>(); // 注册单例
            // services.AddSingleton<IMyEmail,MyEmail02>(); // 注册单例 ,一个一个注册,也可以批量
            // 服务,生存期,配置
            // 自带的不好用,可以换成第三方的
            // 依赖注入框架很多:第三方:Unity/Autofac/Ninject/
            
            // 自定义的服务
            // 比较规范的封装,
            //扩展类和方法,参数带Action<类>,类构造函数(services)执行,类内定义各种执行函数
            services.AddMessage(builder => builder.UserEmail());
            
        }

        // 配置中间件, 中间件组成管道
        // 必须的,中间件就是处理HTTP请求和响应的
        // 管道的源码,模拟实现管道
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World!"); });
            });
        }
    }
app.UseHttpsRedirection();
app.UseStaticFiles();  // 启用静态文件 中间件
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
    endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World!"); });
});
自定义服务

Services> MyMessage

public interface IMyMessage
    {
        void send();
    }
public class MyEmailMessage:IMyMessage
    {
        public void send()
        {
            // 这是邮件服务
        }
    }
    public class MySmsMessage:IMyMessage
    {
        public void send()
        {
            // 这是短信发送服务
        }
    }

Extensions

public class MyMessageServiceExtension
    {
        public static void AddMessage(
            this IServiceCollection services,
            Action<MyMessageServiceBuilder> config
        )
        {
            //services.AddSingleton<>();
            var builder = new MyMessageServiceBuilder(services);
            config(builder);
        }
    }

public class MyMessageServiceBuilder
    {
        public  IServiceCollection ServiceCollection { get; set; }
        public MyMessageServiceBuilder(IServiceCollection services)
        {
            ServiceCollection = services;
        }

        public void UserEmail()
        {
            ServiceCollection.AddSingleton<IMyMessage, MyEmailMessage>();
        }
        public void UserSms()
        {
            ServiceCollection.AddSingleton<IMyMessage, MySmsMessage>();
        }
    }

跨域 Cors

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace CorsDomainDemo
{
    public class Startup
    {
        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.AddCors(options =>
            //options.AddPolicy("cors",
            //p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials()));

            //允许一个或多个来源可以跨域
            //services.AddCors(options =>
            //{
            //    options.AddPolicy("CustomCorsPolicy", policy =>
            //    {
            //        // 设定允许跨域的来源,有多个可以用','隔开
            //        policy.WithOrigins("http://localhost:21632", "http://localhost:24661")
            //          .AllowAnyHeader()
            //           .AllowAnyMethod()
            //           .AllowCredentials();
            //    });
            //});

            // 读取配置文件内容
            OptionConfigure(services);
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<CorsOptions> corsOptions)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            // 允许所有跨域,cors是在ConfigureServices方法中配置的跨域策略名称
            //app.UseCors("cors");

            // 设定特定ip允许跨域 CustomCorsPolicy是在ConfigureServices方法中配置的跨域策略名称
            //app.UseCors("CustomCorsPolicy");

            // 设置允许所有来源跨域
            //app.UseCors(options =>
            //{
            //    options.AllowAnyHeader();
            //    options.AllowAnyMethod();
            //    options.AllowAnyOrigin();
            //    options.AllowCredentials();
            //});

            // 设置只允许特定来源可以跨域
            //app.UseCors(options =>
            //{
            //    options.WithOrigins("http://localhost:3000", "http://127.0.0.1"); // 允许特定ip跨域
            //    options.AllowAnyHeader();
            //    options.AllowAnyMethod();
            //    options.AllowCredentials();
            //});

            // 利用配置文件实现
            CorsOptions _corsOption = corsOptions.Value;
            // 分割成字符串数组
            string[] hosts = _corsOption.url.Split('|');

            // 设置跨域
            app.UseCors(options =>
            {
                options.WithOrigins(hosts);
                options.AllowAnyHeader();
                options.AllowAnyMethod();
                options.AllowCredentials();
            });

            app.UseHttpsRedirection();
            app.UseMvc();
        }

        private void OptionConfigure(IServiceCollection services)
        {
            services.Configure<CorsOptions>(Configuration.GetSection("AllowedHosts"));
        }
    }
}
第一种:配置StartUp.cs的ConfigureServices和Configure
public void ConfigureServices(IServiceCollection services)
{
    // 配置跨域处理,允许所有来源
    services.AddCors(options =>
    	options.AddPolicy("cors",
    		p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials()));
    
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<CorsOptions> corsOptions)
{
    // 允许所有跨域,cors是在ConfigureServices方法中配置的跨域策略名称
    app.UseCors("cors");

    app.UseHttpsRedirection();
    app.UseMvc();
}
第二种:配置StartUp.cs的ConfigureServices和Configure【自定义源】
public void ConfigureServices(IServiceCollection services)
{
    //允许一个或多个来源可以跨域
    services.AddCors(options =>
    {
        options.AddPolicy("CustomCorsPolicy", policy =>
        {
            // 设定允许跨域的来源,有多个可以用','隔开
            policy.WithOrigins("http://localhost:21632", "http://localhost:24661")
              .AllowAnyHeader()
               .AllowAnyMethod()
               .AllowCredentials();
        });
    });
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<CorsOptions> corsOptions)
{
    // 设定特定ip允许跨域 CustomCorsPolicy是在ConfigureServices方法中配置的跨域策略名称
    //app.UseCors("CustomCorsPolicy");

    app.UseHttpsRedirection();
    app.UseMvc();
}
第三种:只配置StartUp.cs的Configure *
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<CorsOptions> corsOptions)
{
    // 设置允许所有来源跨域
    //app.UseCors(options =>
    //{
    //    options.AllowAnyHeader();
    //    options.AllowAnyMethod();
    //    options.AllowAnyOrigin();
    //    options.AllowCredentials();
    //});

    // 设置只允许特定来源可以跨域
    //app.UseCors(options =>
    //{
    //    options.WithOrigins("http://localhost:3000", "http://127.0.0.1"); // 允许特定ip跨域
    //    options.AllowAnyHeader();
    //    options.AllowAnyMethod();
    //    options.AllowCredentials();
    //});

    app.UseHttpsRedirection();
    app.UseMvc();
}
第四种:配置StartUp.cs的ConfigureServices和Configure+AppSetting.json

appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": {
    "url": "http://localhost:21632|http://localhost:24663"
  }
}

StartUp.cs

public void ConfigureServices(IServiceCollection services)
{
    // 读取配置文件内容
    OptionConfigure(services);
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<CorsOptions> corsOptions)
{
	// 利用配置文件实现
    CorsOptions _corsOption = corsOptions.Value;
    // 分割成字符串数组
    string[] hosts = _corsOption.url.Split('|');
    // 设置跨域
    app.UseCors(options =>
    {
        options.WithOrigins(hosts);
        options.AllowAnyHeader();
        options.AllowAnyMethod();
        options.AllowCredentials();
    });
    
    app.UseHttpsRedirection();
    app.UseMvc();
}
private void OptionConfigure(IServiceCollection services)
{
    services.Configure<CorsOptions>(Configuration.GetSection("AllowedHosts"));
}
注意:有些浏览器需要Controller->Action设置Response的Header
public IActionResult GetWorker(string workNo){
    Response.Headers.Add("Access-Control-Allow-Origin", "*");  // 用于回传跨域的头
    return Json(new{Msg="OK",data=[]});
}
.NET Core 3.1跨域
public void ConfigureServices(IServiceCollection services)
{
    // 跨域
    services.AddCors(options =>
    {
        options.AddPolicy("any", builder =>
        {
            builder.WithMethods("GET", "POST", "HEAD", "PUT", "DELETE", "OPTIONS")
            //.AllowCredentials()//指定处理cookie
            .AllowAnyOrigin(); //允许任何来源的主机访问
        });
    });
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<CorsOptions> corsOptions)
{
	app.UseAuthorization();    
    // 使用跨域,要在app.UseAuthorization() 后面
    app.UseCors("any");
}

♥.net 5.0 设置跨域:特定IP/所有

// 设置跨域
app.UseCors(options =>
{
    //options.WithOrigins("http://*", "*").AllowAnyHeader().AllowAnyMethod().AllowCredentials(); // 允许特定ip跨域
    options.SetIsOriginAllowed(_=>true).AllowAnyHeader().AllowAnyMethod().AllowCredentials(); // 允许所有ip
});

管道 Pipeline

ASP.NET Core 路由,认证,会话,缓存,都是有管道来处理,中间, MVC webapi 都是建立在某个特殊的中间件之上。
MVC 路由的中间件,请求地址和控制器之间的映射,实例化控制器,执行Action,以及渲染View等一些列功能
编写中间件,扩展请求管道,可以在ASP.NET Core的基础之上,创建自己的WEB框架。

中间件 Middleware

两个职责:
1.选择是否将请求传递到管道的下一个中间件
2.在管道中的下一个中间件的前后执行工作

每一个中间件都有权力做出决定是否将请求传递到下一个中间件,也可以直接做出响应,促使管道短路,不再向下传,结束请求,直接响应,原路返回,层层。

ASP.NET MVC 过滤器:
权限验证,过滤器和中间件很相似?
都是AOP(面向切面编程)的产物,定位和关注点不一样
过滤器:如何实现功能,是功能。【是中间件的好处之一】
中间件:管道模型中的重要组成部分。担负的是整个管道的请求到相应的处理流程。

布置管道:
在管道里布置中间件。

// 配置中间件, 中间件组成管道
// 必须的,中间件就是处理HTTP请求和响应的
// 管道的源码,模拟实现管道
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // IApplicationBuilder app  用于添加中间件到管道
    // Use( 委托 ) 有next,表示可以传到下一个中间件 
    app.Use(async (context, next) =>
    {
        await context.Response.WriteAsync("Hello Middleware"); 
        await next(); // 执行下一个中间件
        await context.Response.WriteAsync("Hello Middleware end"); // 执行完下一个中间件回来的后再执行
    });
    // app.Run( Action) 中间件 就是一个委托,终端中间件,一般放在最后;如果没有Run则会返回错误
    app.Run(async context => { await context.Response.WriteAsync("Hello"); });
}

一般将中间件封装起来,不使用 Use和Run在配置内编写。

中间件是有顺序的。
添加中间件的顺序就是调用中间件的顺序。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // 环境名称 Development
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage(); // 开发人员异常页面中间件
    }
    
    // 终结点(端点) 路由中间件,  用于路由请求匹配
    // ASP.NET CORE 2.X 没有这个
    // ASP.NET CORE 3.X 
    app.UseRouting(); // 
    // 还可以添加一些其他的中间件
    
    // 终结点中间件 必须要与 UseRouting(),成对出现, 用于路由请求匹配的配置
    // 是配置,配置中间件和路由器的之间关系,映射
    // 终结点中间件 可以理解为 MVC的 /控制器/action
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World!"); });
    });
}

自定义中间件:

约定:
具有类型RequestDelegate的参数公共构造函数
名为 invoke 或者 invokeAsync 的方法。

public class MyTestMiddleware
{
    private RequestDelegate _next;
    public MyTestMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    public async Task InvorkAsync(HttpContext httpContext)
    {
        // 在这里写中间件的业务代码
        // HTTP请求处理
        await _next(httpContext);
        // HTTP 响应处理
    }
}

自定义中间件使用:

app.UseMiddleware<MyTestMiddleware>();

或者使用扩展类方法

public static class CustonMiddlewareExtensions
{
    public static IApplicationBuilder UseMyTestMiddleware(this IApplicationBuilder app){
    	return app.UseMiddleware<MyTestMiddleware>();
    }
}

// StartUp 内使用 app.UseMyTestMiddleware();

ASP.NET Core 源代码:
GitHub Clone下来
双击运行 restore.cmd, 命令行文件运行,还原源代码环境
没有提供整个解决文案的sln
SRC文件夹,【http】文件夹内源码,管道。
先运行 startvs.cmd , 再打开sln

路由:

静态文件

默认为“wwwroot”文件夹,存在Project/wwwroot
修改配置文件夹名:
program.cs

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                    //webBuilder.UseUrls("http://127.0.0.1:8099");
                    //webBuilder.UseContentRoot("public");  // 修改静态文件夹名称
                });

Startup.cs

app.UseHttpsRedirection();
app.UseStaticFiles();  // 启用静态文件 中间件
app.UseRouting();
app.UseAuthorization();

Nuget 包管理器(.NET)

Libman 库管理器(CSS/JS)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

ASP.NET MVC 捆绑和压缩
JS和CSS,请求,
捆绑,可以把一堆JS绑到一个文件里

ASP.NET Core 捆绑和压缩

在这里插入图片描述

1.优化系统,Nuget 安装: BuildBundlerMinifier
2.新增一个** bundleconfig.json**
捆绑+压缩:

[
  {
  	"outputFileName":"wwwroot/css/site.css",
    "inputFiles":[
    	"wwwroot/site.css",
      "wwwroot/index.css"
    ]
  }
]

捆绑,不压缩:

 {
  	"outputFileName":"wwwroot/css/site.css",
    "inputFiles":[
    	"wwwroot/site.css",
      "wwwroot/index.css"
    ],
    "minify":{
    	"enabled":false
    }
  }

使用IHttpClientFactory+Polly

NuGet安装 Microsoft.Extensions.Http.Polly 扩展:

1.Startup.cs

public void ConfigureServices(IServiceCollection services)
{
	services.AddHttpClient(); // 注册IHttpClientFactory
}

HttpClientHelper.cs

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
// using System.Text.Json; // 使用 Objs = await JsonSerializer.DeserializeAsync<IEnumerable<T>>(responseStream);
namespace Helper
{
    /*
        使用:          
    */
    public class HttpClientHelper
    {    
        private static readonly object LockObj = new object();
        private static HttpClient client;
        public string Msg{get;private set;}  // 返回信息
        public HttpClientHelper()
        {
            GetInstance();
            this.Msg="OK";
        }

        public static HttpClient GetInstance()
        {
            if (client == null)
            {
                lock (LockObj)
                {
                    if (client == null)
                    {
                        client = new HttpClient();
                    }
                }
            }
            return client;
        }

        /// <summary>
        /// 基础调用,所有方法都最终调用此函数
        /// </summary>
        public async Task<HttpResponseMessage> PostAsync(Func<HttpResponseMessage> func)
        {
            try
            {
                return await Task.Run(func);          
            }
            catch(Exception ex)
            {
                string str = ex.StackTrace;
                Msg = "Error : "
                + str.Substring(str.LastIndexOf("\\") + 1, str.Length - str.LastIndexOf("\\") - 1)
                + "--" + ex.Message;
                return new HttpResponseMessage(){
                    Content = new StringContent(Msg)
                };
            }
        }

        public async Task<HttpResponseMessage> PostMultiFDAsync(string url,Dictionary<string,string> contents)
        {
            return await PostAsync(()=>{
                using(var formDC = new MultipartFormDataContent()){          
                    foreach(string key in contents.Keys){  // 添加请求的内容参数
                        formDC.Add(new StringContent(contents[key]),key);
                    }
                    return client.PostAsync(url,formDC).Result;
                }
            });
        } // end OnGet

        public async Task<HttpResponseMessage> PostUrlFDAsync(string url,Dictionary<string,string> contents)
        {
            return await PostAsync(()=>{
                var ls = new List<KeyValuePair<string, string>>();  
                foreach(string key in contents.Keys){  // 添加请求的内容参数
                    ls.Add(new KeyValuePair<string, string>(key,contents[key]));
                }
                HttpContent hc = new FormUrlEncodedContent(ls);                     
                return client.PostAsync(url,hc).Result;                                           
            });
        }

        public async Task<HttpResponseMessage> GetAsync(string url){
            try
            {
                var response = await client.GetAsync(url); // 客户端发送请求
                Msg =await response.Content.ReadAsStringAsync();
                return response;
            }catch(Exception ex)
            {
                string str = ex.StackTrace;
                Msg = "Error : "
                + str.Substring(str.LastIndexOf("\\") + 1, str.Length - str.LastIndexOf("\\") - 1)
                + "--" + ex.Message;
                return new HttpResponseMessage(){
                    Content = new StringContent(Msg)
                };
            }
        }

    }
}

SWEmailHelper.cs

using System;
using System.Collections.Generic;

namespace Helper
{
    public class SWEmailHelper
    {
        #region 邮件预警
        public static string SendEmail(string MAIL_URL, Dictionary<string,string> dic)
        {
            // return WCF_Use_Helper.WCF_SDTEmail_Helper.SendMail(to, cc, subject, content);
            var caller = new HttpClientHelper();
            var ret = caller.PostMultiFDAsync(MAIL_URL,dic);
            return ret.Result.Content.ReadAsStringAsync().Result;
        }

        public static string MailMsgMaker(string date,string msg,string sysUrl,string sysName)
        {
            string txt = @"<style>.table-l{border:1px double #494e8f;}.table-l tr td,th{border:1px solid #78cdd1; padding:1rem; }</style>
<table class='table-l'><tr><th>日期</th><th>提示信息</th><th>网址</th></tr>
<tr><td>"+ date + "</td><td>"+msg+ "</td><td><a href='"+sysUrl+"' target='_blank'>"+sysName+"</a></td></tr></table>";
            return txt;
        }

        public static string SendEmail_main(string emailAPIUrl,List<string> tos,List<string> ccs, string title, string msg,string sysUrl,string sysName)
        {
            string to = "";
            string cc = "";
            foreach(var s in tos){
                to+=s+";";
            }
            foreach(var s in ccs){
                cc+=s+";";
            }
            string content = MailMsgMaker(DateTime.Now.ToString("yyyy-MM-dd"),msg,sysUrl,sysName);
            content = Convert.ToBase64String(System.Text.UTF8Encoding.UTF8.GetBytes(content)); //内容是html,有非法字符,需要转化后传输
            Dictionary<string,string> dic = new Dictionary<string, string>();
            dic.Add("to",to);
            dic.Add("cc",cc);
            dic.Add("title",title);
            dic.Add("content",content);
            var rlt =  SendEmail(emailAPIUrl,dic);
            return rlt;
        }
        #endregion
    }
}

处理临时故障

动态选择策略

添加多个 Polly 处理程序

从 Polly 注册表添加策略

四.实例开发步骤

1.编码:

2.发布:

3.部署:

【发布】–【框架依赖/独立】【可移植/Linux/Win64/win86】

依赖框架的部署(FDD):

【框架依赖】【可移植】
依赖系统以安装的.NET Core库,包含自己的代码和第三方的依赖项
包含.dll,dotnet执行
优点:
不必先预先定义应用运行的目标操作系统,生产的可执行文件,通用的PE文件格式,.NET Core都可以执行
部署包很小
降低磁盘控件
如果运行时更新了,只需要更新操作系统
缺点:
系统上.NET Core版本>=应用的版本

独立部署(SCD):

【独立】【Linux/Win64/win86】
不依赖系统的.NET Core
代码+第三方库+.NET Core库+可执行文件.EXE/.DLL
优点:
保证应用是可执行的
缺点:
不可移植,只能对应的目标系统
文件较大

依赖框架的可执行文件(FDE):

【框架依赖】【Linux/Win64/win86】
依赖系统的 .NET Core , 只能运行在特定的系统。

部署到IIS:

https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/publish-to-iis?view=aspnetcore-5.0&tabs=visual-studio

IIS需要先安装 AspNetCoreModule,下载链接
在这里插入图片描述

进程内托管(优先):
在这里插入图片描述

进程管理器(IIS/windows服务),收到请求的时候启用应用,并且在应用发生故障时负责重启
性能比进程外要高,直接把请求给应用(不使用kestrel)

进程外托管:
在这里插入图片描述

通过反向代理将请求转发给应用
多了一层转发,环回适配器(网络接口,)

ASP.NET Core Kestrel 只是性能高,但 功能太弱,不易暴露出去

1.确保已经安装了AspNetCoreModule
2.添加IIS网站-网站名+文件夹+端口
3.修改程序池为【无托管代码】

在这里插入图片描述

4.确保已有处理程序映射

在这里插入图片描述

5.修改进程内外:

执行文件夹的web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <aspNetCore ... hostingModel="inprocess" /> 
      <!-- inprocess 进程内, outofprocess 进程外 -->
    </system.webServer>
  </location>
</configuration>
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值