为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
翻过高山走不出你 2021-11-07 19:44:01
我遇到了 .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)} 的孩子谢谢
查看完整描述

1 回答

?
青春有我

TA贡献1784条经验 获得超8个赞

恐怕没有内置的路由可以满足您的需求。但是,编写自定义中间件很容易。

简短的回答:

  1. 写一个谓词,它将设置Context.Items["Ids"]Context.Items["WantChildren"]

  2. 将谓词传递给MapWhen()方法。

  3. 编写一个中间件来处理逻辑以显示内容或根据Context.Items["Ids"]和获取它的孩子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());

        });

    }

);

这是一个有效的屏幕截图

//img1.sycdn.imooc.com//6187bc2f0001b39206780354.jpg

进一步重构

为了更好地维护,您可以提取Ids和WantChildren到单个 Class ,例如ContentChildrenContext:


public class  ContentChildrenContext{

    public List<int> Ids {get;set;}

    public bool WantChildren{get;set;}

}

您还可以围绕中间件本身进行抽象,例如,创建一个返回 RequestDelegate 的工厂方法,该方法可以轻松用于app.Run():


Func<Func<ContentChildrenContext,Task>,RequestDelegate> CreateContentChildrenMiddleware(Func<ContentChildrenContext,Task> action){

    return async content =>{

        var ccc= (ContentChildrenContext)(context.Items["ContentChildrenContext"]);

        await action(ccc);

    };

}


查看完整回答
反对 回复 2021-11-07
  • 1 回答
  • 0 关注
  • 162 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信