基于.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,这里只用到了其中的两个,其它自定义实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/183208.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MDK AC5和AC6是什么?在KEIL5中添加和选择ARMCC版本

前言 看视频有UP主提到“AC5”“AC6”这样的词&#xff0c;一开始有些不理解&#xff0c;原来他说的是ARMCC版本。 keil自带的是ARMCC5&#xff0c;由于ARMCC5已经停止维护了&#xff0c;很多开发者会选择ARMCC6。 在维护公司“成年往事”项目可能就会遇到新KEIL旧版本编译器…

NSGA-II求解微电网多目标优化调度(MATLAB)

一、NSGA-II简介 NSGA-Ⅱ算法是Kalyanmoy Deb等人于 2002年在 NSGA 的基础上提出的&#xff0c;它比 NSGA算法更加优越&#xff1a;它采用了快速非支配排序算法&#xff0c;计算复杂度比 NSGA 大大的降低&#xff1b;采用了拥挤度和拥挤度比较算子&#xff0c;代替了需要指定的…

第十五届蓝桥杯(Web 应用开发)模拟赛 1 期-大学组(详细分析解答)

目录 1.动态的Tab栏 1.1 题目要求 1.2 题目分析 1.3 源代码 2.地球环游 2.1 题目要求 2.2 题目分析 2.3 源代码 3.迷惑的this 3.1 题目要求 3.2 题目分析 3.3 源代码 4.魔法失灵了 4.1 题目要求 4.2 题目分析 4.3 源代码 5.燃烧你的卡路里 5.1 题目要求 5.2…

西门子(Siemens)仿真PLC启动报错处理

目录 一、背景&#xff1a; 二、卸载软件 三、安装软件 三、启动软件 四、下载PORTAL项目 五、测试 一、背景&#xff1a; 在启动S7-PLCSIM Advanced V3.0仿真PLC时报错&#xff0c;报错信息为&#xff1a;>>Siemens PLCSIM Virtual Switch<<is misconfigu…

基于C#实现Prim算法

图论在数据结构中是非常有趣而复杂的&#xff0c;作为 Web 码农的我&#xff0c;在实际开发中一直没有找到它的使用场景&#xff0c;不像树那样的频繁使用&#xff0c;不过还是准备仔细的把图论全部过一遍。 一、最小生成树 图中有一个好玩的东西叫做生成树&#xff0c;就是用…

Redis并发问题解决方案

目录 前言 1.分布式锁 1.基于单个节点 2.基于多个节点 3.watch(乐观锁) 2.原子操作 1.单命令操作 2.Lua 脚本(多命令操作) 3.事务 1.执行步骤 2.错误处理 3.崩溃处理 总结 前言 在多个客户端并发访问Redis的时候&#xff0c;虽然Redis是单线程执行指令&#xff…

基于IDEA+HTML+SpringBoot前后端分离电子商城

基于springboot的电子商城 项目介绍&#x1f481;&#x1f3fb; •B2C 商家对客户 •C2B2C 客户对商家对客户 1.1.1 B2C 平台运营方即商品的卖家 小米商城 •商品 •用户 1.1.2 C2B2C 平台运营方不卖商品&#xff08;也可以卖&#xff09; 卖家是平台的用户 买家也是平台用户 •…

【算法】经典算法题

文章目录 专题一&#xff1a;双指针1. 移动零2. 复写零3. 快乐数4. 盛最多水的容器5. 有效三角形的个数6. 查找总价格为目标值的两个商品7. 三数之和8. 四数之和 专题二&#xff1a;滑动窗口1. 长度最小的子数组2. 无重复字符的最长字串3. 最大连续1的个数 III4. 将 x 减到 0 的…

请你说一下Vue中v-if和v-for的优先级谁更高

v-if 与 v-for简介 v-ifv-forv-if & v-for使用 v-if 与 v-for优先级比较 vue2 中&#xff0c;v-for的优先级高于v-if 例子进行分析 vue3 v-if 具有比 v-for 更高的优先级 例子进行分析 总结 在vue2中&#xff0c;v-for的优先级高于v-if在vue3中&#xff0c;v-if的优先级高…

61 权限提升-RedisPostgre令牌窃取进程注入

