前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Winform开启Web API服务新姿势

Winform开启Web API服务新姿势

作者头像
沙漠尽头的狼
发布2023-12-04 20:38:18
2230
发布2023-12-04 20:38:18
举报
文章被收录于专栏:Dotnet9Dotnet9

首先Nuget中下载包:Microsoft.AspNet.WebApi.SelfHost,如下:

注意版本哦,最高版本只能4.0.30506能用。

  1. 配置路由
代码语言:javascript
复制
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 差不多。

  1. 创建一个控制器
代码语言:javascript
复制
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,以来加载实现单例

代码语言:javascript
复制
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();
        }
    }
代码语言:javascript
复制
public class WebApiFactory
    {
        static string baseAddress = "http://localhost:9000/";
 
        static WebApiFactory()
        {
            Server = WebServer.Instance;
            Server.BaseAddress = baseAddress;
        }
        public static WebServer Server { get;private set; }
    }

使用

代码语言:javascript
复制
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

扩展:简单添加权限验证,不通过路由

代码语言:javascript
复制
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中注册

代码语言:javascript
复制
// 注册身份验证
config.MessageHandlers.Add(new BasicAuthorizationHandler());

根据自己需求做扩展吧,这里由于时间问题简单做身份验证(全局)

根据控制器或方法添加身份验证(非全局):

代码语言:javascript
复制
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;
        }
    }
代码语言:javascript
复制
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 }
            );
        }
    }

然后在控制器中:

代码语言:javascript
复制
 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;
        }
    }

全局异常处理:

代码语言:javascript
复制
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)
       {
           // 在这里编写将异常信息记录到日志的逻辑
       }
   }
代码语言:javascript
复制
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 }
            );
        }
    }

写一个测试接口:

代码语言:javascript
复制
    [HttpGet]
    public int Test3()
    {
        int a = 3;
        int b = 0;
 
        return a / b;
    }

我们知道有5个Filter,这里只用到了其中的两个,其它自定义实现

本文由游子吟i[1]投稿,原文链接:基于.net framework4.0框架下winform项目实现寄宿式web api-CSDN博客[2]

参考

[1]

游子吟i: https://blog.csdn.net/ftfmatlab

[2]

基于.net framework4.0框架下winform项目实现寄宿式web api-CSDN博客: https://blog.csdn.net/ftfmatlab/article/details/134563953

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-12-03,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 Dotnet9 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 参考
相关产品与服务
多因子身份认证
多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com