HttpControllerDescriptor与HttpActionDescriptor

HttpControllerDescriptor封装了某个HttpController类型的元数据,我们可以将它视为某个HttpController类型的描述对象。HttpActionDescriptor也类似。上一篇中说到Abp将ApiControler与Action信息分别封装于DynamicApiControllerInfo,DynamicApiActionInfo。Abp种HttpControllerDescriptor与HttpActionDescriptor有新的实现DynamicHttpControllerDescriptor,DyanamicHttpActionDescriptor。

Action的执行

Action方法的执行最终实现在HttpActionDescriptor的ExecuteAsync方法中。DyanamicHttpActionDescriptor也重写了ExecuteAsync,并且将Action的返回值类型定义为AjaxResponse。

  1. public override Type ReturnType
  2. {
  3. get
  4. {
  5. return typeof(AjaxResponse);
  6. }
  7. }
  8.  
  9. public override System.Threading.Tasks.Task<object> ExecuteAsync(HttpControllerContext controllerContext, System.Collections.Generic.IDictionary<string, object> arguments, System.Threading.CancellationToken cancellationToken)
  10. {
  11. return base
  12. .ExecuteAsync(controllerContext, arguments, cancellationToken)
  13. .ContinueWith(task =>
  14. {
  15. try
  16. {
  17. if (task.Result == null)
  18. {
  19. return new AjaxResponse();
  20. }
  21.  
  22. if (task.Result is AjaxResponse)
  23. {
  24. return task.Result;
  25. }
  26.  
  27. return new AjaxResponse(task.Result);
  28. }
  29. catch (AggregateException ex)
  30. {
  31. ex.InnerException.ReThrow();
  32. throw; // The previous line will throw, but we need this to makes compiler happy
  33. }
  34. });
  35. }

IHttpControllerSelector与IHttpActionSelector

在上一篇的开头提到了动态的WebApi的核心之一就是对原有的WebApi服务进行了替换。其中就包括IHttpControllerSelector与IHttpActionSelector,这两个接口的主要功能就是对url进行解析生成相应的HttpControllerDescriptor与HttpControllerDescriptor,并传给WebApi系统,再由WebApi系统去执行Action。

在上一篇中说到Abp将ApiController作DynamicApiControllerInfo缓存于DynamicApiControllerManager中,在DynamicApiControllerManager中有一DynamicApiControllers的静态IDictionary属性。

  1. private static readonly IDictionary<string, DynamicApiControllerInfo> DynamicApiControllers;

  

在Abp系统的AbpHttpControllerSelector的中,根据url的解析出相应的服务名在DynamicApiControllerManager查找出DynamicApiControllerInfo.再生成DynamicHttpControllerDescriptor返回。

  1. public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
  2. {
  3. if (request != null)
  4. {
  5. var routeData = request.GetRouteData();
  6. if (routeData != null)
  7. {
  8. string serviceNameWithAction;
  9. if (routeData.Values.TryGetValue("serviceNameWithAction", out serviceNameWithAction) && DynamicApiServiceNameHelper.IsValidServiceNameWithAction(serviceNameWithAction))
  10. {
  11. var serviceName = DynamicApiServiceNameHelper.GetServiceNameInServiceNameWithAction(serviceNameWithAction);
  12. var controllerInfo = DynamicApiControllerManager.FindOrNull(serviceName);
  13. if (controllerInfo != null)
  14. {
  15. var controllerDescriptor = new DynamicHttpControllerDescriptor(_configuration, controllerInfo.ServiceName, controllerInfo.Type, controllerInfo.Filters);
  16. controllerDescriptor.Properties["__AbpDynamicApiControllerInfo"] = controllerInfo;
  17. return controllerDescriptor;
  18. }
  19. }
  20. }
  21. }
  22.  
  23. return base.SelectController(request);
  24. }

DynamicApiControllerInfo中有IDictionary<string, DynamicApiActionInfo> Actions字典所以获取Action也就十分方便。

Abp的路由

Abp定义了自己的路由格式

  1. public static class DynamicApiRouteConfig
  2. {
  3. /// <summary>
  4. /// Registers dynamic api controllers
  5. /// </summary>
  6. public static void Register()
  7. {
  8. //Dynamic Web APIs (with area name)
  9. GlobalConfiguration.Configuration.Routes.MapHttpRoute(
  10. name: "AbpDynamicWebApi",
  11. routeTemplate: "api/services/{*serviceNameWithAction}"
  12. );
  13. }
  14. }

