zoukankan      html  css  js  c++  java
  • .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);
        }
    }

    注意:

    1. 选择Controller类必须有一个参数的构造函数,构造函数传入为httpConfiguration类
    2. 重写SelectController方法,实现从ServiceContainer中获取ApiService实现类
    3. 重写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);
        }
    }
    • 注意:

      1. 此类不重写也可以实现ApiService类的执行,此类主要是处理在Action执行前一个些额外操作。
      2. 从中我们也可以看出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());
    }

    运行结果:

  • 相关阅读:
    To select the file to upload we can use the standard HTML input control of type
    Cascading Menu Script using Javascript Explained
    网站首页head区代码规范
    轻松掌握 Java 泛型
    JDK 5.0 中的泛型类型学习
    如何在firefox下获取下列框选中option的text
    是同步方法还是 synchronized 代码? 详解多线程同步规则
    javascript select option对象总结
    Select的动态取值(Text,value),添加,删除。兼容IE,FireFox
    javascript在ie和firefox下的一些差异
  • 原文地址:https://www.cnblogs.com/cqhaibin/p/6624189.html
Copyright © 2011-2022 走看看