.net core 3.1常用总结

 

1.读取JSON配置

        

public class ConfigerHelper

    {

        public static string GetSection(string sectionName)

        {

            //添加 json 文件路径

            var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");

            //创建配置根对象

            var configurationRoot = builder.Build();

            //取配置根下的 name 部分

            var nameSection = configurationRoot.GetSection(sectionName);

            return nameSection.Value;

 

        }

    }

 

使用DLL:

Microsoft.Extensions.Configuration

 

 

 

2.配置端口

public class Program

    {

        public static void Main(string[] args)

        {

            CreateHostBuilder(args).Build().Run();

        }

 

        public static IHostBuilder CreateHostBuilder(string[] args) =>

            Host.CreateDefaultBuilder(args)

                .ConfigureAppConfiguration(builder =>

                {

                    builder.AddJsonFile("appsettings.json", optional: true);

                })

                .ConfigureWebHostDefaults(webBuilder =>

                {

                    webBuilder.UseStartup<Startup>();

                });

    }

JSON配置文件

{

    "Logging": {

        "LogLevel": {

            "Default": "Information",

            "Microsoft": "Warning",

            "Microsoft.Hosting.Lifetime": "Information"

        }

    },

    "AllowedHosts": "*",

    "Port": "9000",

    "urls": "http://*:5102"

 

 

}

 

3.配置跨域

public void ConfigureServices(IServiceCollection services)

        {

            services.AddControllers();

 

            services.AddCors(options => {

                options.AddPolicy("any", builder => { builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); });

            });

 

        }

 

 

 

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

        {

 

            app.UseCors("any");

 

            if (env.IsDevelopment())

            {

                app.UseDeveloperExceptionPage();

            }

 

            app.UseRouting();

 

            app.UseAuthorization();

 

            app.UseEndpoints(endpoints =>

            {

                endpoints.MapControllers();

            });

        }

 

使用了dll:

 

4.AJAX和API参数

Ajax传递参数,api接受参数,2者需要搭配使用。

 

4.1 jq ajax 参数

 

type:字符串,默认值值是get ,可选值是get,post,表示是get请求还是post请求。

 

url:字符串,表示请求的地址

 

dataType:字符串,主要是json,text,xml,jsonp,script,表示预期服务器返回的数据类型。如果不指定,则jq根据

响应头的content-type 进行判断。

 

data:字符串,表示发送到服务器的数据。

         注意这里data的数据类型是字符串,而我写成对象形式也是正确的, data:{Code1:'Nam11e',Code2:'Pas22s'}。

         这里有个默认的数据处理,如果 processData设置为true,则会对数据进行转换成Code1=Nam11e&Code2=Pas22s。

 

processData:布尔类型,默认值true。

 

contentType:字符串,默认值: "application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。

默认值适合大多数情况,但是有时候需要设置,比如post请求上传JSON数据,此时设置为application/json 。dataType是服务器返回的数据类型,

 

contypeType是上传的数据类型。

 

success:函数 成功时调用 function(data,state){} 参数是data:ajax返回的数据,state,ajax的状态

 

error:函数 失败时调用 function(xhr, textStatus, errorThrown){} 参数时xhr:xhr 对象,textStatus:错误状态,errorThrown 异常

 

 

 

 

 

4.2get请求

 

前端:

//ajax1

$.ajax({

            type:'get',

            url:'http://localhost:5102/test/getName',

            dataType:'text',

            data:{Code1:'Nam11e',Code2:'Pas22s'},

            success:function(data,dataState){

                alert(JSON.stringify(data));

            },

            error: function (xhr, textStatus, errorThrown) {

                alert(textStatus);

        }

        });

                  

//ajax2

$.ajax({

            type:'get',

            url:'http://localhost:5102/test/getName?Code1=Nam11e&Code2=Pas22s',

            dataType:'text',

            success:function(data,dataState){

                alert(JSON.stringify(data));

            },

            error: function (xhr, textStatus, errorThrown) {

                alert(textStatus);

        }

        });

                  

//ajax3

$.ajax({

            type:'get',

            url:'http://localhost:5102/test/getName',

            dataType:'text',

            data:'Code1=Nam11e&Code2=Pas22s',

            success:function(data,dataState){

                alert(JSON.stringify(data));

            },

            error: function (xhr, textStatus, errorThrown) {

                alert(textStatus);

        }

        });

                  

        

后端:

 

[HttpGet]

        [Route("[action]")]

        public List<string> GetName(string Code1,string Code2)

        {

            List<string> ts = new List<string>();

            ts.Add("001");

            ts.Add("002");

            return ts;

        }

                  

 

get请求,无论如何,所有的参数都会被附加到url上。这是因为processData默认为true。

 

