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. )
  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控制器接口。

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

服务启动成功!

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

OWIN 自宿主模式WebApi项目,WebApi层作为单独类库供OWIN调用的更多相关文章

  1. webapi从入门到放弃(一)OWIN 自寄宿模式

     1.创建web空项目 2.创建完如图 3.安装如下程序包Microsoft.AspNet.WebApi.Core (5.2.4)Microsoft.Owin.Host.SystemWeb (4.0. ...

  2. .Net Core3.0 WebApi 项目框架搭建 五:仓储模式

    .Net Core3.0 WebApi 项目框架搭建:目录 理论介绍 仓储(Respository)是存在于工作单元和数据库之间单独分离出来的一层,是对数据访问的封装.其优点: 1)业务层不需要知道它 ...

  3. .Net Core3.0 WebApi 项目框架搭建 五: 轻量型ORM+异步泛型仓储

    .Net Core3.0 WebApi 项目框架搭建:目录 SqlSugar介绍 SqlSugar是国人开发者开发的一款基于.NET的ORM框架,是可以运行在.NET 4.+ & .NET C ...

  4. Restful WebApi项目开发实践

    前言 踩过了一段时间的坑,现总结一下,与大家分享,愿与大家一起讨论. Restful WebApi特点 WebApi相较于Asp.Net MVC/WebForm开发的特点就是前后端完全分离,后端使用W ...

  5. Asp.net WebApi 项目示例(增删改查)

    1.WebApi是什么 ASP.NET Web API 是一种框架,用于轻松构建可以由多种客户端(包括浏览器和移动设备)访问的 HTTP 服务.ASP.NET Web API 是一种用于在 .NET ...

  6. Angularjs,WebAPI 搭建一个简易权限管理系统 —— WebAPI项目主体结构(四)

    目录 前言 Angularjs名词与概念 Angularjs 基本功能演示 系统业务与实现 WebAPI项目主体结构 Angularjs 前端主体结构 5.0 WebAPI项目主体结构 5.1 总体结 ...

  7. SNF快速开发平台MVC-EasyUI3.9之-WebApi和MVC-controller层接收的json字符串的取值方法和调用后台服务方法

    最近项目组很多人问我,从前台页面传到后台controller控制层或者WebApi 时如何取值和运算操作. 今天就都大家一个在框架内一个取值技巧 前台JS调用代码: 1.下面是选中一行数据后右键点击时 ...

  8. c#搭建webapi项目

    一.添加WebApi项目     二.nuget下载WebApi所需的类库引用 install-package Microsoft.AspNet.WebApi install-package Micr ...

  9. .Net Core3.0 WebApi 项目框架搭建:目录

    一.目录 .Net Core3.0 WebApi 项目框架搭建 一:实现简单的Resful Api .Net Core3.0 WebApi 项目框架搭建 二:API 文档神器 Swagger .Net ...

随机推荐

  1. javascript的getter和setter(转)

    显然这是一个无关IE(高级IE除外)的话题,尽管如此,有兴趣的同学还是一起来认识一下ECMAScript5标准中getter和setter的实现.在一个对象中,操作其中的属性或方法,通常运用最多的就是 ...

  2. React组件实现越级传递属性

    如果有这样一个结构:三级嵌套,分别是:一级父组件.二级子组件.三级孙子组件,且前者包含后者,结构如图: 如果把一个属性,比如color,从一级传递给三级,一般做法是使用props逐一向下传递,代码如下 ...

  3. 【linux 爱好者群】程序猿的那些聊天记录

    分享&&交流&&开放 you should get it 声明:好吧,我们的群只有5个人,但是有句话不是说的很对吗,一个项目最理想的不就是5个人么.我是写文本那个. 下 ...

  4. wpf之StackPanel、WrapPanel、WrapPanel之间的关系

    一.StackPanel StackPanel是以堆叠的方式显示其中的控件 1.可以使用Orientation属性更改堆叠的顺序分为水平方向(Orientation="Horizontal& ...

  5. 百度开源上传组件WebUploader的formData动态传值技巧

    基于Web页面的文件上传一直是互联网应用开发中避免不了的,从asp时代的AspUpload组件.到asp无组件上传,到.Net时代的FileUpload,再到HTML5时代的各种基于jQuery的上传 ...

  6. 【lucene系列学习】排序

    用lucene3实现搜索多字段并排序功能(设置权重)    

  7. 今天打补丁出问题了,害得我组长被扣了1k奖金。

    今天是第三次给mxdw打补丁和打包,外加公司高管说有一个东西必须要今天之内搞定外放. 我当时问策划为什么这么着急?策划说大佬决定的(这种做事方式真的很不习惯).我等屁民加班加点的搞事情,把功能搞出去了 ...

  8. 在Windows上安装MongoDB

    原文官方文档:https://docs.mongodb.org/v2.6/tutorial/install-mongodb-on-windows/ 基于版本:MongoDB 2.6 概览 通过这个示例 ...

  9. winXP/win7/win10系统关闭445端口方法全攻略

    近日有多个高校发布了关于连接校园网的电脑大面积中勒索病毒的消息,这种病毒致使许多高校毕业生的毕业论文(设计)被锁.受害机器的磁盘文件会被篡改为相应的后缀,图片.文档.视频.压缩包等各类资料都无法正常打 ...

  10. java内存模型6-final

    与前面介绍的锁和volatile相比较,对final域的读和写更像是普通的变量访问.对于final域,编译器和处理器要遵守两个重排序规则: 在构造函数内对一个final域的写入,与随后把这个被构造对象 ...