基于.net framework4.0框架下winform项目实现寄宿式web api

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

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

1.配置路由

cs 复制代码
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.创建一个控制器

cs 复制代码
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,以来加载实现单例

cs 复制代码
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();
        }
    }
cs 复制代码
public class WebApiFactory
    {
        static string baseAddress = "http://localhost:9000/";

        static WebApiFactory()
        {
            Server = WebServer.Instance;
            Server.BaseAddress = baseAddress;
        }
        public static WebServer Server { get;private set; }
    }

使用

cs 复制代码
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

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

cs 复制代码
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中注册

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

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

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

cs 复制代码
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;
        }
    }
cs 复制代码
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 }
            );
        }
    }

然后在控制器中:

cs 复制代码
 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;
        }
    }

全局异常处理:

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

写一个测试接口:

cs 复制代码
        [HttpGet]
        public int Test3()
        {
            int a = 3;
            int b = 0;

            return a / b;
        }

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

相关推荐
波波0072 小时前
每日一题:中间件是如何工作的?
中间件·.net·面试题
无风听海3 小时前
.NET 10之可空引用类型
数据结构·.net
码云数智-园园4 小时前
基于 JSON 配置的 .NET 桌面应用自动更新实现指南
.net
无风听海4 小时前
.NET 10 之dotnet run的功能
.net
岩屿4 小时前
Ubuntu下安装Docker并部署.NET API(二)
运维·docker·容器·.net
码云数智-大飞4 小时前
.NET 中高效实现 List 集合去重的多种方法详解
.net
easyboot4 小时前
使用tinyply.net保存ply格式点云
.net
张人玉4 小时前
WPF 多语言实现完整笔记(.NET 4.7.2)
笔记·.net·wpf·多语言实现·多语言适配
波波0071 天前
Native AOT 能改变什么?.NET 预编译技术深度剖析
开发语言·.net
Crazy Struggle2 天前
.NET 中如何快速实现 List 集合去重?
c#·.net