zoukankan      html  css  js  c++  java
  • ABP之动态WebAPI

    HttpControllerDescriptor与HttpActionDescriptor

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

    Action的执行

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

    复制代码
            public override Type ReturnType
            {
                get
                {
                    return typeof(AjaxResponse);
                }
            }
    
            public override System.Threading.Tasks.Task<object> ExecuteAsync(HttpControllerContext controllerContext, System.Collections.Generic.IDictionary<string, object> arguments, System.Threading.CancellationToken cancellationToken)
            {
                return base
                    .ExecuteAsync(controllerContext, arguments, cancellationToken)
                    .ContinueWith(task =>
                    {
                        try
                        {
                            if (task.Result == null)
                            {
                                return new AjaxResponse();
                            }
    
                            if (task.Result is AjaxResponse)
                            {
                                return task.Result;
                            }
                            
                            return new AjaxResponse(task.Result);
                        }
                        catch (AggregateException ex)
                        {
                            ex.InnerException.ReThrow();
                            throw; // The previous line will throw, but we need this to makes compiler happy
                        }
                    });
            }
    复制代码
    View Code

    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返回。

            public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
            {
                if (request != null)
                {
                    var routeData = request.GetRouteData();
                    if (routeData != null)
                    {
                        string serviceNameWithAction;
                        if (routeData.Values.TryGetValue("serviceNameWithAction", out serviceNameWithAction) && DynamicApiServiceNameHelper.IsValidServiceNameWithAction(serviceNameWithAction))
                        {
                            var serviceName = DynamicApiServiceNameHelper.GetServiceNameInServiceNameWithAction(serviceNameWithAction);
                            var controllerInfo = DynamicApiControllerManager.FindOrNull(serviceName);
                            if (controllerInfo != null)
                            {
                                var controllerDescriptor = new DynamicHttpControllerDescriptor(_configuration, controllerInfo.ServiceName, controllerInfo.Type, controllerInfo.Filters);
                                controllerDescriptor.Properties["__AbpDynamicApiControllerInfo"] = controllerInfo;
                                return controllerDescriptor;
                            }
                        }
                    }
                }
    
                return base.SelectController(request);
            }
    View Code

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

    Abp的路由

    Abp定义了自己的路由格式

        public static class DynamicApiRouteConfig
        {
            /// <summary>
            /// Registers dynamic api controllers
            /// </summary>
            public static void Register()
            {
                //Dynamic Web APIs (with area name)
                GlobalConfiguration.Configuration.Routes.MapHttpRoute(
                    name: "AbpDynamicWebApi",
                    routeTemplate: "api/services/{*serviceNameWithAction}"
                    );
            }
        }
    View Code

    具体的解析就是:

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

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

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

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

    如SimpleTaskSystem:

     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     

    [DependsOn(typeof(AbpWebApiModule))] //We declare depended modules explicitly

    publicclassSimpleTaskSystemWebApiModule : AbpModule

    {

        publicoverridevoidInitialize()

        {

            //This code is used to register classes to dependency injection system for this assembly using conventions.

            IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());

     

            //Creating dynamic Web Api Controllers for application services.

            //Thus, 'web api layer' is created automatically by ABP.

     

            DynamicApiControllerBuilder

                .ForAll<IApplicationService>(Assembly.GetAssembly(typeof(SimpleTaskSystemApplicationModule)), "tasksystem")

                .Build();

        }

    }

      

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

    复制代码
            public static string GetConventionalServiceName(Type type)
            {
                var typeName = type.Name;
    
                if (typeName.EndsWith("ApplicationService"))
                {
                    typeName = typeName.Substring(0, typeName.Length - "ApplicationService".Length);
                }
                else if (typeName.EndsWith("AppService"))
                {
                    typeName = typeName.Substring(0, typeName.Length - "AppService".Length);
                }
                else if (typeName.EndsWith("Service"))
                {
                    typeName = typeName.Substring(0, typeName.Length - "Service".Length);
                }
    
                if (typeName.Length > 1 && typeName.StartsWith("I") && char.IsUpper(typeName, 1))
                {
                    typeName = typeName.Substring(1);
                }
    
                return typeName.ToCamelCase();
            }
    复制代码
    View Code

    Action:即为方法名

    HttpVerb

    Apb定义的四种Http访问方式

    复制代码
        [Flags]
        public enum HttpVerb
        {
            /// <summary>
            /// GET
            /// </summary>
            Get,
    
            /// <summary>
            /// POST
            /// </summary>
            Post,
    
            /// <summary>
            /// PUT
            /// </summary>
            Put,
    
            /// <summary>
            /// DELETE
            /// </summary>
            Delete,
        }
    复制代码
    View Code

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

        /// <summary>
        /// NOTE: This is not used (as all members are private)
        /// </summary>
        internal static class DynamicApiVerbHelper
        {
            private static HttpVerb GetConventionalVerbForMethodName(string methodName)
            {
                if (methodName.StartsWith("Get"))
                {
                    return HttpVerb.Get;
                }
    
                if (methodName.StartsWith("Update") || methodName.StartsWith("Put"))
                {
                    return HttpVerb.Put;
                }
    
                if (methodName.StartsWith("Delete") || methodName.StartsWith("Remove"))
                {
                    return HttpVerb.Delete;
                }
    
                if (methodName.StartsWith("Create") || methodName.StartsWith("Post"))
                {
                    return HttpVerb.Post;
                }
    
                return GetDefaultHttpVerb();
            }
    
            private static HttpVerb GetDefaultHttpVerb()
            {
                return HttpVerb.Post;
            }
        }
    View Code

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

  • 相关阅读:
    2018-2019-1 20175330 《信息安全系统设计基础》第四周学习总结
    2019-2020-1 20175330 《信息安全系统设计基础》第三周学习总结
    《程序设计与数据结构》实验一报告
    《程序设计与数据结构》第四周学习总结
    学号 20172326 《程序设计与数据结构》第三周学习总结
    《程序设计与数据结构》第二周学习总结
    《JAVA软件结构与数据结构》第一周学习总结
    《程序设计与数据结构》(上)课程总结
    2017-2018-2 《程序设计与数据结构》实验五报告
    《程序设计与数据结构》实验四报告
  • 原文地址:https://www.cnblogs.com/cb521413/p/8796916.html
Copyright © 2011-2022 走看看