1,OWIN的介绍
OWIN 的全称是 "Open Web Interface for .NET", OWIN 在 .NET Web 服务器和 .NET Web 应用之间定义了一套标准的接口, 其目的是为了实现服务器与应用之间的解耦,使得便携式 .NET Web 应用以及跨平台的愿望成为现实, 标准的 OWIN 应用可以在任何 OWIN 兼容的服务器上运行, 不再依赖于Windows和IIS 。
2,添加NutGet
添加Microsoft.AspNet.WebApi.Owin 和 Microsoft.AspNet.WebApi.Owin Self Host包(Self Host 用于开启OWIN Host,设置监听接受Http请求)
3,添加Startup类
Startup是OWIN约定的,用于对OWIN做相关配置的,代码如下:
using Owin;using System;using System.Collections.Generic;using System.Linq;using System.Net.Http.Headers;using System.Text;using System.Threading.Tasks;using System.Web.Http;using System.Web.Http.Cors;namespace WebAPIServer{ /// <summary> /// Startup是OWIN约定的,用于对OWIN做相关配置 /// </summary> public class Startup { public void Configuration(IAppBuilder appBuilder) { try { HttpConfiguration config = new HttpConfiguration(); config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); config.EnableCors(new EnableCorsAttribute("*", "*", "*")); //启用路由特性 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional }, constraints: new { id = @"\d*" }//新增一个约束,指定id只能是数字,不能是其他 ); //再自定义一个路由,第一个路由匹配失败再匹配这个 config.Routes.MapHttpRoute( name: "ActionApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); appBuilder.UseWebApi(config); } catch (Exception ex) { throw ex; } } }}
4,新建Controllers文件夹,添加FileControllers类
按照 Web API 项目的约定,在项目中添加一个名称为 Controllers 的文件夹,然后新建 一个FileController类,设置其基类为 System.Web.Http.ApiController ,作为示例,其内容与 Visual Studio 自带的 Web API Controller 模板一致,包含4种请求方式(GET/POST/PUT/DELETE),用于演示,重写GET方法(直接返回请求参数)和POST方法(接受实体类参数直接返回),FileController代码如下:
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Net;using System.Net.Http;using System.Net.Http.Headers;using System.Threading.Tasks;using System.Web;using System.Web.Http;using WebAPIServer.Services;namespace WebAPIServer.Controllers{ /// <summary> /// 文件类控制器 /// </summary> public class FileController : ApiController { private string UploadFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UploadFolder"); private MediaServer _mediaServer = new MediaServer(); /// <summary> /// 上传文件 /// </summary> /// <returns></returns> [HttpPost] public async Task<IHttpActionResult> UploadFolder() { if (!Request.Content.IsMimeMultipartContent("form-data")) { return StatusCode(HttpStatusCode.UnsupportedMediaType); } var provider = new MultipartMemoryStreamProvider(); await Request.Content.ReadAsMultipartAsync(provider); await _mediaServer.UploadFolder(provider, UploadFolderPath); // 创建文件夹(如果尚未存在) return Ok(); } [HttpGet] public async Task<HttpResponseMessage> DownloadFile(string fileName) { // 获取文件路径 string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "~/UploadFolder/" + fileName); // 检查文件是否存在 if (!File.Exists(filePath)) { return Request.CreateErrorResponse(HttpStatusCode.NotFound, "The specified file does not exist."); } // 创建 HTTP 响应消息 HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); // 设置响应内容 using (FileStream fileStream = File.OpenRead(filePath)) { response.Content = new StreamContent(fileStream); // 设置响应头 response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = fileName }; await response.Content.LoadIntoBufferAsync(); } return response; } }
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Net.Http;using System.Threading.Tasks;using System.Web;namespace WebAPIServer.Services{ public class MediaServer { /// <summary> /// 上传文件 /// </summary> /// <param name="provider"></param> /// <param name="_uploadFolder"></param> /// <returns></returns> public async Task UploadFolder(MultipartMemoryStreamProvider provider, string _uploadFolder) { // 创建文件夹(如果尚未存在) Directory.CreateDirectory(_uploadFolder); foreach (var content in provider.Contents) { var disposition = content.Headers.ContentDisposition; var fileName = disposition.FileName.Trim('"'); fileName = Path.GetFileName(fileName); var fileData = await content.ReadAsByteArrayAsync(); // 将文件保存到本地文件夹中 var filePath = Path.Combine(_uploadFolder, fileName); using (var fileStream = new FileStream(filePath, FileMode.Create)) { await fileStream.WriteAsync(fileData, 0, fileData.Length); } } } }}
using System;using System.Collections.Generic;using System.Linq;using System.Net.Http;using System.Text;using System.Threading.Tasks;using System.Web.Http;namespace WebAPIServer.Controllers{ /// <summary> /// 验证管理控制器 /// </summary> public class AuthorizationController : ApiController { // GET api/<controller> public string Get() { return "ok"; } // GET api/<controller>/5 public string Get(int id) { return string.Format("owin {0} by:linezero", id); } /// <summary> /// 获取授权码 /// </summary> /// <param name="info"></param> /// <returns></returns> [Route("api/Authorization"), HttpPost] // 自定义路由 public async Task<HttpResponseMessage> GetAuthorizationCode([FromBody] AuthorizationInfo info) { await Task.Run(() => { //进行计算并将相应值保存至服务器 WebAPIOWINServer.AuthorizationInfoRequest?.Invoke(this, info); }); HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); response.Content = new StringContent($"感谢您的支持,我们将以邮件的形式将授权码发送给您的Email:{info.Email},请注意查收。", Encoding.UTF8); return response; } // PUT api/<controller>/5 public string Put([FromBody] string value) { return "Success"; } // DELETE api/<controller>/5 public string Delete([FromBody] string value) { return "Success"; } } public class AuthorizationInfo { public string Id { get; set; } public string CPUSerialNumber { get; set; } public string BIOSSerialNumber { get; set; } public string Email { get; set; } public DateTime CreateDate { get; set; } }}
5,添加WebApi服务类,代码如下:
using Microsoft.Owin.Hosting;using System;using System.Collections.Generic;using System.Linq;using System.Net.Http;using System.Text;using System.Threading.Tasks;using WebAPIServer.Controllers;namespace WebAPIServer{ /// <summary> /// WebAPI服务类,提供WebApi服务 /// </summary> public class WebAPIOWINServer { static IDisposable webApiObject = null; /// <summary> /// 开启WebApi服务 /// </summary> /// <param name="ServerUrl">绑定的服务uri</param> /// <returns></returns> public bool Start(string ServerUrl) { try { //调用Startup启动owin,url需要调用方传入 webApiObject = WebApp.Start<Startup>(url: ServerUrl); HttpClient client = new HttpClient(); //通过get请求数据,测试owin服务是否正常开启 Uri uri = new Uri(new Uri(ServerUrl), "api/Authorization/get"); var response = client.GetAsync(uri).Result; if (response.IsSuccessStatusCode) { return true; } else { webApiObject?.Dispose(); throw new Exception("Owin loacal server start failed!"); } } catch (Exception) { webApiObject?.Dispose(); throw; } } #region 定义应用于webapi接口 /// <summary> /// 请求获取授权码 /// </summary> public static Action<object, Controllers.AuthorizationInfo> AuthorizationInfoRequest; #endregion /// <summary> /// 关闭服务 /// </summary> public void Close() { webApiObject?.Dispose(); } }}
6,实例:
效果:
特别注意事项:非管理员权限只用于绑定localhost,若绑定其他地址如:http;//127.0.0.1将抛出“调用目标发生异常”的异常。如果想绑定其他地址请使用管理员权限。
代码:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace Demo{ public partial class Form1 : Form { WebAPIServer.WebAPIOWINServer server = new WebAPIServer.WebAPIOWINServer(); public Form1() { InitializeComponent(); } private void btnStart_Click(object sender, EventArgs e) { if (btnStart.Text == "启动服务") { if (Uri.IsWellFormedUriString(txtIP.Text.Trim(), UriKind.RelativeOrAbsolute)) { try { if (server.Start(txtIP.Text.Trim())) { SetStatus(true); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } else { MessageBox.Show("网址格式错误"); } } else { server.Close(); SetStatus(false); } } void SetStatus(bool isOpen) { if (isOpen) { btnStart.BackColor = Color.Green; btnStart.Text = "停止服务"; btnStart.ForeColor = Color.Black; txtIP.Enabled = false; } else { btnStart.BackColor = Color.Red; btnStart.Text = "启动服务"; btnStart.ForeColor = Color.White; txtIP.Enabled = true; } } }}
API控制器
using System;using System.Collections.Generic;using System.Linq;using System.Net.Http;using System.Text;using System.Threading.Tasks;using System.Web.Http;namespace WebAPIServer.Controllers{ /// <summary> /// 验证管理控制器 /// </summary> public class AuthorizationController : ApiController { // GET api/<controller> public string Get() { return "ok"; } // GET api/<controller>/5 public IHttpActionResult Get(int id) { return Json(new {Method="Get",Value=id }); } /// <summary> /// 获取授权码 /// </summary> /// <param name="info"></param> /// <returns></returns> [Route("api/Authorization"), HttpPost] // 自定义路由 public async Task<HttpResponseMessage> GetAuthorizationCode([FromBody] AuthorizationInfo info) { await Task.Run(() => { //进行计算并将相应值保存至服务器 WebAPIOWINServer.AuthorizationInfoRequest?.Invoke(this, info); }); HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); response.Content = new StringContent($"感谢您的支持,我们将以邮件的形式将授权码发送给您的Email:{info.Email},请注意查收。", Encoding.UTF8); return response; } // PUT api/<controller>/5 public string Put([FromBody] string value) { return "Success"; } // DELETE api/<controller>/5 public string Delete([FromBody] string value) { return "Success"; } } public class AuthorizationInfo { public string Id { get; set; } public string CPUSerialNumber { get; set; } public string BIOSSerialNumber { get; set; } public string Email { get; set; } public DateTime CreateDate { get; set; } }}
调用WebApi服务时,不仅仅需要引用上述自定义的程序集WebApiServer.dll,还需要再次添加Microsoft.AspNet.WebApi.Owin 和 Microsoft.AspNet.WebApi.Owin Self Host包,否则将报错。
7,WebApiDemo链接。
https://download.csdn.net/download/lingxiao16888/89726657