.Net WebApi 初探
实现服务层与api层共用,也就表明Service层就是api层。
-
关键类和接口
- System.Web.Http.Dispatcher.DefaultHttpControllerSelector
webpai选择控制器的默认实现,可以重写SelectController方法
- System.Web.Http.Controllers.ApiControllerActionSelector
webapi选择指定控制器下的action的默认实现,可以重写SelectAction方法。
- System.Web.Http.ApiController
api控制器的基类,继承于此的类都可以成为Api控制器
-
类和接口关系图 api自定义扩展实现
api注册流程
如果实现Servie层的Controller。
- 所有服务类都需要继承于ApiController类,让服务类拥有控制器的特性 ApiServier类代码(继承ApiController此可,设置服务基类用于后期扩展):
public class ApiService:System.Web.Http.ApiController { }
TestServer类代码:
public class TestService:ApiService { public string Get() { return "Get-Test"; } }
实现服务类,且具有ApiController的能力
- 实现ServiceContainer类,实现服务类的缓存,并用于Controller的选择类,获取服务类代码如下:
private void Init() { var assembly = System.Reflection.Assembly.GetExecutingAssembly(); var ls = assembly.GetTypes().Where(x => typeof(Services.ApiService).IsAssignableFrom(x)); foreach(var item in ls) { _apis.Add(item.FullName, item); } }
- 重写api选择controller类代码:
public class CustomSelectController:System.Web.Http.Dispatcher.DefaultHttpControllerSelector { public CustomSelectController(System.Web.Http.HttpConfiguration config) : base(config) { } public override HttpControllerDescriptor SelectController(HttpRequestMessage request) { var routeData = request.GetRouteData().Values; foreach( var route in routeData) { if(route.Key == "controller") { //找controller var controllerType = ServicesContainer.CreateInstance().Apis .Where(x => x.Key.ToLower().IndexOf(route.Value.ToString() + "service") > 0).FirstOrDefault(); if (controllerType.Value!=null) { return new DyControllerDescriptor(request.GetConfiguration(), controllerType.Value); } } } return base.SelectController(request); } }
注意:
- 选择Controller类必须有一个参数的构造函数,构造函数传入为httpConfiguration类
- 重写SelectController方法,实现从ServiceContainer中获取ApiService实现类
- 重写ActionSelector类
public class CustomActionActivator:System.Web.Http.Controllers.ApiControllerActionSelector { public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext) { if (!(controllerContext.ControllerDescriptor is DyControllerDescriptor)) { return base.SelectAction(controllerContext); } var realType = controllerContext.ControllerDescriptor as DyControllerDescriptor; Type[] types = new Type[0]; System.Reflection.MethodInfo methodInfo = realType.ControllerInfo.GetMethod("Get", types); return new DyActionDescriptor(controllerContext.Configuration, controllerContext.ControllerDescriptor, methodInfo); } }
-
注意:
- 此类不重写也可以实现ApiService类的执行,此类主要是处理在Action执行前一个些额外操作。
- 从中我们也可以看出Action的执行也是需要MethodInfo这个类的实例。
-
Global.cs中注入Api路由时,必须在Mvc注入路由之前
protected void Application_Start() { common.ServicesContainer.CreateInstance(); AreaRegistration.RegisterAllAreas(); //必须放在RouteConfig.RegisterRoutes前面 GlobalConfiguration.Configure((config) => { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); }); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); GlobalConfiguration.Configuration.Services.Replace(typeof(System.Web.Http.Dispatcher.IHttpControllerSelector), new common.CustomSelectController(GlobalConfiguration.Configuration)); GlobalConfiguration.Configuration.Services.Replace(typeof(System.Web.Http.Controllers.IHttpActionSelector), new common.CustomActionActivator()); }
运行结果:
1. 随笔为作者自己经验以及学习的总结;
2. 如本文对您有帮助请移步右下角,推荐本文,先谢谢各位看官,因为您的支持是我最大动力;
3. 欢迎大家转载本文;
2. 如本文对您有帮助请移步右下角,推荐本文,先谢谢各位看官,因为您的支持是我最大动力;
3. 欢迎大家转载本文;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库