当前位置: 代码网 > it编程>编程语言>Asp.net > Clear Code for Minimal API

Clear Code for Minimal API

2024年05月20日 Asp.net 我要评论
我在写MinimalAPI的时候,发现不能最清晰的看到每个API,原因就是:WebAPI中不断增长逻辑处理过程 于是我在想如何简化API至一行,在一点一点想办法中,发现了简化DotNET Minimal API的方式。特此记录下来这个思路给需要帮助的人。我的灵感来源于 C# 11 功能 - 接口中的 ...

我在写minimalapi的时候,发现不能最清晰的看到每个api,原因就是:webapi中不断增长逻辑处理过程

于是我在想如何简化api至一行,在一点一点想办法中,发现了简化dotnet minimal api的方式。特此记录下来这个思路给需要帮助的人。我的灵感来源于 c# 11 功能 - 接口中的静态虚拟成员,通过静态虚拟成员清晰整个api。


这是我思路的最终结果:在 program.cs 中我们能通过一行代码,清晰的看到代码情况。
而无需指定平常不是很关心的处理过程和请求方式。

app.mapgroup("connect", o =>
{
    o.mapmethods<authorize>("authorize");
    o.mapmethods<authorize.callback>("authorize/callback");
    o.mapmethods<token>("token");
    o.mapmethods<userinfo>("userinfo").requireauthorization(new authorizeattribute()
    {
        authenticationschemes = openiddictvalidationaspnetcoredefaults.authenticationscheme
    });
    o.mapmethods<endsession>("endsession");
});
app.mapgroup("account", o =>
{
    o.mapmethods<login>("login");
    o.mapmethods<externallogin>("externallogin");
    o.mapmethods<externallogin.callback>("externallogin/callback");
    o.mapmethods<confirmationlogin>("confirmationlogin");
    o.mapmethods<forgotpassword>("forgotpassword");
    o.mapmethods<resetpassword>("resetpassword");
});

我们只需要简单的三步就可以做到这个事情,并且可以不用反射和其他的复杂过程。
第一步,我们需要创建(附带静态抽象函数的接口)iendpointbase。

public interface iendpointbase
{
    public static abstract ienumerable<string> httpmethods();
    public static abstract delegate handler();
}

第二步,需要实现iendpointbase。

public class login : iendpointbase
{
    public record accountloginrequest
    {
        [jsonpropertyname("u"), required]
        public string username { get; set; } = default!;

        [jsonpropertyname("p"), required]
        public string password { get; set; } = default!;

        [jsonpropertyname("r"), required]
        public string returnurl { get; set; } = default!;

        [fromquery]
        public bool usecookies { get; set; }
    }
    public static delegate handler()
    {
        var callback = async ([frombody] accountloginrequest request, [fromservices] signinmanager signinmanager) =>
        {
            // todo: returnurl validate is success

            var result = await signinmanager.passwordsigninasync(request.username, request.password, request.usecookies, lockoutonfailure: true);
            return results.text(result.tostring());
        };
        return callback;
    }

    public static ienumerable<string> httpmethods() => [httpmethods.post];
}

第三步:处理静态iendpointbase,此时我们已经完成了这件事情。

public static routehandlerbuilder mapmethods<t>(this iendpointroutebuilder app, [stringsyntax("route")] string pattern) where t : iendpointbase
{
    return app.mapmethods(pattern, t.httpmethods(), t.handler());
}

单纯的使用扩展好的 mapmethods 已经足够清晰了。


但如果有对api进行分组的要求,使用原生的还是不会清晰,原因是:

  1. 要对 mapgroup 的值赋予变量名,比如说 var accountgroup = app.mapgroup("account"),每个组都要想个名字。accountgroup

  2. 不能清楚自己的边界,比如说 写代码时,有可能出现插队的情况,本来 accountgroup下面都是属于它的端点,结果不小心插进来一个别的。

于是简单的对mapgroup进行了扩展,最终结果在本文最上面。

public static void mapgroup(this iendpointroutebuilder endpoints, [stringsyntax("route")] string prefix, action<iendpointroutebuilder> action)
{
    var group = endpoints.mapgroup(prefix);
    action(group);
}

总结:通过这种方式,代码结构已经清晰多了。若是有议,可以在评论区联系我。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com