WebApi实现原理

【实战】C# OAuth2.0授权码模式:从原理到WebAPI资源保护的完整实现 本文详细解析了C#实现OAuth2.0授权码模式的完整流程,从核心原理到WebAPI资源保护实战。通过代码示例演示了授权服务器搭建、令牌验证及客户端集成等关键步骤,并分享生产环境中的安全加固与性能优化技巧,帮助开发者构建安全的认证授权系统。 阅读详情

什么是 WebApi

WebApi 就是网络接口,运行流程如下。image

如何实现

1 最开始的执行方法

如果要执行一个方法,最简单的会通过如下几步执行。

[ApiController]
[Router("WeatherForecast")]
public class WeatherForecastController
{
    [Router("/Get")]
    public Random Get()
    {
        var rng = new Random();
        return rng;
    }

    public Random Post()
    {
        var rng = new Random();

        return rng;
    }

    public Random Put()
    {
        var rng = new Random();

        return rng;
    }

    public Random Delete()
    {
        var rng = new Random();

        return rng;
    }
}
// 1、获取反射类型
Type type = typeof(WeatherForecastController);

// 2、创建对象
object _obejct = Activator.CreateInstance(type);

// 3、获取方法
MethodInfo methodInfo = type.GetMethod("Get");
//MethodInfo methodInfo = type.GetMethod("Post");

// 4、执行方法
object result = methodInfo.Invoke(_obejct, new object[] { });

2 第一次改造,加入建造者模式加载所有方法到集合

但是上面代码只能是给定类,是写死的,我们需要动态把所有 Controller 中方法都获取到。

添加 Endpoint 类,里面存储方法的信息。

/// <summary>
/// 端点(就是Action的抽象)
/// </summary>
public class Endpoint
{
    /// <summary>
    /// 方法信息
    /// </summary>
    public MethodInfo MethodInfo { set; get; }

    /// <summary>
    /// 控制器
    /// </summary>
    public object Controller { set; get; }

    /// <summary>
    /// 方法参数类型
    /// </summary>
    public IList<ParameterInfo> ParameterInfos { set; get; }

    /// <summary>
    /// 方法返回值
    /// </summary>
    public object ReturnValue { set; get; }

    // 数据输出格式(json,xml)
    public string JataType { set; get; }

}

添加 Endpoint 数据源,用于存储 Endpoint 数据集合。

/// <summary>
/// Endpoint数据源(存储Endpoint数据集合)
/// </summary>
class EndpointDataSources
{
    /// <summary>
    /// Endpoint字典 key路径value端点信息
    /// </summary>
    private Dictionary<string, Endpoint> EndpointDic = new Dictionary<string, Endpoint>();

    public void AddEndpoint(string path, Endpoint endpoint)
    {
        EndpointDic.Add(path, endpoint);
    }
    /// <summary>
    /// 提供Endpoint
    /// </summary>
    /// <param name="endpointName"></param>
    /// <returns></returns>
    public Endpoint this[string MethodName]
    {
        get { return EndpointDic[MethodName]; }
    }
}

EndpointDataSourcesBuilder 用于构建 EndpointDataSources,其中 MapControllers 方法就是循环获取到所有 Controller 中的方法加入字典。

/// <summary>
/// 构建EndpointDataSources(建造者设计模式)
/// </summary>
class EndpointDataSourcesBuilder
{
    /// <summary>
    /// Endpoint集合
    /// </summary>
    private EndpointDataSources endpointDataSources = new EndpointDataSources();

    public void MapControllers()
    {
        Assembly assembly = Assembly.Load("WebApiCode");
        Type[] types = assembly.GetTypes();
        foreach (var type in types)
        {
            // 1、实现控制器过滤
            ApiController apiController = type.GetCustomAttribute<ApiController>();
            if (apiController != null)
            {
                // 1、获取控制器路径
                Router controllerRouter = type.GetCustomAttribute<Router>();

                // 2、创建对象
                object _obejct = Activator.CreateInstance(type);

                // 3、获取方法
                MethodInfo[] methodInfos = type.GetMethods();
                foreach (var methodInfo in methodInfos)
                {
                    // 特性过滤,路径映射
                    Router router = methodInfo.GetCustomAttribute<Router>();
                    if (router != null)
                    {
                        // 端点映射
                        Endpoint endpoint = new Endpoint
                        {
                            MethodInfo = methodInfo,
                            Controller = _obejct
                        };

                        // 获取控制器方法路径
                        string path = controllerRouter.Path + router.Path;
                        endpointDataSources.AddEndpoint(path, endpoint);
                    }
                }
            }
        }
    }