具体的解析就是:

Api/services/{ServicePrefix}/{ServiceName}/{Action}

在SimpleTaskSystem中一访问所有Tasks的url为

http://localhost:6247/api/services/tasksystem/task/GetTasks

ServicePrefix:服务前缀,由开发者自己定义

如SimpleTaskSystem:

  1. [DependsOn(typeof(AbpWebApiModule))] //We declare depended modules explicitly
  2. public class SimpleTaskSystemWebApiModule : AbpModule
  3. {
  4. public override void Initialize()
  5. {
  6. //This code is used to register classes to dependency injection system for this assembly using conventions.
  7. IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
  8.  
  9. //Creating dynamic Web Api Controllers for application services.
  10. //Thus, 'web api layer' is created automatically by ABP.
  11.  
  12. DynamicApiControllerBuilder
  13. .ForAll<IApplicationService>(Assembly.GetAssembly(typeof (SimpleTaskSystemApplicationModule)), "tasksystem")
  14. .Build();
  15. }
  16. }

  

ServiceName:服务名,由服务接口名解析而成。具体规则在BatchApiControllerBuilder. GetConventionalServiceName中

  1. public static string GetConventionalServiceName(Type type)
  2. {
  3. var typeName = type.Name;
  4.  
  5. if (typeName.EndsWith("ApplicationService"))
  6. {
  7. typeName = typeName.Substring(, typeName.Length - "ApplicationService".Length);
  8. }
  9. else if (typeName.EndsWith("AppService"))
  10. {
  11. typeName = typeName.Substring(, typeName.Length - "AppService".Length);
  12. }
  13. else if (typeName.EndsWith("Service"))
  14. {
  15. typeName = typeName.Substring(, typeName.Length - "Service".Length);
  16. }
  17.  
  18. if (typeName.Length > && typeName.StartsWith("I") && char.IsUpper(typeName, ))
  19. {
  20. typeName = typeName.Substring();
  21. }
  22.  
  23. return typeName.ToCamelCase();
  24. }

Action:即为方法名

HttpVerb

Apb定义的四种Http访问方式

  1. [Flags]
  2. public enum HttpVerb
  3. {
  4. /// <summary>
  5. /// GET
  6. /// </summary>
  7. Get,
  8.  
  9. /// <summary>
  10. /// POST
  11. /// </summary>
  12. Post,
  13.  
  14. /// <summary>
  15. /// PUT
  16. /// </summary>
  17. Put,
  18.  
  19. /// <summary>
  20. /// DELETE
  21. /// </summary>
  22. Delete,
  23. }

原本作者是定义了HttpVerb的处理方式,即对是通过方法名进行的分析。

  1. /// <summary>
  2. /// NOTE: This is not used (as all members are private)
  3. /// </summary>
  4. internal static class DynamicApiVerbHelper
  5. {
  6. private static HttpVerb GetConventionalVerbForMethodName(string methodName)
  7. {
  8. if (methodName.StartsWith("Get"))
  9. {
  10. return HttpVerb.Get;
  11. }
  12.  
  13. if (methodName.StartsWith("Update") || methodName.StartsWith("Put"))
  14. {
  15. return HttpVerb.Put;
  16. }
  17.  
  18. if (methodName.StartsWith("Delete") || methodName.StartsWith("Remove"))
  19. {
  20. return HttpVerb.Delete;
  21. }
  22.  
  23. if (methodName.StartsWith("Create") || methodName.StartsWith("Post"))
  24. {
  25. return HttpVerb.Post;
  26. }
  27.  
  28. return GetDefaultHttpVerb();
  29. }
  30.  
  31. private static HttpVerb GetDefaultHttpVerb()
  32. {
  33. return HttpVerb.Post;
  34. }
  35. }

但作者好像并不打算这么做,在源代码中我也没有找到别的处理方式。

