C#restapi,模型的子级应该是相同的类型,并且路由必须递归定义
您好,我在.NET Core中遇到了架构问题 我有一个名为SContent的控制器,负责此路线->C#restapi,模型的子级应该是相同的类型,并且路由必须递归定义,c#,.net,asp.net-core,routing,C#,.net,Asp.net Core,Routing,您好,我在.NET Core中遇到了架构问题 我有一个名为SContent的控制器,负责此路线-> [Route("api/content")] 如果您输入此路由/api/content/您将获得Id为Guid.Empty的所有内容 如果您输入此路由/api/content/{id},您将从第一级内容中获得特定内容(在这种情况下,MasterId必须等于Guid.Empty) 如果您输入此路由/api/content/{id}/children,您将获得父{id}的所有子级 现在我要做的是
[Route("api/content")]
- 如果您输入此路由/api/content/您将获得Id为Guid.Empty的所有内容
- 如果您输入此路由/api/content/{id},您将从第一级内容中获得特定内容(在这种情况下,MasterId必须等于Guid.Empty)
- 如果您输入此路由/api/content/{id}/children,您将获得父{id}的所有子级
/api/content/{id}/children/{id2}
/api/content/{id}/children/{id2}/children
/api/content/{id}/children/{id2}/children/{id3}
等等等等等等
有可能做那样的事吗?
-子项属于同一类型的父项
-{id(N)}应始终是{id(N-1)}的子项
谢谢恐怕没有可以满足您需求的内置线路。然而,编写自定义中间件很容易 简短答复:
Context.Items[“id”]
和Context.Items[“WantChildren”]
MapWhen()
方法Context.Items[“id”]
和Context.Items[“WantChildren”]
处理显示内容或获取其子级的逻辑app.MapWhen(
context =>{
var path=context.Request.Path.ToString().ToLower();
if (path.EndsWith("/")) {
path = path.Substring(0, path.Length-1);
}
if (!path.StartsWith("/api/content")) {
return false;
}
var ids = new List<int>();
var wantChildren = false;
var match= Regex.Match(path,"/(?<id>\\d+)(?<children>/children)?");
while (match.Success) {
var id = Convert.ToInt32(match.Groups["id"].Value); // todo: if throws an exception , ...
wantChildren= !String.IsNullOrEmpty(match.Groups["children"].Value);
ids.Add(id);
match = match.NextMatch();
}
context.Items["Ids"] = ids;
context.Items["WantChildren"] = wantChildren;
return true;
},
appBuilder => {
appBuilder.Run(async context =>{
var ids = (List<int>)(context.Items["Ids"]);
var wantChildren = (bool)(context.Items["WantChildren"]);
// just a demo
// the code below should be replaced with those that you do with id list and whether you should display children
foreach (var id in ids) {
await context.Response.WriteAsync(id.ToString());
await context.Response.WriteAsync(",");
}
await context.Response.WriteAsync(wantChildren.ToString());
});
}
);
您还可以围绕中间件本身进行抽象,例如,创建一个工厂方法,该方法返回一个RequestDelegate,该方法可以轻松地与app.Run()
一起使用:
Func CreateContentChildrenMiddleware(Func操作){
返回异步内容=>{
var ccc=(ContentChildrenContext)(context.Items[“ContentChildrenContext”]);
等待行动(ccc);
};
}
最好的祝愿。对于每个不同的路由,如
/api/content/{id}/children/{id2}/children
,您必须创建一个包含参数id.id2的函数。如果要创建新路由/api/content/{id}/children/{id2}/children/{id3}
,则必须创建一个包含参数id、id2、id3的新函数。所以,我认为,您不能在这里实现递归。可能是
public class ContentChildrenContext{
public List<int> Ids {get;set;}
public bool WantChildren{get;set;}
}
Func<Func<ContentChildrenContext,Task>,RequestDelegate> CreateContentChildrenMiddleware(Func<ContentChildrenContext,Task> action){
return async content =>{
var ccc= (ContentChildrenContext)(context.Items["ContentChildrenContext"]);
await action(ccc);
};
}