    public EndpointDataSources Build()
    {
        return endpointDataSources;
    }
}

相关特性。

/// <summary>
///  API控制器
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
class ApiController : Attribute 
{ }

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
class Router : Attribute
{
    /// <summary>
    /// 路径
    /// </summary>
    public string Path { get; }

    public Router(string path)
    {
        Path = path;
    }
}

经过以上改造,客户端就可以这样写了。

//1、创建EndpointDataSourcesBuilder对象并构建EndpointDataSources
EndpointDataSourcesBuilder builder = new();
builder.MapControllers();
EndpointDataSources endpointData = builder.Build();
//2、获取Endpoint
var endpoint = endpointData["WeatherForecast/Get"];
//3、获取方法
MethodInfo methodInfo = endpoint.MethodInfo;
//4、执行方法
methodInfo.Invoke(endpoint.Controller, new object[] { });

3 第二次改造,加入路由匹配

因为 WebApi 请求是通过路由找到执行的方法,所以我们需要加入路由。

添加模拟 Http 相关类。

/// <summary>
/// http上下文类(用于获取HttpRequest和HttpResponse)
/// </summary>
public class HttpContext
{
    public string RequestPath { set; get; }

    public HttpRequest Request { set; get; }
    public HttpResponse Response { set; get; }
}
public class HttpRequest { }
public class HttpResponse { }

添加路由路径匹配。

/// <summary>
/// Endpoint 路由:通过路径获取EndPoint
/// </summary>
class EndpointRoute
{
    public EndpointDataSources endpointDataSources { get; set; }

    /// <summary>
    /// 路由匹配
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public Endpoint Match(HttpContext httpContext)
    {
        // 路径判断
        return endpointDataSources[httpContext.RequestPath];
    }
}

客户端变成如下。

//1、创建EndpointDataSourcesBuilder对象并构建EndpointDataSources
EndpointDataSourcesBuilder builder = new();
builder.MapControllers();
EndpointDataSources endpointData = builder.Build();

//2、获取Endpoint
HttpContext httpContext = new()
{
    RequestPath = "WeatherForecast/Get"
};
EndpointRoute route = new()
{
    endpointDataSources = endpointData
};
var endpoint = route.Match(httpContext);

//3、获取方法
MethodInfo methodInfo = endpoint.MethodInfo;
//4、执行方法
methodInfo.Invoke(endpoint.Controller, new object[] { });

4 第三次改造,端点执行进行封装

添加端点处理类 EndpointHandler。

/// <summary>
/// 端点处理
/// </summary>
public class EndpointHandler
{
    /// <summary>
    /// 执行端点
    /// </summary>
    /// <param name="endpoint"></param>
    /// <param name="providedArgs">方法参数值</param>
    /// <returns></returns>
    public object HandlerEndpoint(Endpoint endpoint, object[] providedArgs)
    {
        // 1、获取方法
        MethodInfo methodInfo = endpoint.MethodInfo;
        // 2、执行
        return methodInfo.Invoke(endpoint.Controller, providedArgs);
    }
}

客户端修改。

//1、创建EndpointDataSourcesBuilder对象并构建EndpointDataSources
EndpointDataSourcesBuilder builder = new();
builder.MapControllers();
EndpointDataSources endpointData = builder.Build();

//2、获取Endpoint
HttpContext httpContext = new()
{
    RequestPath = "WeatherForecast/Get"
};
EndpointRoute route = new()
{
    endpointDataSources = endpointData
};
var endpoint = route.Match(httpContext);

//3、执行Endpoint
EndpointHandler endpointHandler = new();
endpointHandler.HandlerEndpoint(endpoint, new object[] { });

5 第四次改造,使用外观模式封装成中间件

既然以上 WebApi 的执行流程已经确定,那么我们可以使用外观模式将其封装成中间件调用。

添加终结点中间件 EndpointMiddleware,把过程封装进 Invoke 方法。

/// <summary>
/// 终结点中间件(外观模式)。
/// </summary>
class EndpointMiddleware
{
    private EndpointDataSources endpointDataSources;
    private EndpointRoute endpointRoute;
    private EndpointHandler endpointHandler;

