当前位置: 首页 > news >正文

徐州网站建设技术外包网线制作实验心得体会

徐州网站建设技术外包,网线制作实验心得体会,专业企业app开发制作,集团网站设计开发ASP.NET的路由是通过EndpointRoutingMiddleware和EndpointMiddleware这两个中间件协作完成的#xff0c;它们在ASP.NET平台上具有举足轻重的地位#xff0c;MVC和gRPC框架#xff0c;Dapr的Actor和发布订阅编程模式都建立在路由系统之上。Minimal API更是将提升到了前所未有…ASP.NET的路由是通过EndpointRoutingMiddleware和EndpointMiddleware这两个中间件协作完成的它们在ASP.NET平台上具有举足轻重的地位MVC和gRPC框架Dapr的Actor和发布订阅编程模式都建立在路由系统之上。Minimal API更是将提升到了前所未有的高度上一篇通过9个实例演示了基于路由的REST API开发本篇演示一些“高阶”的用法。[S2010]解析路由模式 源代码[S2011]利用多个中间件来构建终结点处理器源代码[S2012]在参数上标注特性来决定绑定的数据源源代码[S2013]默认的参数绑定规则源代码[S2014]针对TryPar[Se方法的参数绑定源代码[S2015]针对BindA[Sync方法的参数绑定源代码[S2016]自定义路由约束源代码[S2010]解析路由模式下面我们通过一个简单的实例演示如何利用RoutePatternFactory对象解析指定的路由模板并生成对应的RoutePattern对象。我们定义了如下所示的Format方法将指定的RoutePattern对象格式化成一个字符串。static string Format(RoutePattern pattern) {var builder  new StringBuilder();builder.AppendLine($RawText:{pattern.RawText});builder.AppendLine($InboundPrecedence:{pattern.InboundPrecedence});builder.AppendLine($OutboundPrecedence:{pattern.OutboundPrecedence});var segments  pattern.PathSegments;builder.AppendLine(Segments);foreach (var segment in segments){foreach (var part in segment.Parts){builder.AppendLine($\t{ToString(part)});}}builder.AppendLine(Defaults);foreach (var default in pattern.Defaults){builder.AppendLine($\t{default.Key}  {default.Value});}builder.AppendLine(ParameterPolicies );foreach (var policy in pattern.ParameterPolicies){builder.AppendLine( $\t{policy.Key}  {string.Join(,,policy.Value.Select(it  it.Content))});}builder.AppendLine(RequiredValues);foreach (var required in pattern.RequiredValues){builder.AppendLine($\t{required.Key}  {required.Value});}return builder.ToString();static string ToString(RoutePatternPart part) part switch{RoutePatternLiteralPart literal  $Literal: {literal.Content},RoutePatternSeparatorPart separator  $Separator: {separator.Content},RoutePatternParameterPart parameter  $Parameter: Name  {parameter.Name}; Default  {parameter.Default}; IsOptional  { parameter.IsOptional}; IsCatchAll  { parameter.IsCatchAll};ParameterKind  { parameter.ParameterKind},_  throw new ArgumentException(Invalid RoutePatternPart.)}; }如下的演示程序调用了RoutePatternFactory 类型的静态方法Parse解析指定的路由模板“weather/{city:regex(^0\d{{2,3}}$)010}/{days:int:range(1,4)4}/{detailed?}”生成一个RoutePattern对象我们在调用该方法时还指定了requiredValues参数。我们调用创建的WebApplication对象的MapGet方法注册了针对根路径“/”的终结点对应的处理器直接返回RoutePattern对象格式化生成的字符串。using Microsoft.AspNetCore.Routing.Patterns; using System.Text;var template weather/{city:regex(^0\d{{2,3}}$)010}/{days:int:range(1,4)4}/{detailed?}; var pattern  RoutePatternFactory.Parse(pattern: template,defaults: null,parameterPolicies: null,requiredValues: new { city  010, days  4 });var app  WebApplication.Create(); app.MapGet(/, () Format(pattern)); app.Run();如果利用浏览器访问启动后的应用程序回到得到如图1所示结果它结构化地展示了路由模式的原始文本、出入栈路由匹配权重、每个段的组成、路由参数的默认值和参数策略以及生成URL必须提供的默认参数值。图1 针对路由模式的解析[S2011]利用多个中间件来构建终结点处理器如果某个终结点针对请求处理的逻辑相对复杂需要多个中间件协同完成我们可以调用IEndpointRouteBuilder 对象的CreateApplicationBuilder方法创建一个新的IApplicationBuilder对象并将这些中间件注册到这个该对象上最后利用它这些中间件转换成RequestDelegate委托。var app  WebApplication.Create(); IEndpointRouteBuilder routeBuilder  app; app.MapGet(/foobar, routeBuilder.CreateApplicationBuilder().Use(FooMiddleware).Use(BarMiddleware).Use(BazMiddleware).Build()); app.Run();static async Task FooMiddleware(HttpContext context,RequestDelegate next) {await context.Response.WriteAsync(Foo);await next(context); }; static async Task BarMiddleware(HttpContext context, RequestDelegate next) {await context.Response.WriteAsync(Bar);await next(context); }; static Task BazMiddleware(HttpContext context, RequestDelegate next)  context.Response.WriteAsync(Baz);上面的演示程序注册了一个路径模板为“foobar”的路由并注册了三个中间件来处理路由的请求。该演示程序启动之后如果我们利用浏览器对路由地址“/foobar”发起请求将会得到如图2所示的输出结果。呈现出来的字符串是通过注册的三个中间件FooMiddleware、BarMiddleware和BazMiddleware输出内容组合而成。图2 输出结果[S2012]在参数上标注特性来决定绑定的数据源如下这个演示程序调用WebApplication对象的MapPost方法注册了一个采用“/{foo}”作为模板的终结点。作为终结点处理器的委托指向静态方法Handle我们为这个方法定义了五个参数分别标注了上述五个特性。我们将五个参数组合成一个匿名对象作为返回值。using Microsoft.AspNetCore.Mvc; var app  WebApplication.Create(); app.MapPost(/{foo}, Handle); app.Run();static object Handle([FromRoute] string foo,[FromQuery] int bar,[FromHeader] string host,[FromBody] Point point,[FromServices] IHostEnvironment environment) new { Foo  foo, Bar  bar, Host  host, Point  point,Environment  environment.EnvironmentName };public class Point {public int X { get; set; }public int Y { get; set; } }程序启动之后我们针对“http://localhost:5000/abc?bar123”这个URL发送了一个POST请求请求的主体内容为一个Point对象序列化成生成的JSON。如下所示的是请求报文和响应报文的内容可以看出Handle方法的foo和bar参数分别绑定的是路由参数“foo”和查询字符串“bar”的值参数host绑定的是请求的Host报头参数point是请求主体内容反序列化的结果参数environment则是由针对当前请求的IServiceProvider对象提供的服务S2012。POST http://localhost:5000/abc?bar123 HTTP/1.1 Content-Type: application/json Host: localhost:5000 Content-Length: 18{x:123, y:456}HTTP/1.1 200 OK Content-Type: application/json; charsetutf-8 Date: Sat, 06 Nov 2021 11:55:54 GMT Server: Kestrel Content-Length: 100{foo:abc,bar:123,host:localhost:5000,point:{x:123,y:456},environment:Production}[S2013]默认的参数绑定规则如果请求处理器方法的参数没有显式指定绑定数据的来源路由系统也能根据参数的类型尽可能地从当前HttpContext上下文中提取相应的内容予以绑定。针对如下这几个类型对应参数的绑定源是明确的。HttpContext绑定为当前HttpContext上下文。HttpRequest绑定为当前HttpContext上下文的Request属性。HttpResponse: 绑定为当前HttpContext上下文的Response属性。ClaimsPrincipal: 绑定为当前HttpContext上下文的User属性。CancellationToken: 绑定为当前HttpContext上下文的RequestAborted属性。上述的绑定规则体现在如下演示程序的调试断言中。这个演示实例还体现了另一个绑定规则那就是只要当前请求的IServiceProvider能够提供对应的服务对应参数“httpContextAccessor”上标注的FromSerrvicesAttribute特性不是必要的。但是倘若缺少对应的服务注册请求的主体内容会一般会作为默认的数据来源所以FromSerrvicesAttribute特性最好还是显式指定为好。对于我们演示的这个例子如果我们将前面针对AddHttpContextAccessor方法的调用移除对应参数的绑定自然会失败但是错误消息并不是我们希望看到的。using System.Diagnostics; using System.Security.Claims;var builder  WebApplication.CreateBuilder(); builder.Services.AddHttpContextAccessor(); var app  builder.Build(); app.MapGet(/, Handle); app.Run();static void Handle(HttpContext httpContext, HttpRequest request, HttpResponse response,ClaimsPrincipal user, CancellationToken cancellationToken, IHttpContextAccessor httpContextAccessor) {var currentContext  httpContextAccessor.HttpContext;Debug.Assert(ReferenceEquals(httpContext, currentContext));Debug.Assert(ReferenceEquals(request, currentContext.Request));Debug.Assert(ReferenceEquals(response, currentContext.Response));Debug.Assert(ReferenceEquals(user, currentContext.User));Debug.Assert(cancellationToken  currentContext.RequestAborted); }[S2014]针对TryParse方法的参数绑定如果我们在某个类型中定义了一个名为TryParse的静态方法将指定的字符串表达式转换成当前类型的实例路由系统在对该类型的参数进行绑定的时候会优先从路由参数和查询字符串中提取相应的内容并通过调用这个方法生成绑定的参数。var app  WebApplication.Create(); app.MapGet(/, (Point foobar)  foobar); app.Run();public class Point {public int X { get; set; }public int Y { get; set; }public Point(int x, int y){X  x;Y  y;}public static bool TryParse(string expression, out Point? point){var split  expression.Trim((, )).Split(,);if (split.Length  2  int.TryParse(split[0], out var x)  int.TryParse(split[1], out var y)){point  new Point(x, y);return true;}point  null;return false;} }上面的演示程序为自定义的Point类型定义了一个静态的TryParse方法使我们可以将一个以“(x,y)”形式定义的表达式转换成Point对象。注册的终结点处理器委托以该类型为参数指定的参数名称为“foobar”。我们在发送的请求中以查询字符串的形式提供对应的表达式“123456”从返回的内容可以看出参数得到了成功绑定。图3 TryParse方法针对参数绑定的影响[S2015]针对BindAsync方法的参数绑定如果某种类型的参数具有特殊的绑定方式我们还可以将具体的绑定实现在一个按照约定定义的BindAsync方法中。按照约定这个BindAsync应该定义成返回类型为ValueTaskT的静态方法它可以拥有一个类型为HttpContext的参数也可以额外提供一个ParameterInfo类型的参数这两个参数分别与当前HttpContext上下文和描述参数的ParameterInfo对象绑定。前面演示实例中为Point类型定义了一个TryParse方法可以替换成如下这个 BingAsync方法。public class Point {public int X { get; set; }public int Y { get; set; }public Point(int x, int y){X  x;Y  y;}public static ValueTaskPoint? BindAsync(HttpContext httpContext, ParameterInfo parameter){Point? point  null;var name  parameter.Name;var value  httpContext.GetRouteData().Values.TryGetValue(name!, out var v) ? v : httpContext.Request.Query[name!].SingleOrDefault();if (value is string expression){var split  expression.Trim((, ))?.Split(,);if (split?.Length  2  int.TryParse(split[0], out var x)   int.TryParse(split[1], out var y)){point  new Point(x, y);}}return new ValueTaskPoint?(point);} }[S2016]自定义路由约束我们可以使用预定义的IRouteConstraint实现类型完成一些常用的约束但是在一些对路由参数具有特定约束的应用场景中我们不得不创建自定义的约束类型。举个例子如果需要对资源提供针对多语言的支持最好的方式是在请求的URL中提供对应的Culture。为了确保包含在URL中的是一个合法有效的Culture最好为此定义相应的约束。下面将通过一个简单的实例来演示如何创建这样一个用于验证Culture的自定义路由约束。我们创建了一个提供基于不同语言资源的API。我们将资源文件作为文本资源进行存储如图4所示我们创建了两个资源文件 Resources.resx和Resources.zh.resx并定义了一个名为hello的文本资源条目。图4 存储文本资源的两个资源文件如下演示程序中注册了一个模板为“resources/{lang:culture}/{resourceName:required}”的终结点。路由参数“{resourceName}”表示资源条目的名称比如“hello”另一个路由参数“{lang}”表示指定的语言约束表达式名称culture对应的就是我们自定义的针对语言文化的约束类型CultureConstraint。因为这是一个自定义的路由约束我们通过调用IServiceCollection接口的ConfigureTOptions方法将此约束采用的表达式名称“culture”和CultureConstraint类型之间的映射关系添加到RouteOptions配置选项中。using App; using App.Properties; using System.Globalization;var builder  WebApplication.CreateBuilder(); var template  resources/{lang:culture}/{resourceName:required}; builder.Services.ConfigureRouteOptions(options  options.ConstraintMap.Add(culture, typeof(CultureConstraint))); var app  builder.Build(); app.MapGet(template, GetResource); app.Run();static IResult GetResource(string lang, string resourceName) {CultureInfo.CurrentUICulture  new CultureInfo(lang);var text  Resources.ResourceManager.GetString(resourceName);return string.IsNullOrEmpty(text)? Results.NotFound(): Results.Content(text); }该终结点的处理方法GetResource定义了两个参数我们知道它们会自动绑定为同名的路由参数。由于系统自动根据当前线程的UICulture来选择对应的资源文件我们对CultureInfo类型的CurrentUICulture静态属性进行了设置。如果从资源文件将对应的文本提取出来我们将创建一个ContentResult对象并返回。应用启动之后我们可以利用浏览器指定匹配的URL获取对应语言的文本。如图5所示如果指定一个不合法的语言如“xx”将会违反我们自定义的约束此时就会得到一个状态码为“404 Not Found”的响应。图5 采用相应的URL得到某个资源针对某种语言的内容我们来看看针对语言文化的路由约束CultureConstraint究竟做了什么。如下面的代码片段所示我们在Match方法中会试图获取作为语言文化内容的路由参数值如果存在这样的路由参数就可以利用它创建一个CultureInfo对象。如果这个CultureInfo对象的EnglishName属性名不以“Unknown Language”字符串作为前缀我们就认为指定的是合法的语言文件。public class CultureConstraint : IRouteConstraint {public bool Match(HttpContext? httpContext, IRouter? route, string routeKey,RouteValueDictionary values, RouteDirection routeDirection){try{if (values.TryGetValue(routeKey, out var value)  value is not null){return !new CultureInfo((string)value).EnglishName.StartsWith(Unknown Language);}return false;}catch{return false;}} }
http://wiki.neutronadmin.com/news/320916/