4.3post请求

 

前端:

 

 $.ajax({

            type:'post',

            url:'http://localhost:5102/test/getName',

            dataType:'text',

            data:JSON.stringify({Code1:'Name',Code2:'Pass'}),

            success:function(data,dataState){

                alert(JSON.stringify(data));

            },

            contentType:'application/json; charset=utf-8',

            error: function (xhr, textStatus, errorThrown) {

                alert(textStatus);

        }

        });

                  

[HttpPost]

        [Route("[action]")]

        public List<string> GetName(Dictionary<string,string> obj)

        {

            List<string> ts = new List<string>();

            ts.Add("001");

            ts.Add("002");

            return ts;

        }

                  

                  

post的请求和get相比有3个变化

1.客户端ajax 的 contentType:'application/json; charset=utf-8'

2.客户端ajax 的 data:JSON.stringify({Code1:'Name',Code2:'Pass'}),

3.服务端的参数 变成了一个对象 Dictionary<string,string> obj,

 

 

 

 

4.3如何在Post传递更加复杂和灵活的参数?

 

https://docs.microsoft.com/zh-cn/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api#using-frombody

 

默认情况下,Web API 使用以下规则来绑定参数:

如果该参数为 "simple" 类型,则 Web API 会尝试从 URI 获取值。 简单类型包括 .NET 基元类型 (int、 bool、 double 等) ,以及 TimeSpan、 DateTime、 Guid、 decimal 和 string,

以及具有可从字符串转换的类型转换器 的任何类型 。 稍后 (有关类型转换器的详细信息。 )

对于复杂类型,Web API 会尝试使用 媒体类型格式化程序从消息正文中读取值。

 

 

后端使用了泛型和简单实体,很复杂的数据都可以传递过去。

为什么obj参数可以接受复杂的类型呢?

 

Data<TestEntity,List<Dictionary<string,string>>,int,string> 复杂类型使用媒体类型查询,

这里就是JSON数据,把JSON数据转成c#对象。

这里里数据要么是简单类型int,string,要么是包含简单类型的对象实体。

 

前端:

$.ajax({

            type:'post',

            url:'http://localhost:5102/PutReport/GetName',

            dataType: 'text',

            data: JSON.stringify({ Value1: { Name: "OP01", Score: 90 }, Value2: [{ Code1: 'code1' }], Value3: 23, Value4:'parent' }),

            success:function(data,dataState){

                alert(JSON.stringify(data));

            },

           // processData:false,

            contentType:'application/json; charset=utf-8',

            error: function (xhr, textStatus, errorThrown) {

                alert(errorThrown);

        }

        });

 

后端:

   public class Data

    {

       

    }

 

    public class Data<T>:Data

    {

       public T Value1 { get; set; }

    }

 

    public class Data<T,T1> : Data<T>

    {

        public T1 Value2 { get; set; }

    }

 

    public class Data<T,T1,T2> : Data<T,T1>

    {

        public T2 Value3 { get; set; }

    }

 

    public class Data<T,T1,T2,T3> : Data<T,T1, T2>

    {

        public T3 Value4 { get; set; }

    }

 

 

    public class TestEntity

    {

        public string Name { get; set; }

        public int score { get; set; }

 

 

}

 

 

public class PutReport: ServiceBas

    {

        [HttpPost]

        public string GetName(string UserCode,string UserName,string UserId,

            Data<TestEntity,List<Dictionary<string,string>>,int,string> obj)

        {

            return "";

        }

}

 

 

4.4文件上传

曾经有一种方法使用formdata,但是不够通用。

还有一种方法更加通用,使用FileReade读取文件到字符串中。

 