目录 演示案例:Redis数据库权限提升-计划任务PostgreSQL数据库权限提升Windows2008&7令牌窃取提升-本地Windows2003&10进程注入提升-本地pinjector进程注入工具针对-win2008以前操作系统pexec64 32进程注入工具针对-win2008及后操作系统- (佛系) 涉及资源: postgersql是…

2023亚太杯数学建模APMCM竞赛C题思路讲解:基于ARIMA与机理模型进行预测

本文针对6大问题,从多角度分析了我国新能源电动汽车发展形势与前景。文中针对不同问题,采用了层次分析法、时间序列模型、机理模型、回归模型等数学方法。并结合实例数据,对相关模型进行求解,以量化预测了新能源电动汽车在政策驱动、市场竞争、温室气体减排等多个方面的潜在贡献…

OpenCV快速入门:图像分析——图像分割和图像修复

文章目录 前言一、图像分割1.1 漫水填充法1.1.1 漫水填充法原理1.1.2 漫水填充法实现步骤1.1.3 代码实现 1.2 分水岭法1.2.1 分水岭法原理1.2.2 分水岭法实现步骤1.2.3 代码实现 1.3 GrabCut法1.3.1 GrabCut法原理1.3.2 GrabCut法实现步骤1.3.3 代码实现 1.4 Mean-Shift法1.4.1…

【分布式】小白看Ring算法 - 03

相关系列 【分布式】NCCL部署与测试 - 01 【分布式】入门级NCCL多机并行实践 - 02 【分布式】小白看Ring算法 - 03 【分布式】大模型分布式训练入门与实践 - 04 概述 NCCL&#xff08;NVIDIA Collective Communications Library&#xff09;是由NVIDIA开发的一种用于多GPU间…

Navicat 技术指引 | 适用于 GaussDB 的数据迁移工具

Navicat Premium&#xff08;16.2.8 Windows版或以上&#xff09; 已支持对 GaussDB 主备版的管理和开发功能。它不仅具备轻松、便捷的可视化数据查看和编辑功能&#xff0c;还提供强大的高阶功能&#xff08;如模型、结构同步、协同合作、数据迁移等&#xff09;&#xff0c;这…

基于element-ui后台模板,日常唠嗑

后面会补充github地址 文章目录 目录 文章目录 案例说明 1.引入库 2.创建布局组件 3.创建布局组件 4.菜单效果展示 5.创建顶部组件 5.创建顶部面包屑组件 6.创建内容区域组件 7.效果总览 7.布丁&#xff08;实现一些小细节&#xff09; 前言一、pandas是什么&#xff1f;二、使…

Android Studio记录一个错误:Execution failed for task ‘:app:lintVitalRelease‘.

Android出现Execution failed for task :app:lintVitalRelease.> Lint found fatal errors while assembling a release target. Execution failed for task :app:lintVitalRelease解决方法 Execution failed for task ‘:app:lintVitalRelease’ build project 可以正常执…

计算机网络之网络层

一、概述 主要任务是实现网络互连&#xff0c;进而实现数据包在各网络之间的传输 1.1网络引入的目的 从7层结构上看&#xff0c;网络层下是数据链路层 从4层结构上看&#xff0c;网络层下面是网络接口层 至少我们看到的网络层下面是以太网 以太网解决了什么问题&#xff1f; 答…

python中一个文件(A.py)怎么调用另一个文件(B.py)中定义的类AA详解和示例

本文主要讲解python文件中怎么调用另外一个py文件中定义的类&#xff0c;将通过代码和示例解读&#xff0c;帮助大家理解和使用。 目录 代码B.pyA.py 调用过程 代码 B.py 如在文件B.py,定义了类别Bottleneck&#xff0c;其包含卷积层、正则化和激活函数层&#xff0c;主要对…

微信小程序实现【点击 滑动 评分 评星(5星)】功能

wxml文件&#xff1a; <view class"wxpl_xing"><view class"manyidu">{{scoreContent}}</view><view><block wx:for{{scoreArray}} wx:for-item"item"><view classstarLen bindtapchangeScore data-sy"{{…

什么是LLC电路?

LLC电路是由2个电感和1个电容构成的谐振电路&#xff0c;故称之为LLC&#xff1b; LLC电路主要由三个元件组成&#xff1a;两个电感分别为变压器一次侧漏感(Lr)和励磁电感(Lm)&#xff0c;电容为变压器一次侧谐振电容(Cr)。这些元件构成了一个谐振回路&#xff0c;其中输入电感…