C# REST API,模型的子级应该是相同类型的,并且必须递归定义路由

我遇到了 .NET Core 的架构问题

我有一个名为 SContent 的控制器,带有此路由 ->

[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)} 的孩子

谢谢


翻过高山走不出你
浏览 163回答 1
1回答

青春有我

恐怕没有内置的路由可以满足您的需求。但是,编写自定义中间件很容易。简短的回答:写一个谓词,它将设置Context.Items["Ids"]和Context.Items["WantChildren"]将谓词传递给MapWhen()方法。编写一个中间件来处理逻辑以显示内容或根据Context.Items["Ids"]和获取它的孩子Context.Items["WantChildren"]。快速而肮脏的演示这是一个快速而肮脏的演示:app.MapWhen(&nbsp; &nbsp; context =>{&nbsp; &nbsp; &nbsp; &nbsp; var path=context.Request.Path.ToString().ToLower();&nbsp; &nbsp; &nbsp; &nbsp; if (path.EndsWith("/")) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; path = path.Substring(0, path.Length-1);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (!path.StartsWith("/api/content")) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; var ids = new List<int>();&nbsp; &nbsp; &nbsp; &nbsp; var wantChildren = false;&nbsp; &nbsp; &nbsp; &nbsp; var match= Regex.Match(path,"/(?<id>\\d+)(?<children>/children)?");&nbsp; &nbsp; &nbsp; &nbsp; while (match.Success) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var id = Convert.ToInt32(match.Groups["id"].Value);&nbsp; // todo: if throws an exception&nbsp; , ...&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wantChildren= !String.IsNullOrEmpty(match.Groups["children"].Value);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ids.Add(id);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; match = match.NextMatch();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; context.Items["Ids"] = ids;&nbsp; &nbsp; &nbsp; &nbsp; context.Items["WantChildren"] = wantChildren;&nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; },&nbsp; &nbsp; appBuilder => {&nbsp; &nbsp; &nbsp; &nbsp; appBuilder.Run(async context =>{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var ids = (List<int>)(context.Items["Ids"]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var wantChildren = (bool)(context.Items["WantChildren"]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // just a demo&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // the code below should be replaced with those that you do with id list and whether you should display children&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; foreach (var id in ids) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await context.Response.WriteAsync(id.ToString());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await context.Response.WriteAsync(",");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await context.Response.WriteAsync(wantChildren.ToString());&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; });这是一个有效的屏幕截图进一步重构为了更好地维护,您可以提取Ids和WantChildren到单个 Class ,例如ContentChildrenContext:public class&nbsp; ContentChildrenContext{&nbsp; &nbsp; public List<int> Ids {get;set;}&nbsp; &nbsp; public bool WantChildren{get;set;}}您还可以围绕中间件本身进行抽象,例如,创建一个返回 RequestDelegate 的工厂方法,该方法可以轻松用于app.Run():Func<Func<ContentChildrenContext,Task>,RequestDelegate> CreateContentChildrenMiddleware(Func<ContentChildrenContext,Task> action){&nbsp; &nbsp; return async content =>{&nbsp; &nbsp; &nbsp; &nbsp; var ccc= (ContentChildrenContext)(context.Items["ContentChildrenContext"]);&nbsp; &nbsp; &nbsp; &nbsp; await action(ccc);&nbsp; &nbsp; };}
打开App,查看更多内容
随时随地看视频慕课网APP