ABP之动态WebAPI(二)的更多相关文章

  1. ABP源码分析三十五:ABP中动态WebAPI原理解析

    动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类就可以对外提供WebAPI的功能, ...

  2. ABP之动态WebAPI(一)

    ABP的动态WebApi实现了直接对服务层的调用(其实病没有跨过ApiController,只是将ApiController公共化,对于这一点的处理类似于MVC,对服务端的 调用没有跨过HttpHan ...

  3. ABP中动态WebAPI原理解析

    ABP中动态WebAPI原理解析 动态WebAPI应该算是ABP中最Magic的功能之一了吧.开发人员无须定义继承自ApiController的类,只须重用Application Service中的类 ...

  4. ABP之动态WebAPI

    ABP之动态WebAPI ABP的动态WebApi实现了直接对服务层的调用(其实病没有跨过ApiController,只是将ApiController公共化,对于这一点的处理类似于MVC,对服务端的 ...

  5. 动态WebApi

    动态WebApi实现了直接对Service的调用,其实没有跨过ApiController,只是我们自己创建出ApiController 实现主要分以下几步 一 对默认WebApi服务的替换 ApiGl ...

  6. ABP项目中使用Swagger生成动态WebAPI

    本文是根据角落的白板报的<使用ABP实现SwaggerUI,生成动态webapi>一文的学习总结,感谢原文作者角落的白板报. 1 安装Swashbuckle.core 1.1 选择WebA ...

  7. 最新版ABP 动态WebAPI 日期转json带T的解决方案| ABP DateTIme Json format

    ABP动态webapi返回的json数据中,日期时间带T还有毫秒数的问题,在以往的版本中可以使用下面方法解决: 在XXXAbpWebApiModule中加上下面的代码: 很老的很老的版本有效: pub ...

  8. ASP.NET Core 奇淫技巧之动态WebApi

    一.前言 接触到动态WebApi(Dynamic Web API)这个词的已有几年,是从ABP框架里面接触到的,当时便对ABP的这个技术很好奇,后面分析了一波,也尝试过从ABP剥离一个出来作为独立组件 ...

  9. [ABP框架]动态web Api的拦截用法。

    先进行配置 首先这种需求,一般发生在APP端,我们给APP,不会给所有项目系统的接口给他们用.我们系统有200个接口,但是APP的需求只会用20个.那么这个需求也就应运而生了. 以上为API文件夹中为 ...

随机推荐

  1. Session for SSRS Report of Microsoft Dynamics AX

    Session for SSRS Report of Microsoft Dynamics AX 版权声明:本文为博主原创文章,未经博主允许不得转载. Contract •A data contrac ...

  2. Distribution2:Distribution Writer

    Distribution Writer 调用Statement Delivery 存储过程,将Publication的改变同步到Subscriber中.查看Publication Properties ...

  3. SEO的Content里面的内容被转义的解决方法

    看图,不说话 转义的根源 收工 可能不全面,不过确实解决了这个问题,有更好的方法可以提一下,逆天感激不尽

  4. Sql Server系列:嵌套查询

    嵌套查询是指一个查询语句嵌套在另一个查询语句内部的查询.嵌套查询也就子查询,在SELECT子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或多个表.子查询中可以使用比较运 ...

  5. EF Power Tools参数不正确的解决方法

    在Visual Studio 2010安装了EF Power Tools Beta 3之后,希望根据本地现有数据库模型来生成基于Entity Framework Code First的代码时,经常出现 ...

  6. WPF DatePicker只显示年和月 修改:可以只显示年

    最近的项目,查询时只需要年和月,不需要日,因此需要对原有的DatePicker进行修改,查询了网上的内容,最终从一篇帖子里看到了添加附加属性的方法,地址是http://stackoverflow.co ...

  7. 深入理解CSS Media媒体查询

    × 目录 [1]媒介类型 [2]媒体属性 [3]语法[4]方法 前面的话 一说到响应式设计,肯定离不开媒体查询media.一般认为媒体查询是CSS3的新增内容,实际上CSS2已经存在了,CSS3新增了 ...

  8. 统计Go, Go, Go

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢!   结束了概率论,我们数据之旅的下一站是统计.这一篇,是统计的一个小介绍.   统 ...

  9. Easyui datagrid加载本地Json数据,CGI数据

    网上示例(记得引用Jquery): [html] view plaincopy var jsonstr = '{"total":1,"rows":[{" ...

  10. 【记录】ASP.NET MVC AuthorizeAttribute OnAuthorization 验证跳转

    重写 AuthorizeAttribute 的 OnAuthorization 方法: using System.Web.Mvc; namespace Demo.Web.Common { public ...