5.依赖注入

         名字比较拗口,术语难以理解。

         从结果出发吧,只讲使用和结果。

        

        

         https://docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/dependency-injection?view=aspnetcore-3.1

        

        

         1.控制器添加依赖注入

                   1.定义一个接口

                   public interface IDateTime

                   {

                            DateTime Now { get; }

                   }

                   2.定义一个实现

                   public class SystemDateTime : IDateTime

                   {

                            public DateTime Now

                            {

                                     get { return DateTime.Now; }

                            }

                   }

                   3.注册.net core服务

                    public void ConfigureServices(IServiceCollection services)

        {

            services.AddControllers();

            services.AddSingleton<IDateTime, SystemDateTime>();//添加单例服务 第一个参数是接口,第二个参数是实现类,

        }

                   4.控制器访问服务

                  

                   [ApiController]

                   [Route("[controller]")]

                   public class TestController : ControllerBase

                   {

                            private readonly IDateTime _dateTime;

 

                            public TestController(IDateTime dateTime)

                            {

                                     _dateTime = dateTime;

 

                            }

                            [HttpGet]

                            [Route("[action]")]

                            public string GetName()

                            {

                                     return _dateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                            }

                   }

                  

                   依赖注入框架到底做了什么呢?

                   当控制器类运行构造函数的时候,创建一个SystemDateTime,赋值给dateTime变量。

                   依赖注入框架做了2件事情,1.当需要创建对象的时候,框架创建了对象并且赋值。

                   2.框架创建对象的时候还保证了对象是单例的。AddSingleton就要求创建是单例的。

                  

                   所谓的服务就是一项功能,为了保证程序的扩展良好,通常需要定义接口和实现类。

                  

        

         2.更加复杂的依赖注入

                   当有多层结构的时候,每一层都应该有接口和实现。

                   比如 A使用B的功能,B使用C的功能。

                   1.接口和类的定义

                   public class A

                   {

                            private IB _bx;

                            public A(IB bx)

                            {

                                     _bx = bx;

                            }

                            public string GetName()

                            {

                                     return _bx.GetColor()+"ATest_";

                            }

                   }

 

                   public interface IB

                   {

                            string GetColor();

                   }

 

            public class B : IB

                   {

                            private IC _cx;

                            public B(IC cx)

                            {

                                     _cx = cx;

                            }

                            public string GetColor()

                            {

                                     return _cx.GetHome()+"BTest_";

                            }

                   }

 

                   public interface IC

                   {

                            string GetHome();

                   }

 

                   public class C:IC

                   {

                            public string GetHome()

                            {

                                     return "CTest_";

                            }

                   }

                  

                  

         2.注册服务

          public void ConfigureServices(IServiceCollection services)

        {

            services.AddControllers();

 

            services.AddCors(options => {

                options.AddPolicy("any", builder => { builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); });

            });

 

            services.AddScoped<A>()

                .AddScoped<IB,B>()

                .AddScoped<IC,C>();

        }

                  

                  

         3.使用服务     

    [ApiController]

    [Route("[controller]")]

    public class TestController : ControllerBase

    {

        public readonly A _a;

        public TestController(A a)

        {

            _a = a;

        }

        [HttpGet]

        [Route("[action]")]

        public string GetName()

        {

            return _a.GetName();

        }

         }

        

         这里就有好几层的依赖关系了,

         这里使用了AddTransient,AddSingleton,AddScoped的区别在于对象的生命周期不一样。

        

        

        

         3.为什么我看到的系统注册服务都是AddControllers,AddCors而不是 AddScoped?

          public void ConfigureServices(IServiceCollection services)

        {

            services.AddControllers();

 

            services.AddCors(options => {

                options.AddPolicy("any", builder => { builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); });

            });

                   }

        

        

         ASP.NET Core 框架使用一种约定来注册一组相关服务。 约定使用单个 Add{GROUP_NAME} 扩展方法来注册该框架功能所需的所有服务。

         例如,AddControllers 扩展方法会注册 MVC 控制器所需的服务,

         AddControllersWithViews 会添加带视图的 MVC 控制器所需的服务,

         AddRazorPages 会添加 Razor Pages 所需的服务。

 

 

6.控制器

 

interface IService

    {

      

    }

 

 

    [ApiController]

    [Route("[controller]/[action]")]

    [ActionFilter]

    public class ServiceBas : ControllerBase,IService

    {

        public string BookCode { get; set; }

        public ServiceBas()

        {

 

        }

    }

 

    public class PutReport: ServiceBas

    {

        [HttpGet]

        public string GetName(string bookCode)

        {

            return bookCode;

        }

 

        [HttpGet]

 

        public string GetSex(string bookCode)

        {

            return bookCode;

        }

 

}

 

 

public class ActionFilter : Attribute, IActionFilter

    {

        public void OnActionExecuted(ActionExecutedContext context)

        {

 

        }

 

        public void OnActionExecuting(ActionExecutingContext context)

        {

            string user = context.HttpContext.Request.Cookies.FirstOrDefault(m => m.Key == "user").Value;

            var ret = context.Controller as ServiceBas;

            ret.BookCode = user;

            context.ActionArguments.Add("bookCode", user);

        }

    }

 

 

IService接口是自定义的接口,ServiceBase是自定义的普通类,但是只有这个类加上

[ApiController] [Route("[controller]/[action]")]2个特性,就变成了一个webapi的类。

 

过滤器:

         1.可以获取request对象,reponse对象,result对象

         2.可以设置action的参数值,这里从cookie获取信息,传递到action的参数

        

ActionExecutingContext

 

context.Controller 获取action所属的控制器。

context.HttpContext 获取action的上下文

context.HttpContext.Request 请求对象

