zoukankan      html  css  js  c++  java
  • OWIN 自宿主模式WebApi项目,WebApi层作为单独类库供OWIN调用

    为什么我们需要OWIN

    过去,IIS作为.NET开发者来说是最常用的Web Server(没有之一),源于微软产品的紧耦合关系,我们不得不将Website、Web Application、Web API等部署在IIS上,事实上在2010年前并没有什么不妥,但随着近些年来Web的发展,特别是移动互联网飞速发展,IIS作为Web Server已经暴露出他的不足了。主要体现在两个方面,ASP.NET (System.Web)紧耦合IIS,IIS紧耦合OS,这就意味着,我们的Web Framework必须部署在微软的操作系统上,难以跨平台。
    ...
    OWIN是什么?在本文里面就不进行赘述,网上有很多介绍OWIN的信息以及优缺点的博文,这里可以给几个链接大家进行自行参考:
    ..
    下面我们重点介绍我在搭建OWIN自宿主平台的过程,对于我是学习的过程,对于想要接触他的大家来说,也是一种帮助。
    很多人搭建的OWIN+WebApi项目都是写在一个项目中的,我个人为了代码的隔离,将控制器层写在了另外一个项目中,这样有助于后期大型框架的形成。
    下面是搭建步骤:
    1、首先新建一个控制台应用程序和一个.NETFramework类库项目,控制台引用类库项目。
    项目结构如下图所示:

    OWIN.WebApi WebApi层

    OWIN.WebApi.Sv WebApi服务层,将要作为启动项!

    2、控制台项目使用NuGet引用需要的类库:
      OWIN
      Microsoft.Owin.Hosting
      Microsoft.Owin.Host.HttpListener
      Microsoct.AspNet.WebApi.Owin
      这里需要手动从WebApi项目里面找到System.Web.Web,System.Net.Http等Web类库进行引用。
      OWIN.WebApi.Srv层的引用情况(我这里有跨域配置,不需要的请忽略)
      
      在OWIN.WebApi层,我们需要同样引用Web的类库,我们才可以在WebApi项目控制器层继承自ApiController
        OWIN.WebApi层的引用情况(我这里有跨域配置,不需要的请忽略)
      
     3、因为WebApi层要分开类库项目写,所以这里比一般的OWIN要多一些配置,在我项目的OWIN.WebApi层的config目录下,我新建了一个Global.cs类,里面的代码是对控制器的解析,代码展示如下:
    复制代码
      1 using System.Web.Http;
      2 using System.Web.Http.Dispatcher;
      3 using System;
      4 using System.Collections.Concurrent;
      5 using System.Collections.Generic;
      6 using System.Linq;
      7 using System.Net;
      8 using System.Net.Http;
      9 using System.Web.Http.Controllers;
     10 
     11 namespace OWIN.WebApi.config
     12 {
     13     public class WebApiApplication : System.Web.HttpApplication
     14     {
     15         protected void Application_Start()
     16         {
     17             //ignore the xml return it`s setting let json return only 
     18             GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
     19             GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
     20 
     21             GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector),
     22             new WebApiControllerSelector(GlobalConfiguration.Configuration));
     23         }
     24     }
     25     /// <summary>
     26     /// the WebApiControllerSelector
     27     /// author:qixiao
     28     /// time:2017-1-31 19:24:32
     29     /// </summary>
     30     public class WebApiControllerSelector : DefaultHttpControllerSelector
     31     {
     32         private const string NamespaceRouteVariableName = "Namespace";
     33         private readonly HttpConfiguration _configuration;
     34         private readonly Lazy<ConcurrentDictionary<string, Type>> _apiControllerCache;
     35 
     36         public WebApiControllerSelector(HttpConfiguration configuration)
     37             : base(configuration)
     38         {
     39             _configuration = configuration;
     40             _apiControllerCache = new Lazy<ConcurrentDictionary<string, Type>>(
     41                 new Func<ConcurrentDictionary<string, Type>>(InitializeApiControllerCache));
     42         }
     43 
     44         private ConcurrentDictionary<string, Type> InitializeApiControllerCache()
     45         {
     46             IAssembliesResolver assembliesResolver = this._configuration.Services.GetAssembliesResolver();
     47             var types = this._configuration.Services.GetHttpControllerTypeResolver()
     48                 .GetControllerTypes(assembliesResolver).ToDictionary(t => t.FullName, t => t);
     49 
     50             return new ConcurrentDictionary<string, Type>(types);
     51         }
     52 
     53         public IEnumerable<string> GetControllerFullName(HttpRequestMessage request, string controllerName)
     54         {
     55             object namespaceName;
     56             var data = request.GetRouteData();
     57             IEnumerable<string> keys = _apiControllerCache.Value.ToDictionary<KeyValuePair<string, Type>, string, Type>(t => t.Key,
     58                     t => t.Value, StringComparer.CurrentCultureIgnoreCase).Keys.ToList();
     59 
     60             if (!data.Values.TryGetValue(NamespaceRouteVariableName, out namespaceName))
     61             {
     62                 return from k in keys
     63                        where k.EndsWith(string.Format(".{0}{1}", controllerName,
     64                        DefaultHttpControllerSelector.ControllerSuffix), StringComparison.CurrentCultureIgnoreCase)
     65                        select k;
     66             }
     67 
     68             string[] namespaces = (string[])namespaceName;
     69             return from n in namespaces
     70                    join k in keys on string.Format("{0}.{1}{2}", n, controllerName,
     71                    DefaultHttpControllerSelector.ControllerSuffix).ToLower() equals k.ToLower()
     72                    select k;
     73         }
     74 
     75         public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
     76         {
     77             Type type;
     78             if (request == null)
     79             {
     80                 throw new ArgumentNullException("request");
     81             }
     82             string controllerName = this.GetControllerName(request);
     83             if (string.IsNullOrEmpty(controllerName))
     84             {
     85                 throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
     86                     string.Format("No route providing a controller name was found to match request URI '{0}'", new object[] { request.RequestUri })));
     87             }
     88             IEnumerable<string> fullNames = GetControllerFullName(request, controllerName);
     89             if (fullNames.Count() == 0)
     90             {
     91                 throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
     92                         string.Format("No route providing a controller name was found to match request URI '{0}'", new object[] { request.RequestUri })));
     93             }
     94 
     95             if (this._apiControllerCache.Value.TryGetValue(fullNames.First(), out type))
     96             {
     97                 return new HttpControllerDescriptor(_configuration, controllerName, type);
     98             }
     99             throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
    100                 string.Format("No route providing a controller name was found to match request URI '{0}'", new object[] { request.RequestUri })));
    101         }
    102     }
    103 }
    复制代码

    4、在OWIN.WebApi.Srv层里面新建AppStart.cs类,并且写如下代码:

    复制代码
     1 using Microsoft.Owin.Hosting;
     2 using System;
     3 using Owin;
     4 using System.Web.Http;
     5 using System.Web.Http.Dispatcher;
     6 using QX_Frame.App.WebApi.Extends;
     7 using System.Web.Http.Cors;
     8 
     9 namespace OWIN.WebApi.Srv
    10 {
    11     class AppStart
    12     {
    13         static void Main(string[] args)
    14         {
    15             //string baseAddress = "http://localhost:3999/";    //localhost visit
    16             string baseAddress = "http://+:3999/";              //all internet environment visit  
    17             try
    18             {
    19                 WebApp.Start<StartUp>(url: baseAddress);
    20                 Console.WriteLine("BaseIpAddress is " + baseAddress);
    21                 Console.WriteLine("
    Application Started !");
    22             }
    23             catch (Exception ex)
    24             {
    25                 Console.WriteLine(ex.ToString());
    26             }
    27 
    28             for (;;)
    29             {
    30                 Console.ReadLine();
    31             }
    32         }
    33     }
    34     //the start up configuration
    35     class StartUp
    36     {
    37         public void Configuration(IAppBuilder appBuilder)
    38         {
    39             HttpConfiguration config = new HttpConfiguration();
    40 
    41             // Web API configuration and services
    42             //跨域配置 //need reference from nuget
    43             config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
    44             //enabing attribute routing
    45             config.MapHttpAttributeRoutes();
    46             // Web API Convention-based routing.
    47             config.Routes.MapHttpRoute(
    48                 name: "DefaultApi",
    49                 routeTemplate: "api/{controller}/{id}",
    50                 defaults: new { id = RouteParameter.Optional },
    51                 namespaces: new string[] { "OWIN.WebApi" }
    52             );
    53             config.Services.Replace(typeof(IHttpControllerSelector), new OWIN.WebApi.config.WebApiControllerSelector(config));
    54 
    55             //if config the global filter input there need not write the attributes
    56             //config.Filters.Add(new App.Web.Filters.ExceptionAttribute_DG());
    57 
    58             //new ClassRegisters(); //register ioc menbers
    59 
    60             appBuilder.UseWebApi(config);
    61         }
    62     }
    63 }
    复制代码

    里面对地址进行了配置,当然可以根据需求自行配置,显示信息也进行了适当的展示,需要说明的一点是,我这里进行了跨域的配置,没有配置或者是不需要的请注释掉并忽略!

    这里需要注意的是第53行,这里引用的是刚才的OWIN.WebApi层的Global.cs里面的类,请对照上述两段代码进行查找。

    这行是关键,有了这行,程序才可以扫描到WebApi层的Controller。好了,我们进行Controller的书写。
    5、在OWIN.WebApi层进行控制器类的编写,这里随意,我只在这里列出我的例子。
    复制代码
     1 using QX_Frame.App.WebApi;
     2 using QX_Frame.Helper_DG;
     3 using System.Web.Http;
     4 
     5 namespace OWIN.WebApi
     6 {
     7     /*
     8      * author:qixiao
     9      * time:2017-2-27 10:32:57
    10      **/
    11     public class Test1Controller:ApiController
    12     {
    13         //access http://localhost:3999/api/Test1  get method
    14         public IHttpActionResult GetTest()
    15         {
    16             //throw new Exception_DG("login id , pwd", "argumets can not be null", 11111, 2222);
    17             return Json(new { IsSuccess = true, Msg = "this is get method" });
    18         }
    19         //access http://localhost:3999/api/Test1  post method
    20         public IHttpActionResult PostTest(dynamic queryData)
    21         {
    22             return Json(new { IsSuccess = true, Msg = "this is post method",Data=queryData });
    23         }
    24         //access http://localhost:3999/api/Test1  put method
    25         public IHttpActionResult PutTest()
    26         {
    27             return Json(new { IsSuccess = true, Msg = "this is put method" });
    28         }
    29         //access http://localhost:3999/api/Test1  delete method
    30         public IHttpActionResult DeleteTest()
    31         {
    32             return Json(new { IsSuccess = true, Msg = "this is delete method" });
    33         }
    34     }
    35 }
    复制代码

    这里我是用的是RESTFull风格的WebApi控制器接口。

     然后我们可以进行试运行:

    服务启动成功!

    测试通过,我们可以尽情地探索后续开发步骤!

  • 相关阅读:
    November 13th 2016 Week 47th Sunday The 1st Day
    November 12th 2016 Week 46th Saturday
    November 11th 2016 Week 46th Friday
    November 10th 2016 Week 46th Thursday
    November 9th 2016 Week 46th Wednesday
    November 8th 2016 Week 46th Tuesday
    windows 7文件共享方法
    Win7无线网络共享设置方法
    常量指针和指针常量
    如何查找局域网的外网ip
  • 原文地址:https://www.cnblogs.com/xieyulin/p/7050623.html
Copyright © 2011-2022 走看看