当前位置:首页 > APP资源 > 正文内容

webapp导航横向滑动(div横向导航栏)

APP资源8个月前 (03-11)324

[S2010]解析路由模式 (源代码)

[S2011]利用多个中间件来构建终结点处理器(源代码)

[S2012]在参数上标注特性来决定绑定的数据源(源代码)

[S2013]默认的参数绑定规则(源代码)

[S2014]针对TryPar[Se方法的参数绑定(源代码)

[S2015]针对BindA[Sync方法的参数绑定(源代码)

[S2016]自定义路由约束(源代码)

[S2010]解析路由模式 (源代码)

[S2011]利用多个中间件来构建终结点处理器(源代码)

[S2012]在参数上标注特性来决定绑定的数据源(源代码)

[S2013]默认的参数绑定规则(源代码)

[S2014]针对TryPar[Se方法的参数绑定(源代码)

[S2015]针对BindA[Sync方法的参数绑定(源代码)

[S2016]自定义路由约束(源代码)

下面我们通过一个简单的实例演示如何利用RoutePatternFactory对象解析指定的路由模板,并生成对应的RoutePattern对象。我们定义了如下所示的Format方法将指定的RoutePattern对象格式化成一个字符串。

staticstringFormat( RoutePattern pattern)

{

varbuilder = newStringBuilder;

builder.AppendLine(

$"RawText: {pattern.RawText}" );

builder.AppendLine(

$"InboundPrecedence: {pattern.InboundPrecedence}" );

builder.AppendLine(

$"OutboundPrecedence: {pattern.OutboundPrecedence}" );

展开全文

varsegments = pattern.PathSegments;

builder.AppendLine( "Segments");

foreach( varsegment insegments)

{

foreach( varpart insegment.Parts)

{

builder.AppendLine( $"\t {ToString(part)}" );

}

}

builder.AppendLine( "Defaults");

foreach( var@ defaultinpattern.Defaults)

{

builder.AppendLine(

$"\t {@ default.Key} = {@ default.Value} " );

}

builder.AppendLine( "ParameterPolicies ");

foreach( varpolicy inpattern.ParameterPolicies)

{

builder.AppendLine(

$"\t {policy.Key}= { string.Join( ',',policy.Value.Select(it = it.Content))} " );

}

builder.AppendLine( "RequiredValues");

foreach( varrequired inpattern.RequiredValues)

{

builder.AppendLine(

$"\t {required.Key}= {required.Value}" );

}

returnbuilder.ToString;

staticstringToString( 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}" ,

_ = thrownewArgumentException( "Invalid RoutePatternPart.")

};

}

usingMicrosoft.AspNetCore.Routing.Patterns;

usingSystem.Text;

vartemplate = @"weather/{city:regex(^0\d{{2,3}}$)=010}/{days:int:range(1,4)=4}/{detailed?}";

varpattern = RoutePatternFactory.Parse(

pattern: template,

defaults: null,

parameterPolicies: null,

requiredValues: new{ city = "010", days = 4});

varapp = WebApplication.Create;

app.MapGet( "/", = Format(pattern));

app.Run;

如果利用浏览器访问启动后的应用程序,回到得到如图1所示结果,它结构化地展示了路由模式的原始文本、出入栈路由匹配权重、每个段的组成、路由参数的默认值和参数策略,以及生成URL必须提供的默认参数值。

图1 针对路由模式的解析

[S2011]利用多个中间件来构建终结点处理器

如果某个终结点针对请求处理的逻辑相对复杂,需要多个中间件协同完成,我们可以调用IEndpointRouteBuilder 对象的CreateApplicationBuilder方法创建一个新的IApplicationBuilder对象,并将这些中间件注册到这个该对象上,最后利用它这些中间件转换成RequestDelegate委托。

varapp = WebApplication.Create;

IEndpointRouteBuilder routeBuilder = app;

app.MapGet( "/foobar", routeBuilder

.CreateApplicationBuilder

.Use(FooMiddleware)

.Use(BarMiddleware)

.Use(BazMiddleware)

.Build);

app.Run;

staticasyncTask FooMiddleware(

HttpContext context,RequestDelegate next )

{

awaitcontext.Response.WriteAsync( "Foo=");

awaitnext(context);

};

staticasyncTask BarMiddleware(

HttpContext context, RequestDelegate next )

{

awaitcontext.Response.WriteAsync( "Bar=");

awaitnext(context);

};

staticTask BazMiddleware(

HttpContext context, RequestDelegate next )

= context.Response.WriteAsync( "Baz");

上面的演示程序注册了一个路径模板为“foobar”的路由,并注册了三个中间件来处理路由的请求。该演示程序启动之后,如果我们利用浏览器对路由地址“/foobar”发起请求,将会得到如图2所示的输出结果。呈现出来的字符串是通过注册的三个中间件(FooMiddleware、BarMiddleware和BazMiddleware)输出内容组合而成。

图2 输出结果

[S2012]在参数上标注特性来决定绑定的数据源

如下这个演示程序调用WebApplication对象的MapPost方法注册了一个采用“/{foo}”作为模板的终结点。作为终结点处理器的委托指向静态方法Handle,我们为这个方法定义了五个参数,分别标注了上述五个特性。我们将五个参数组合成一个匿名对象作为返回值。

usingMicrosoft.AspNetCore.Mvc;

varapp = WebApplication.Create;

app.MapPost( "/{foo}", Handle);

app.Run;

staticobjectHandle(

[FromRoute] stringfoo,

[FromQuery] intbar,

[FromHeader] stringhost,

[FromBody] Point point,

[FromServices] IHostEnvironment environment )

= new{ Foo = foo, Bar = bar, Host = host, Point = point,

Environment = environment.EnvironmentName };

publicclassPoint

{

publicintX { get; set; }

publicintY { get; set; }

}

程序启动之后,我们针对“http://localhost:5000/abc?bar=123”这个URL发送了一个POST请求,请求的主体内容为一个Point对象序列化成生成的JSON。如下所示的是请求报文和响应报文的内容,可以看出Handle方法的foo和bar参数分别绑定的是路由参数“foo”和查询字符串“bar”的值,参数host绑定的是请求的Host报头,参数point是请求主体内容反序列化的结果,参数environment则是由针对当前请求的IServiceProvider对象提供的服务(S2012)。

POST http: //localhost:5000/abc?bar=123 HTTP/1.1

Content-Type: application/json

Host: localhost: 5000

Content-Length: 18

{ "x": 123, "y": 456}

HTTP/ 1.1200OK

Content-Type: application/json; charset=utf -8

Date: Sat, 06Nov 202111: 55: 54GMT

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方法的调用移除,对应参数的绑定自然会失败,但是错误消息并不是我们希望看到的。

usingSystem.Diagnostics;

usingSystem.Security.Claims;

varbuilder = WebApplication.CreateBuilder;

builder.Services.AddHttpContextAccessor;

varapp = builder.Build;

app.MapGet( "/", Handle);

app.Run;

staticvoidHandle(

HttpContext httpContext,

HttpRequest request,

HttpResponse response,

ClaimsPrincipal user,

CancellationToken cancellationToken,

IHttpContextAccessor httpContextAccessor )

{

varcurrentContext = 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的静态方法将指定的字符串表达式转换成当前类型的实例,路由系统在对该类型的参数进行绑定的时候会优先从路由参数和查询字符串中提取相应的内容,并通过调用这个方法生成绑定的参数。

varapp = WebApplication.Create;

app.MapGet( "/", (Point foobar) = foobar);

app.Run;

publicclassPoint

{

publicintX { get; set; }

publicintY { get; set; }

publicPoint( intx, inty )

{

X = x;

Y = y;

}

publicstaticboolTryParse(

stringexpression, outPoint? point )

{

varsplit = expression.Trim( '(', ')').Split( ',');

if(split.Length == 2

int.TryParse(split[ 0], outvarx)

int.TryParse(split[ 1], outvary))

{

point = newPoint(x, y);

returntrue;

}

point = null;

returnfalse;

}

}

上面的演示程序为自定义的Point类型定义了一个静态的TryParse方法使我们可以将一个以“(x,y)”形式定义的表达式转换成Point对象。注册的终结点处理器委托以该类型为参数,指定的参数名称为“foobar”。我们在发送的请求中以查询字符串的形式提供对应的表达式“(123,456)”,从返回的内容可以看出参数得到了成功绑定。

图3 TryParse方法针对参数绑定的影响

[S2015]针对BindAsync方法的参数绑定

如果某种类型的参数具有特殊的绑定方式,我们还可以将具体的绑定实现在一个按照约定定义的BindAsync方法中。按照约定,这个BindAsync应该定义成返回类型为ValueTaskT的静态方法,它可以拥有一个类型为HttpContext的参数,也可以额外提供一个ParameterInfo类型的参数,这两个参数分别与当前HttpContext上下文和描述参数的ParameterInfo对象绑定。前面演示实例中为Point类型定义了一个TryParse方法可以替换成如下这个 BingAsync方法。

publicclassPoint

{

publicintX { get; set; }

publicintY { get; set; }

publicPoint( intx, inty )

{

X = x;

Y = y;

}

publicstaticValueTaskPoint? BindAsync(

HttpContext httpContext,

ParameterInfo parameter)

{

Point? point = null;

varname = parameter.Name;

varvalue= httpContext.GetRouteData

.Values.TryGetValue(name!, outvarv)

? v

: httpContext.Request.Query[name!].SingleOrDefault;

if( valueisstringexpression)

{

varsplit = expression.Trim( '(', ')')?.Split( ',');

if(split?.Length == 2

int.TryParse(split[ 0], outvarx)

int.TryParse(split[ 1], outvary))

{

point = newPoint(x, y);

}

}

returnnewValueTaskPoint?(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配置选项中。

usingApp;

usingApp.Properties;

usingSystem.Globalization;

varbuilder = WebApplication.CreateBuilder;

vartemplate = "resources/{lang:culture}/{resourceName:required}";

builder.Services.ConfigureRouteOptions(

options = options.ConstraintMap

.Add( "culture", typeof(CultureConstraint)));

varapp = builder.Build;

app.MapGet(template, GetResource);

app.Run;

staticIResult GetResource(

stringlang, stringresourceName )

{

CultureInfo.CurrentUICulture = newCultureInfo(lang);

vartext = Resources.ResourceManager.GetString(resourceName);

returnstring.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”字符串作为前缀,我们就认为指定的是合法的语言文件。

publicclassCultureConstraint: IRouteConstraint

{

publicboolMatch(

HttpContext? httpContext,

IRouter? route,

stringrouteKey,

RouteValueDictionary values,

RouteDirection routeDirection )

{

try

{

if(values.TryGetValue(routeKey, outvarvalue)

valueisnot null)

{

return! newCultureInfo(( string) value)

.EnglishName.StartsWith( "Unknown Language");

}

returnfalse;

webapp导航横向滑动(div横向导航栏)

}

catch

{

returnfalse;

}

}

}

扫描二维码推送至手机访问。

版权声明:本文由飞速云SEO网络优化推广发布,如需转载请注明出处。

本文链接:http://muyuzhen.com/post/95729.html

分享给朋友:

“webapp导航横向滑动(div横向导航栏)” 的相关文章

武汉app定制开发公司(武汉app定制开发公司怎么样)

武汉app定制开发公司(武汉app定制开发公司怎么样)

1华盛恒辉科技有限公司 上榜理由华盛恒辉是一家专注于高端软件定制开发服务和高端建设的服务机构,致力于为企业提供全面系统的开发制作方案在开发建设到运营推广领域拥有丰富经验,在教育,医疗,APP,管理,商城,人工。 三整体评估选择开发公司,一定要进行整体评估,一是评估自身,二是评估对方四跟进速度好的AP...

keepappcancel的简单介绍

keepappcancel的简单介绍

大部分的健身app提供健身训练计划教练课程分享打卡社区等功能,一些健身软件还提供记录体重变化和饮食习惯分析等功能下面为大家提供了几款方便实用的健身app,一起来看看吧!1KeepappKeep是一款目前非常受欢迎的移动健身指导健身应用,是。 根据查询百度经验得知,如果您不想继续使用keep的会员服务...

做企业规划的app(做企业规划的步骤有哪些)

做企业规划的app(做企业规划的步骤有哪些)

十大室内设计培训机构排行榜 现在室内设计的门槛越来越低,越来越考验设计师的能力,想要让自己的技术精益求精,想在预计的时间内学到真本领,则选择去正规学校进行专业的学习。因为专业的室内培训学校可以给学员进行更加正规的培训,比如杭州清风室内设计培训学院,专攻室内设计一门专业,老师都是股份责任制,培训班进行...

优秀的app首页设计样式(优秀的app首页设计样式有哪些)

优秀的app首页设计样式(优秀的app首页设计样式有哪些)

UI设计必要知道的APP页面 一起始页launchscreen说明程序启动时需要一定的反应时间,在这段时间内屏幕处于空置状态,为了让用户知道程序已经启动,现在只有一个加载过程,而且也是为了缓解用户的焦虑,所以用图片视频代替;回答目前互联发展势头越来越好,app应用也是日益增多,因此app的引导页设计...

快手app成人短视频(快手app成人短视频怎么下载)

快手app成人短视频(快手app成人短视频怎么下载)

1、首先,打开快手应用,然后点击右下角的“我的”按钮在个人主页上方会出现一个“青少年模式”的选项,点击进入在青少年模式页面上,你需要进行实名认证以证明你已经满足使用成年版的条件完成实名认证后,你可以点击页面上的。 2、快手成年版可以通过以下步骤打开1 打开快手App首先,在手机上找到并打开已经安装好...

杭州定制开发app案例(杭州定制开发app案例分析)

杭州定制开发app案例(杭州定制开发app案例分析)

2你想要开发的类型是否是开发公司的强项 再牛的APP开发公司不可能什么类型什么行业的APP都开发过,一般比较好的APP开发公司都有强项,也就是说擅长开发某一个或者哪几个行业的APP,并且有高质量的开发案例所以找APP开发;开发一个App的费用因多种因素而异,一般来说,定制开发的App价格会比较高根据...