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包,否则将报错。