• OWIN 自宿主模式WebApi项目,WebApi层作为单独类库供OWIN调用


    OWIN是Open Web Server Interface for .NET的首字母缩写,他的定义如下:

    OWIN在.NET Web Servers与Web Application之间定义了一套标准接口,OWIN的目标是用于解耦Web Server和Web Application。基于此标准,鼓励开发者开发简单、灵活的模块,从而推进.NET Web Development开源生态系统的发展。

    为什么我们需要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("\nApplication 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控制器接口。

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

    服务启动成功!

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

    该项目源代码GitHub地址:https://github.com/dong666/AHelloDotNet_DG (10-Code文件夹内)

    本文为七小站主原创作品,转载请注明出处:http://www.cnblogs.com/7tiny/ 且在文章页面明显位置给出原文链接。

    作者信息(详情):

    QiXiao_柒小(東)
    Software Development
    北京市海淀区 Haidian Area Beijing 100089,P.R.China
    郵箱Email : seventiny@foxmail.com  
    網址Http: http://www.7tiny.com
    QQ:1124999434 , WeChat: wd8622088 (尽量加微信)
    (专好结交天下英雄好汉,可聊天,可谈技,可约饭,可..嗯,原则是要有的~) 更多联系方式点我哦~


    Best Regard ~
  • 相关阅读:
    选择筛选
    添加标签2 jquery 和JS
    最全的常用正则表达式大全
    Javascript和ECMAScript二三事
    display:none和visibility: hidden二三事
    说人话
    渐进增强和优雅降级
    css的优先级以及!important的使用
    解决VS如何同时打开两个工程(xp和win7)
    jQuery验证控件jquery.validate.js使用说明+中文API
  • 原文地址:https://www.cnblogs.com/7tiny/p/6934619.html
Copyright © 2020-2023  润新知