相关文章:

  • 网站的主要功能模块推广软文怎么写样板
  • 成都网站托管软文范例200字
  • 佛山建设网站公司吗红色网站建设的作用和意义
  • 六安市城乡建设网站中国中小企业河南网
  • 工商局网站年检怎么做我的世界找建筑网站
  • 第三方交易网站怎么做网站建设网站模版
  • 网站建设有哪些工作需需要筹备舆情报告撰写
  • 泰安做网站优化衡水哪儿专业做网站
  • 完整网站开发步骤英文网站提交
  • 网站服务器可以自己做吗株洲在线论坛
  • 访问网站 过程加强部门网页建设
  • 网站设计的素材设计图片大全
  • 网站底部浮动广告代码动漫网站网页设计
  • 莱芜做网站公司六安网站制作找哪家
  • dede企业网站模板下载seo标题优化分析范文
  • 一个好的网站怎样布局分类目录网站大全做seo
  • 镇江住房和城乡建设局网站安徽网站优化好不好
  • 做搜狗网站优化首页软医院网站怎么制作
  • 校园网站建设情况说明书长春专业网站建设推广费用
  • 自助网站建设方案做放单主持的网站
  • 电子商务网站建设专业主修课程网页界面设计的尺寸
  • 松江网站设计公司宣传册排版
  • 网站顶部图片代码湖南长沙网站建
  • 公司培训网站需要广播证吗做网站加入广告联盟
  • 网站cms是什么意思wordpress与joomla哪个好
  • 南宁企业网站建站模板完整个人网站html
  • 中国农村建设网站一级消防工程师考试科目和题型
  • 专业的东莞网站排名鞍山网站建设优化
  • 柯林建站程序建立网站要钱吗?
  • 张家口城乡建设局网站哈尔滨一恒建设