    public EndpointMiddleware()
    {
        EndpointDataSourcesBuilder endpointDataSourcesBuilder = new EndpointDataSourcesBuilder();
        endpointDataSourcesBuilder.MapControllers();
        this.endpointDataSources = endpointDataSourcesBuilder.Build();
        this.endpointRoute = new EndpointRoute();
        this.endpointHandler = new EndpointHandler();
    }

    /// <summary>
    /// 执行请求
    /// </summary>
    /// <param name="httpContext"></param>
    public void Invoke(HttpContext httpContext)
    {
        // 获取Endpoint
        endpointRoute.endpointDataSources = endpointDataSources;
        Endpoint endpoint = endpointRoute.Match(httpContext);

        // 执行endpoint
        object result = endpointHandler.HandlerEndpoint(endpoint, new object[] { });
    }
}

客户端直接用中间件调用。

HttpContext httpContext = new()
{
    RequestPath = "WeatherForecast/Get"
};
EndpointMiddleware endpointMiddleware = new();
endpointMiddleware.Invoke(httpContext);

6 最终所添加的类如下所示

image

OnPropertyChanged()实现原理,WebApi+wpf 的配置 WPF+Prism+WebApi 阅读详情

相关推荐

.net Web Api使用详解(全部实例讲解,可直接运行看效果)

.net Web Api使用详解(全部实例讲解,可直接运行看效果)

WebApi路由机制详解——看完不会用你打我

随着前后端分离的大热,WebApi在项目中的作用也是越来越重要,由于公司的原因我之前一直没有机会参与前后端分离的项目,但WebApi还是要学的呀,因为这东西确实很有用,可单独部署、与前端和App交互都很方便,既然有良好的发展趋势,我们当然应该顺势而为——搞懂WebApi! 从MVC到WebApi,路由机制一直都在其中扮演着重要的角色。 它可以很简单:如果你只需要会用一些简单的路由,如/Home...

xiaouncle的博客 4万+

LC与RC滤波电路实战对比:从原理到选型指南

本文深入对比了LC与RC滤波电路的核心原理与实战应用。LC滤波利用电感与电容的无损能量搬运,适合高频、大电流电源滤波,效率高但需注意谐振风险;RC滤波通过电阻消耗能量实现滤波,结构简单、成本低,适用于低频信号处理或小电流供电场景。文章提供了从工作原理、性能维度到具体选型的完整指南,帮助工程师根据项目需求(如频率范围、负载电流、效率)做出精准选择。

weixin_29240711的博客 499

接口开发笔记-WebApi

记录了weiapi学习过程中的一些基本操作

weixin_63658665的博客 1万+

逆向实战:拼多多anti-content加密参数的全链路解析与动态对抗策略

本文深入解析了拼多多anti-content加密参数的全链路生成逻辑与动态对抗策略。通过逆向工程实战,详细拆解了包含设备指纹、用户行为采集和动态密钥生成在内的12个关键环节,并提供了可持续对抗的精准模拟方案和自动化更新机制,帮助开发者有效应对拼多多的反爬体系。

weixin_30687051的博客 158

Android HCE模拟NFC标签:实现跨设备NDEF数据共享

本文详细介绍了Android HCE技术如何模拟NFC标签实现跨设备NDEF数据共享。通过核心代码实现和标准AID配置,使手机能够被第三方NFC应用直接读取,支持文本、网址、Wi-Fi配置等多种数据类型,大幅提升设备间数据交换的便捷性和兼容性。

pytorch8learner的博客 247

ASP.NET Core WebAPI_Controller简述

ASP.NET Core WebAPI_Controller简述

Mudrock__的博客 732

Android 13 录音APK在后台无数据的处理

未获取到录音数据

chenchen4310的博客 1182

深入解析与优化 WebAPI 的底层机制

本文将深入解析 WebAPI 的底层机制,并通过实例提供一些优化策略,以帮助开发者更好地理解和使用 WebAPI 技术。

weixin_41989626的博客 1068

Intel MKL库常用模块的C语言实现

文章目录1. 随机数生成1.1 等概率的01分布 viRngUniform1.2 (复)高斯分布 vsRngGaussian2. 向量-向量运算2.1 向量数乘与加法 cblas_caxpby2.2 向量内积 cblas_cdotu_sub2.3 向量范数 cblas_scnrm23. 矩阵-向量运算3.1 矩阵存储方案3.2 矩阵-向量乘法 cblas_cgemv4. 矩阵-矩阵运算4.1 矩阵...

