基于.net framework4.0框架下winform项目实现寄宿式web api
首先Nuget中下载包:Microsoft.AspNet.WebApi.SelfHost,如下:

注意版本哦,最高版本只能4.0.30506能用。
1.配置路由
public static class WebApiConfig{public static void Register(this HttpSelfHostConfiguration config){// 配置JSON序列化设置config.Formatters.Clear();config.Formatters.Add(new JsonMediaTypeFormatter());config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();// 配置路由//config.MapHttpAttributeRoutes();config.Routes.Clear();config.Routes.MapHttpRoute(name: "DefaultApi",routeTemplate: "api/{controller}/{action}/{id}",defaults: new { id = RouteParameter.Optional });}}
路由器不要搞错了,其实和老版本asp.net 差不多。
2.创建一个控制器
public class ValuesController : ApiController{[HttpGet]public string HelloWorld(){return "Hello World!";}[HttpGet]public ModelTest Test(){var model = new ModelTest();model.Id = Guid.NewGuid().ToString();model.Name = "Test";return model;}[HttpGet]public List<ModelTest> Test2(){List<ModelTest> modelTests = new List<ModelTest>();for (int i = 0; i < 3; i++){var model = new ModelTest();model.Id = Guid.NewGuid().ToString();model.Name = "Test";modelTests.Add(model);}return modelTests;}}
创建一个WebServer,以来加载实现单例
public class WebServer{private static Lazy<WebServer> _lazy = new Lazy<WebServer>(() => new WebServer());private ManualResetEvent _webEvent;private WebServer(){}public static WebServer Instance => _lazy.Value;public string BaseAddress { get;set; }public Action<WebServer> StartSuccessfulCallback { get; set; }public Action<WebServer> RunEndCallback { get; set; }public Action<WebServer, AggregateException> StartExceptionCallback { get;set; }public void StartWebServer(){if (string.IsNullOrEmpty(BaseAddress)) return;_webEvent=new ManualResetEvent(false);Task.Factory.StartNew(() =>{HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(BaseAddress);config.Register();using (HttpSelfHostServer server = new HttpSelfHostServer(config)){try{server.OpenAsync().Wait();if (StartSuccessfulCallback != null)StartSuccessfulCallback(this);_webEvent.WaitOne();if (RunEndCallback != null)RunEndCallback(this);}catch (AggregateException ex){_webEvent.Set();_webEvent.Close();_webEvent = null;if (StartExceptionCallback != null)StartExceptionCallback(this,ex);}finally{server.CloseAsync().Wait();server.Dispose();}}});}public void StopWebServer(){if (_webEvent == null) return;_webEvent.Set();_webEvent.Close();}}
public class WebApiFactory{static string baseAddress = "http://localhost:9000/";static WebApiFactory(){Server = WebServer.Instance;Server.BaseAddress = baseAddress;}public static WebServer Server { get;private set; }}
使用

public partial class Form1 : Form{public Form1(){InitializeComponent();WebApiFactory.Server.StartSuccessfulCallback = (t) =>{label1.Text = "Web API hosted on " + t.BaseAddress;};WebApiFactory.Server.RunEndCallback = (t) =>{label1.Text = "Web API End on " + t.BaseAddress;};WebApiFactory.Server.StartExceptionCallback = (t,ex) =>{MessageBox.Show(string.Join(";", ex.InnerExceptions.Select(x => x.Message)));};}private void button1_Click(object sender, EventArgs e){WebApiFactory.Server.StartWebServer();}private void button2_Click(object sender, EventArgs e){WebApiFactory.Server.StopWebServer();}private void Form1_FormClosing(object sender, FormClosingEventArgs e){WebApiFactory.Server.StopWebServer();}}
注:启动时必须以管理员身份启动程序
我们挂的是http://localhost:9000/,接下来我们去请求:http://localhost:9000/api/Values/Test2

扩展:简单添加权限验证,不通过路由
public class BasicAuthorizationHandler : DelegatingHandler{protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken){if (request.Method == HttpMethod.Options){var optRes = base.SendAsync(request, cancellationToken);return optRes;}if (!ValidateRequest(request)){var response = new HttpResponseMessage(HttpStatusCode.Forbidden);var content = new Result{success = false,errs = new[] { "服务端拒绝访问:你没有权限" }};response.Content = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json");var tsc = new TaskCompletionSource<HttpResponseMessage>();tsc.SetResult(response); return tsc.Task;}var res = base.SendAsync(request, cancellationToken);return res;}/// <summary>/// 验证信息解密并对比/// </summary>/// <param name="message"></param>/// <returns></returns>private bool ValidateRequest(HttpRequestMessage message){var authorization = message.Headers.Authorization;//如果此header为空或不是basic方式则返回未授权if (authorization != null && authorization.Scheme == "Basic" && authorization.Parameter != null){string Parameter = authorization.Parameter;// 按理说发送过来的做了加密,这里需要解密return Parameter == "111";// 身份验证码}else{return false;}}}/// <summary>/// 构建用于返回错误信息的对象/// </summary>public class Result{public bool success { get; set; }public string[] errs { get; set; }}
然后在WebApiConfig中注册
// 注册身份验证
config.MessageHandlers.Add(new BasicAuthorizationHandler());
根据自己需求做扩展吧,这里由于时间问题简单做身份验证(全局)



根据控制器或方法添加身份验证(非全局):
public class AuthorizationAttribute : AuthorizationFilterAttribute{public override void OnAuthorization(HttpActionContext actionContext){// 如果验证失败,返回未授权的响应if (!IsUserAuthorized(actionContext)){// 如果身份验证失败,返回未授权的响应var content = new Result{success = false,errs = new[] { "服务端拒绝访问:你没有权限" }};actionContext.Response= actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Unauthorized");actionContext.Response.Content = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json");}}private bool IsUserAuthorized(HttpActionContext actionContext){var authorizationHeader = actionContext.Request.Headers.Authorization;if (authorizationHeader != null && authorizationHeader.Scheme == "Bearer" && authorizationHeader.Parameter != null){// 根据实际需求,进行适当的身份验证逻辑// 比较 authorizationHeader.Parameter 和预期的授权参数值return authorizationHeader.Parameter == "111";}return false;}}
public static class WebApiConfig{public static void Register(this HttpSelfHostConfiguration config){// 注册身份验证(全局)//config.MessageHandlers.Add(new BasicAuthorizationHandler());config.Filters.Add(new AuthorizationAttribute());// 配置JSON序列化设置config.RegisterJsonFormatter();// 配置路由config.RegisterRoutes();}private static void RegisterJsonFormatter(this HttpSelfHostConfiguration config){config.Formatters.Clear();config.Formatters.Add(new JsonMediaTypeFormatter());config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();}private static void RegisterRoutes(this HttpSelfHostConfiguration config){//config.MapHttpAttributeRoutes();config.Routes.Clear();config.Routes.MapHttpRoute(name: "DefaultApi",routeTemplate: "api/{controller}/{action}/{id}",defaults: new { id = RouteParameter.Optional });}}
然后在控制器中:
public class ValuesController : ApiController{[HttpGet]public string HelloWorld(){return "Hello World!";}[HttpGet]public ModelTest Test(){var model = new ModelTest();model.Id = Guid.NewGuid().ToString();model.Name = "Test";return model;}[Authorization][HttpGet]public List<ModelTest> Test2(){List<ModelTest> modelTests = new List<ModelTest>();for (int i = 0; i < 3; i++){var model = new ModelTest();model.Id = Guid.NewGuid().ToString();model.Name = "Test";modelTests.Add(model);}return modelTests;}}
全局异常处理:
public class GlobalExceptionFilter : IExceptionFilter{public bool AllowMultiple => false;public Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken){// 在这里实现自定义的异常处理逻辑// 根据实际需求,处理异常并生成适当的响应// 示例:将异常信息记录到日志中LogException(actionExecutedContext.Exception);// 示例:返回带有错误信息的响应var content = new Result{success = false,errs = new[] { "发生了一个错误" }};actionExecutedContext.Response = actionExecutedContext.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Internal Server Error");actionExecutedContext.Response.Content = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json");var tcs = new TaskCompletionSource<object>();tcs.SetResult(null);return tcs.Task;}private void LogException(Exception exception){// 在这里编写将异常信息记录到日志的逻辑}}
public static class WebApiConfig{public static void Register(this HttpSelfHostConfiguration config){// 注册身份验证(全局)//config.MessageHandlers.Add(new BasicAuthorizationHandler());config.Filters.Add(new AuthorizationAttribute());// 注册全局异常过滤器config.Filters.Add(new GlobalExceptionFilter());// 配置JSON序列化设置config.RegisterJsonFormatter();// 配置路由config.RegisterRoutes();}private static void RegisterJsonFormatter(this HttpSelfHostConfiguration config){config.Formatters.Clear();config.Formatters.Add(new JsonMediaTypeFormatter());config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();}private static void RegisterRoutes(this HttpSelfHostConfiguration config){//config.MapHttpAttributeRoutes();config.Routes.Clear();config.Routes.MapHttpRoute(name: "DefaultApi",routeTemplate: "api/{controller}/{action}/{id}",defaults: new { id = RouteParameter.Optional });}}
写一个测试接口:
[HttpGet]public int Test3(){int a = 3;int b = 0;return a / b;}

我们知道有5个Filter,这里只用到了其中的两个,其它自定义实现
相关文章:
基于.net framework4.0框架下winform项目实现寄宿式web api
首先Nuget中下载包:Microsoft.AspNet.WebApi.SelfHost,如下: 注意版本哦,最高版本只能4.0.30506能用。 1.配置路由 public static class WebApiConfig{public static void Register(this HttpSelfHostConfiguration config){// …...
Vue中项目进行文件压缩与解压缩 (接口返回文件的url压缩包前端解析并展示出来,保存的时候在压缩后放到接口入参进行保存)
安装 npm install pako在Vue组件中引入pako: import pako from pako;接口返回的url是这个字段 tableSsjsonUrl 其实打开就是压缩包const source await tableFileUrl ({ id: this.$route.query.id}); if(source.code 0) {this.titleName source.data.tableNam…...
Linux shell编程学习笔记31:alias 和 unalias 操作 命令别名
目录 0 前言1 定义别名2 查看别名 2.1 查看所有别名2.2 查看某个别名 2.2.1 alias 别名2.2.2 alias | grep 别名字符串2.2.3 使用 CtrlAltE 组合键3 unalias:删除别名4 如何执行命令本身而非别名 4.1 方法1:使用 CtrlAltE 组合键 && unalias4…...
Django JSONField/HStoreField SQL注入漏洞(CVE-2019-14234)
漏洞描述 Django 于2019年8月1日 日发布了安全更新,修复了 JSONField 和 HStoreField 两个模型字段的 SQL 注入漏洞。 参考链接: Django security releases issued: 2.2.4, 2.1.11 and 1.11.23 | Weblog | DjangoDjango JSONField SQL注入漏洞&#x…...
Unity中Shader的Standard材质解析(一)
文章目录 前言一、在Unity中,按一下步骤准备1、在资源管理面板创建一个 Standard Surface Shader2、因为Standard Surface Shader有很多缺点,所以我们把他转化为顶点片元着色器3、整理只保留主平行光的Shader效果4、精简后的最终代码 前言 在Unity中&am…...
5.1 Windows驱动开发:判断驱动加载状态
在驱动开发中我们有时需要得到驱动自身是否被加载成功的状态,这个功能看似没啥用实际上在某些特殊场景中还是需要的,如下代码实现了判断当前驱动是否加载成功,如果加载成功, 则输出该驱动的详细路径信息。 该功能实现的核心函数是NtQuerySys…...
Linux之高级IO
目录 IO基本概念五种IO模型钓鱼人例子五种IO模型高级IO重要概念同步通信 VS 异步通信阻塞 VS 非阻塞其他高级IO阻塞IO非阻塞IO IO基本概念 I/O(input/output)也就是输入和输出,在著名的冯诺依曼体系结构当中,将数据从输入设备拷贝…...
进程和线程的关系
⭐ 作者:小胡_不糊涂 🌱 作者主页:小胡_不糊涂的个人主页 📀 收录专栏:JavaEE 💖 持续更文,关注博主少走弯路,谢谢大家支持 💖 进程&线程 1. 什么是进程PCB 2. 什么是…...
YOLOv5全网独家改进:NanoDet算法动态标签分配策略(附原创改进代码),公开数据集mAP有效涨点,来打造新颖YOLOv5检测器
💡本篇内容:YOLOv5全网独家改进:NanoDet算法动态标签分配策略(附原创改进代码),公开数据集mAP有效涨点,来打造新颖YOLOv5检测器 💡🚀🚀🚀本博客 YOLOv5+ 改进NanoDet模型的动态标签分配策略源代码改进 💡一篇博客集成多种创新点改进:NanoDet 💡:重点:更…...
原生DOM事件、react16、17和Vue合成事件
目录 原生DOM事件 注册/绑定事件 DOM事件级别 DOM0:onclick传统注册: 唯一(同元素的(不)同事件会覆盖) 没有捕获和冒泡的,只有简单的事件绑定 DOM2:addEventListener监听注册:可添加多个…...
基于HTML+CSS+JavaScript的登录注册界面设计
一、界面效果: 二、HTML代码: 登录注册html: 登录成功html: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <h1>登录成功!</h1> </body> <…...
BUUCTF [MRCTF2020]Ez_bypass 1
题目环境:F12查看源代码 I put something in F12 for you include flag.php; $flagMRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}; if(isset($_GET[gg])&&isset($_GET[id])) { $id$_GET[id]; $gg$_GET[gg]; if (md5($id) md5($gg) && $id ! $gg) { …...
基于Apache部署虚拟主机网站
文章目录 Apache释义Apache配置关闭防火墙和selinux 更改默认页内容更改默认页存放位置个人用户主页功能基于口令登录网站虚拟主机功能基于ip地址相同ip不同域名相同ip不同端口 学习本章完成目标 1.httpd服务程序的基本部署。 2.个人用户主页功能和口令加密认证方式的实现。 3.…...
大数据平台/大数据技术与原理-实验报告--部署全分布模式HBase集群和实战HBase
实验名称 部署全分布模式HBase集群和实战HBase 实验性质 (必修、选修) 必修 实验类型(验证、设计、创新、综合) 综合 实验课时 2 实验日期 2023.11.07-2023.11.10 实验仪器设备以及实验软硬件要求 专业实验室ÿ…...
手写字符识别神经网络项目总结
1.数据集 手写字符数据集 DIGITS,该数据集的全称为 Pen-Based Recognition of Handwritten Digits Data Set,来源于 UCI 开放数据集网站。 2.加载数据集 import numpy as np from sklearn import datasets digits datasets.load_digits() 3.分割数…...
八、Lua数组和迭代器
一、Lua数组 数组,就是相同数据类型的元素按一定顺序排列的集合,可以是一维数组和多维数组。 在 Lua 中,数组不是一种特定的数据类型,而是一种用来存储一组值的数据结构。 实际上,Lua 中并没有专门的数组类型…...
平凯星辰 TiDB 获评 “2023 中国金融科技守正创新扬帆计划” 十佳优秀实践奖
11 月 10 日,2023 金融街论坛年会同期举办了“第五届成方金融科技论坛——金融科技守正创新论坛”,北京金融产业联盟发布了“扬帆计划——分布式数据库金融应用研究与实践优秀成果”, 平凯星辰提报的实践报告——“国产 HTAP 数据库在金融规模…...
运算符展开、函数,对象,数组,字符串变化 集合
... 展开运算符 用于函数实参或者赋值号右边 console.log(...[1, 2, 3]) // 1,2,3console.log(Math.max(...[1, 2, 3]))//3 console.log(Math.max.apply(null, [1, 2, 3]))//3const o { a: 1, b: 2 }const obj { ...o, c: 3 }console.log(obj)//Object ... 剩余运算符 用于…...
NI自动化测试系统用电必备攻略,电源规划大揭秘
就像使用电脑之前需接通电源一样,自动化测试系统的电源选择也是首当其冲的问题,只不是这个问题更复杂。 比如,应考虑地理位置因素,因为不同国家或地区的公共电网所提供的线路功率有所不同。在电源布局和设备选型方面,有…...
ky10 server arm 在线编译安装openssl3.1.4
在线编译脚本 #!/bin/shOPENSSLVER3.1.4OPENSSL_Vopenssl versionecho "当前OpenSSL 版本 ${OPENSSL_V}" #------------------------------------------------ #wget https://www.openssl.org/source/openssl-3.1.4.tar.gzecho "安装OpenSSL${OPENSSLVER}...&q…...
【反蒸馏实战 07】技术支持工程师:当AI客服处理80%工单,你的价值在复杂根因与客户信任@技术支持工程师的AI治理与根因诊断实操指南
摘要:2026年,AI智能体已替代40%的技术支持岗位,处理80%以上的标准化工单——但这并非技术支持工程师的终点。本文基于AI治理框架、分布式链路追踪技术、Python自动化工具链,拆解“脚本执行者”到“AI治理工程师”的转型路径。通过4个核心实操模块(AI决策审计系统、跨系统根…...
智驾公司生死线 | 端到端是面子,含模量是里子
点击下方卡片,关注“自动驾驶之心”公众号戳我-> 领取自动驾驶近30个方向学习路线作者 | 圆周智行编辑 | 自动驾驶之心原文 | 端到端是面子,含模量是里子——智驾公司的生死线>>自动驾驶前沿信息获取→自动驾驶之心知识星球★谁在真正进化&…...
FastAPI项目半夜报警吵醒你?聊聊告警这事儿怎么搞!翱
Issue 概述 先来看看提交这个 Issue 的作者是为什么想到这个点子的,以及他初步的核心设计概念。?? 本 PR 实现了 Apache Gravitino 与 SeaTunnel 的集成,将其作为非关系型连接器的外部元数据服务。通过 Gravitino 的 REST API 自动获取表结构和元数据&…...
Delphi XE跨平台开发实战:Linux服务端应用构建指南
1. 为什么选择Delphi XE开发Linux服务端应用 作为一个在Windows平台深耕多年的Delphi开发者,当我第一次听说Delphi XE支持Linux开发时,内心是充满怀疑的。毕竟Linux开发环境向来以命令行和开源工具链著称,而Delphi给我的印象一直是可视化开发…...
不用装软件!这款MicroPython浏览器 IDE :让你在手机上也能调试树莓派 Pico毡
1、普通的insert into 如果(主键/唯一建)存在,则会报错 新需求:就算冲突也不报错,用其他处理逻辑 回到顶部 2、基本语法(INSERT INTO ... ON CONFLICT (...) DO (UPDATE SET ...)/(NOTHING)) 语…...
ResMLP、gMLP怎么选?深入对比三大纯MLP视觉模型的优缺点与落地场景
ResMLP、gMLP与MLP-Mixer技术选型指南:三大纯MLP视觉模型实战对比 当计算机视觉领域还在为Transformer和CNN争论不休时,一匹黑马正悄然改变游戏规则——纯MLP架构。不同于传统认知,MLP-Mixer、ResMLP和gMLP这些仅由多层感知机构建的模型&…...
终极游戏分屏解决方案:UniversalSplitScreen让多玩家同屏游戏变得简单
终极游戏分屏解决方案:UniversalSplitScreen让多玩家同屏游戏变得简单 【免费下载链接】UniversalSplitScreen Split screen multiplayer for any game with multiple keyboards, mice and controllers. 项目地址: https://gitcode.com/gh_mirrors/un/UniversalSp…...
抖音内容自动化采集:开源下载工具架构解析与实战应用
抖音内容自动化采集:开源下载工具架构解析与实战应用 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback suppor…...
RevitLookup完全指南:5分钟掌握BIM数据透视神器,轻松解决Revit开发调试难题
RevitLookup完全指南:5分钟掌握BIM数据透视神器,轻松解决Revit开发调试难题 【免费下载链接】RevitLookup Interactive Revit RFA and RVT project database exploration tool to view and navigate BIM element parameters, properties and relationshi…...
别光看模型列表!Spring AI和LangChain4j在向量数据库支持上的真实体验对比
别光看模型列表!Spring AI和LangChain4j在向量数据库支持上的真实体验对比 当开发者选择Java生态的AI框架时,往往被琳琅满目的模型支持列表吸引注意力。但在实际构建RAG系统或知识库应用时,向量数据库的集成体验才是决定开发效率的关键因素。…...
