C#搭建WebApi服务

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//89726657

相关推荐
mudtools16 分钟前
.NET驾驭Word之力:理解Word对象模型核心 (Application, Document, Range)
c#·.net
侃侃_天下6 小时前
最终的信号类
开发语言·c++·算法
echoarts6 小时前
Rayon Rust中的数据并行库入门教程
开发语言·其他·算法·rust
Aomnitrix6 小时前
知识管理新范式——cpolar+Wiki.js打造企业级分布式知识库
开发语言·javascript·分布式
大飞pkz6 小时前
【设计模式】C#反射实现抽象工厂模式
设计模式·c#·抽象工厂模式·c#反射·c#反射实现抽象工厂模式
每天回答3个问题7 小时前
UE5C++编译遇到MSB3073
开发语言·c++·ue5
伍哥的传说7 小时前
Vite Plugin PWA – 零配置构建现代渐进式Web应用
开发语言·前端·javascript·web app·pwa·service worker·workbox
小莞尔7 小时前
【51单片机】【protues仿真】 基于51单片机八路抢答器系统
c语言·开发语言·单片机·嵌入式硬件·51单片机
我是菜鸟0713号8 小时前
Qt 中 OPC UA 通讯实战
开发语言·qt
JCBP_8 小时前
QT(4)
开发语言·汇编·c++·qt·算法