月半 月半的博客 4649

Redhawk-SC输入件配置中的5个常见错误及解决方法

本文针对Redhawk-SC功耗与可靠性签核工具,深入剖析了输入件配置中工艺文件错配、DEF文件路径、时序文件格式、电源网络模型及宏模型处理这5个最常见且棘手的错误。文章提供了资深工程师验证过的实战解决方案与检查清单,旨在帮助用户规避风险,提升配置效率与分析准确性,确保芯片签核流程的顺利进行。

earth的博客 233

C# Webapi中[ApiController]特性的功能,即使用

第一:背景: 之前对这个特性一知半解,了解的不够深入,在试用期的工作中,问到这个特性,需要深入了解 第二个:正文,作用及使用 //[ApiController] //启用下述 API 特定的固定行为: /* * •特性路由要求 不能通过由 Startup.Configure 中的 UseEndpoints、UseMvc 或 UseMvcWithDefaultRoute 定义的传统路由访问操作。即写[Route()] •自动 HTTP 400 响应 ...

xu2034029667的博客 1万+

SAP物料主数据中的销售视图。这是一个在销售与分销模块中至关重要的核心主数据,直接关系到从报价到交货的整个销售流程

SAP物料主数据的销售视图是销售流程的核心基础,它定义了物料如何被销售、定价、开票和交付。销售视图包含五个关键控制点:1)基本销售数据控制物料销售状态;2)销售组织数据决定销售渠道和产品分类;3)通用物料数据管理销售描述和税务分类;4)交货计划控制交付参数;5)开票计划管理定价规则。这些设置直接影响销售流程顺畅度、数据准确性、客户满意度、财务合规性和业务灵活性。建议将销售视图创建纳入新产品引入流程,并建立规范的维护机制,确保业务变化时及时更新配置。

金牌架构师 666

WebApi实现原理解析笔记

这是我看过WebApi实现代码后的一些总结,一方面加深自己的记忆,另外也希望能够帮助大家更深入的了解WebApi。 注:暂时没有好好的整理,可能有些晦涩难懂。 Webapi 控制器类必须实现IHttpController接口 首先调用HttpControllerRouteHandler通过请求上下文(RequestContext)创建创建HttpControllerHandler...

amjc93299的博客 588

零基础学写《扫雷》游戏(Qt扫雷源码)

扫雷游戏是在windows系统中自带的游戏,他的游戏玩法其实很简单,20世纪初期电脑上没有啥游戏可以玩,所以扫雷游戏也算是当时是最常火爆的一个电脑游戏。以下文章详细介绍扫雷游戏的实现。实现语言为C++。

啊渊的专栏 1万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

