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

这里写目录标题

  • 一.安装
  • 二.基础概念
    • 微服务架构:
  • 三.知识讲解
    • Program.cs
    • Kestrel的URL配置的优先级 低-高:
        • 环境变量:
        • 硬编码:
        • 应用配置:
        • 命令行:
    • Startup.cs
        • 自定义服务
    • 跨域 Cors
        • 第一种:配置StartUp.cs的ConfigureServices和Configure
        • 第二种:配置StartUp.cs的ConfigureServices和Configure【自定义源】
        • 第三种:只配置StartUp.cs的Configure *
        • 第四种:配置StartUp.cs的ConfigureServices和Configure+AppSetting.json
        • 注意:有些浏览器需要Controller->Action设置Response的Header
        • .NET Core 3.1跨域
      • ♥.net 5.0 设置跨域:特定IP/所有
    • 管道 Pipeline
      • 中间件 Middleware
      • 自定义中间件:
    • 路由:
    • 静态文件
      • Libman 库管理器(CSS/JS)
      • ASP.NET Core 捆绑和压缩
    • 使用IHttpClientFactory+Polly
      • 1.Startup.cs
      • HttpClientHelper.cs
      • SWEmailHelper.cs
      • 处理临时故障
      • 动态选择策略
      • 添加多个 Polly 处理程序
      • 从 Polly 注册表添加策略
  • 四.实例开发步骤
    • 1.编码:
    • 2.发布:
    • 3.部署:
      • 依赖框架的部署(FDD):
      • 独立部署(SCD):
      • 依赖框架的可执行文件(FDE):
      • 部署到IIS:
        • 1.确保已经安装了AspNetCoreModule
        • 2.添加IIS网站-网站名+文件夹+端口
        • 3.修改程序池为【无托管代码】
        • 4.确保已有处理程序映射
        • 5.修改进程内外:

一.安装

直接使用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
【C#】.Net Core基础入门到实例部署_第1张图片

启动:
自宿主启动
wwwroot文件夹,静态文件
【C#】.Net Core基础入门到实例部署_第2张图片

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

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

HOST有2种:
通用:
webhost:
【C#】.Net Core基础入门到实例部署_第3张图片

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

反向代理:额外的安全配置,HTTPS比较好配置
【C#】.Net Core基础入门到实例部署_第4张图片

配置主机:
组件配置

微服务架构:

【C#】.Net Core基础入门到实例部署_第5张图片

三.知识讲解

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"开头
【C#】.Net Core基础入门到实例部署_第6张图片

【C#】.Net Core基础入门到实例部署_第7张图片

硬编码:

Program.cs

webBuilder.UseUrls("http://*:8081"); // 硬编码

应用配置:

【C#】.Net Core基础入门到实例部署_第8张图片

命令行:

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

【C#】.Net Core基础入门到实例部署_第9张图片

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(); // 注册单例
            // services.AddSingleton(); // 注册单例 ,一个一个注册,也可以批量
            // 服务,生存期,配置
            // 自带的不好用,可以换成第三方的
            // 依赖注入框架很多:第三方: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)

【C#】.Net Core基础入门到实例部署_第10张图片

【C#】.Net Core基础入门到实例部署_第11张图片
【C#】.Net Core基础入门到实例部署_第12张图片

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

ASP.NET Core 捆绑和压缩

【C#】.Net Core基础入门到实例部署_第13张图片

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

        /// 
        /// 基础调用,所有方法都最终调用此函数
        /// 
        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 = @"
日期提示信息网址
"+ date + ""+msg+ ""+sysName+"
"
; 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,下载链接
【C#】.Net Core基础入门到实例部署_第14张图片

进程内托管(优先):
【C#】.Net Core基础入门到实例部署_第15张图片

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

进程外托管:
【C#】.Net Core基础入门到实例部署_第16张图片

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

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

1.确保已经安装了AspNetCoreModule

2.添加IIS网站-网站名+文件夹+端口

3.修改程序池为【无托管代码】

【C#】.Net Core基础入门到实例部署_第17张图片

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

【C#】.Net Core基础入门到实例部署_第18张图片

5.修改进程内外:

执行文件夹的web.config:


<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <aspNetCore ... hostingModel="inprocess" /> 
      
    system.webServer>
  location>
configuration>

你可能感兴趣的:(c#,.netcore,asp.net)