context.HttpContext.Response 响应对象

context.ActionDescriptor action相关信息

context.ActionArguments action参数列表

context.Result action 执行结果

context.RouteData action 路由数据

 

 

IActionResult 接口的所有类型

 

ContentResult 返回一串字符串

FileContentResult    返回文件内容

FilePathResult 返回路径文件的内容

EmptyResult    返回空值

JavaScriptResult      返回一段JavaScript代码

JsonResult        返回Json格式数据

RedirectToResult     重定向到其他URL

HttpUnauthorizedResult          返回HTTP403未授权状态码

RedirectToRouteResult   重定向到不同的控制器动作

ViewResult       接收视图引擎的响应

PartialViewResult    接收分部视图引擎的响应

 

7.中间件

反向代理中间件测试:

 

 

public class ProxyMiddleware

    {

        private static readonly HttpClient _httpClient = new HttpClient();

        private readonly RequestDelegate _nextRequestDelegate;

        private static readonly string _targetUri =  "http://localhost:8080";

        public ProxyMiddleware(RequestDelegate nextMiddleware)

        {

            _nextRequestDelegate = nextMiddleware;

        }

        public async Task Invoke(HttpContext context)

        {

            bool validateUri = false;

            if (context.Request.Path.StartsWithSegments("/api", out var Path))

            {

                validateUri = true;

            }

            if (validateUri == true)

            {

                var targetRequestMessage = CreateTargetMessage(context);

                using (var responseMessage = await _httpClient.SendAsync(targetRequestMessage))

                {

                    context.Response.StatusCode = (int)responseMessage.StatusCode;

                    CloneResponseHeadersIntoContext(context, responseMessage);

                    await responseMessage.Content.CopyToAsync(context.Response.Body);

                }

                return;

            }

            await _nextRequestDelegate(context);

        }

        private void CloneRequestContentAndHeaders(HttpContext context, HttpRequestMessage requestMessage)

        {

            foreach (var header in context.Request.Headers)

            {

                requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());

            }

        }

        private HttpRequestMessage CreateTargetMessage(HttpContext context)

        {

            var requestMessage = new HttpRequestMessage();

            CloneRequestContentAndHeaders(context, requestMessage);

            requestMessage.RequestUri = new Uri(_targetUri+context.Request.Path.Value);

            requestMessage.Headers.Host = requestMessage.RequestUri.Host;

            requestMessage.Method = new HttpMethod(context.Request.Method);

            return requestMessage;

        }

        private void CloneResponseHeadersIntoContext(HttpContext context, HttpResponseMessage responseMessage)

        {

            foreach (var header in responseMessage.Headers)

            {

                context.Response.Headers[header.Key] = header.Value.ToArray();

            }

            foreach (var header in responseMessage.Content.Headers)

            {

                context.Response.Headers[header.Key] = header.Value.ToArray();

            }

            context.Response.Headers.Remove("Transfer-Encoding");

        }

    }

 

Startup.cs

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

        {

            app.UseCors("any");

           // app.UseCookiePolicy();

            app.UseStaticFiles();

 

            if (env.IsDevelopment())

            {

                app.UseDeveloperExceptionPage();

            }

 

            app.UseRouting();

 

            app.UseAuthorization();

 

            app.UseMiddleware<ProxyMiddleware>();//使用中间件

 

            app.UseEndpoints(endpoints =>

            {

                endpoints.MapControllers();

            });

        }

 

 

这里5102的端口的api转发到8080端口上。

UseMiddleware()的顺序很重要,因为中间件的执行是由顺序的。

这里httpClient负责转发,如果不符合条件,则不进行转发,执行

await _nextRequestDelegate(context);

 

8.使用Newtonsoft替换默认WEBAPI序列功能

返回datatable 也可以自动序列化。

使用Newtonsoft.Json和 Microsoft.AspNetCore.Mvc.Newtonsoft

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers()
            .AddNewtonsoftJson(options =>
             {
                 //修改属性名称的序列化方式,首字母小写
                 options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

                 //修改时间的序列化方式
                 options.SerializerSettings.Converters.Add(new IsoDateTimeConverter() { DateTimeFormat = "yyyy/MM/dd HH:mm:ss" });
             });
        }

9.前后端分离

静态文件设置固定目录,通过配置文件配置。

 app.UseStaticFiles(new StaticFileOptions()
            {
                FileProvider = new PhysicalFileProvider(@"D:\工作\个人信息\XONE\File"),
                RequestPath = new PathString("/file")
            });

总结:

这里把常见的问题整理一下,有些问题看似简单,但是好久也不明白,比如webapi传递参数,这跟后台有关,也跟前台ajax有关。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值