浏览器工作原理17 [#]Webapi:XMLHttpRequest是怎么实现的

首先我们介绍了回调函数和系统调用栈;接下来我们站在循环系统的视角,分析了 XMLHttpRequest 是怎么工作的;最后又说明了由于一些安全因素的限制,在使用 XMLHttpRequest 的过程中会遇到跨域问题和混合内容的问题。本篇文章跨度比较大,不是单纯地讲一个问题,而是将回调类型、循环系统、网络请求和安全问题“串联”起来了。

qq_44376306的博客 1054

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Http Base Auth原理及.net6 webapi实现Http Base Auth身份验证

本文介绍了BaseAuth基础认证的原理及在.NET6 WebAPI中的实现方法。BaseAuth是一种简单的HTTP身份验证机制,通过请求头携带用户名和密码的Base64编码进行验证。文章详细说明了服务端如何通过返回401状态码和WWW-Authenticate响应头来要求客户端进行认证,并提供了两种实现方式:一种是在Action中直接处理认证逻辑,另一种是通过创建ActionFilter过滤器实现。后者更符合MVC架构,便于代码复用。两种方式都包含了对Authorization请求头的解析、Base64

JXMaker 729

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

浏览器工作原理与实践--WebAPI:XMLHttpRequest是怎么实现的

好了,今天我们就讲到这里,下面我来总结下今天的内容。首先我们介绍了回调函数和系统调用栈;接下来我们站在循环系统的视角,分析了XMLHttpRequest是怎么工作的;最后又说明了由于一些安全因素的限制,在使用XMLHttpRequest的过程中会遇到跨域问题和混合内容的问题。本篇文章跨度比较大,不是单纯地讲一个问题,而是将回调类型、循环系统、网络请求和安全问题“串联”起来了。

echohuangshihuxue的博客 1848

动态WebAPI实现原理

https://blog.yuanpei.me/posts/116795088/ 转载于:https://www.cnblogs.com/baiqian/p/11493267.html

weixin_30621919的博客 1233

Modern-CPP-Programming:覆盖 C++11 到 C++23 的免费现代 C++ 课程,每个特性配最小代码示例

想写现代 C++,很容易卡在一个坎上:RAII、move 语义、智能指针、concepts,这些特性散落在各种博客和问答帖里,有的按 C++11 讲,有的按 C++20 讲,版本对不上。Modern-CPP-Programming 是一套免费的现代 C++ 课程,从 C++11 一路讲到 C++23/C++26,29 讲内容,每个特性都配最小代码示例。 ## 它到底解决了什么 没有它的时候,你

gitblog_01178的博客 1074

浏览器工作原理与实践--WebAPI:setTimeout是如何实现的

好了,今天我们就介绍到这里,下面我来总结下今天的内容。首先,为了支持定时器的实现,浏览器增加了延时队列。其次,由于消息队列排队和一些系统级别的限制,通过setTimeout设置的回调任务并非总是可以实时地被执行,这样就不能满足一些实时性要求较高的需求了。最后,在定时器中使用过程中,还存在一些陷阱,需要你多加注意。通过分析和讲解,你会发现函数setTimeout在时效性上面有很多先天的不足,所以对于一些时间精度要求比较高的需求,应该有针对性地采取一些其他的方案。

echohuangshihuxue的博客 1120

CleanArchitecture.WebApi项目结构详解:一文读懂洋葱架构的实现原理

CleanArchitecture.WebApi是一个基于ASP.NET Core 3.1构建的WebAPI项目,采用了业界流行的洋葱架构设计模式。这种架构通过严格的依赖规则和分层设计,实现了代码的高内聚低耦合,让项目更易于维护和扩展。本文将深入剖析该项目的结构设计,帮助开发者快速理解洋葱架构在实际项目中的落地方式。 ## 洋葱架构核心思想:依赖方向的艺术 🧅 洋葱架构的核心原则是**内层定

gitblog_01018的博客 1043

浏览器原理 16 # WebAPI:XMLHttpRequest是怎么实现的?

说明 【浏览器工作原理与实践】专栏学习笔记

学习前端这门手艺,栈底到栈顶依次是:浏览器架构、Web 网络、事件循环机制、JavaScript 核心、V8 的内存管理、浏览器的渲染流程、Web 安全、CSS、React、Vue、Node、构建工具链等 698

浏览器原理 15 # WebAPI:setTimeout 是如何实现的?

说明 【浏览器工作原理与实践】专栏学习笔记 用法 setTimeout 定时器,用来指定某个函数在多少毫秒之后执行。 function showName(){ console.log("凯小默") } var timerID = setTimeout(showName, 200); 浏览器怎么实现 setTimeout 渲染进程中所有运行在主线程上的任务都需要先添加到消息队列,然后事件循环系统再按照顺序执行消息队列中的任务。 典型的事件: 当接收到 HTML 文档数据,渲染引擎就会将“解析 DO

学习前端这门手艺,栈底到栈顶依次是:浏览器架构、Web 网络、事件循环机制、JavaScript 核心、V8 的内存管理、浏览器的渲染流程、Web 安全、CSS、React、Vue、Node、构建工具链等 814

浏览器工作原理与实践|16:WebApi setTimeout是怎么实现的

浏览器页面是由消息队列和事件循环系统来驱动的。 过setTimeout和XMLHttpRequest这两个 WebAPI 来介绍事件循环的应用。这两个 WebAPI 是两种不同类型的应用,比较典型,并且在JavaScript 中的使用频率非常高。 setTimeout它就是一个定时器,用来指定某个函数在多少毫秒之后执行。它会返回一个整数,表示定时器的编号,同时你还可以通过该编号来取消这个定时器。 function showName(){ console.log("极客时间") } var timerID

Three_ST的博客 299
上一篇: 模版方法模式
下一篇: Vue3入门
似水明俊德
博客等级 码龄8年 247粉丝 276原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值