.net framework4.5.2+HttpSelfHostConfiguration 使用异常过滤器来做api接口的思想

本文介绍了如何在老旧的.NETFramework4.5中使用HttpSelfHostConfiguration创建自宿主服务,包括添加全局过滤器如授权和异常处理,以及如何设计API接口并实现相关控制器。作者还分享了项目目录结构和关键代码片段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

.Net FrameWork4.5 已经是行将就木的老技术了,当时我刚开始工作的时候就用,现在得有6.7年了,
这次想用它来写个api接口

HttpSelfHostConfiguration 自宿主服务

宿主一词我们不会陌生,它可以看作是一个基础设施,它为一些服务和功能提供最底层的支持,如你的web应用程序可以运行在iis或者apache上,而这两个东西就是web应用程序的宿主,而今天说的自主宿主SelfHost就是说,它可以自己去监听自己的服务,如你可以把一个web应用程序宿主到一个console控制台程序上,或者把一个webApi宿主到一个console或者windowService上,这都是可以的。(这段话是抄的,大家理解一下就好)
下面是我的自宿主程序代码

api接口流程图

api接口的设计流程图如下
在这里插入图片描述

项目目录结构如下

后面有各个类的具体代码
在这里插入图片描述

使用控制台创建自宿主项目 + 绑定全局过滤器

使用自宿主服务,项目要引用几个dll,如果没有的话大家可以去拷贝下载
在这里插入图片描述

using Newtonsoft.Json;
using Robot2.OpenApi.V2.Filter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Cors;
using System.Web.Http.SelfHost;

namespace ConsoleApp2
{
    internal class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string url = string.Format("http://localhost:20100");
                var config = new HttpSelfHostConfiguration(url);
                config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
                config.Formatters.Add(new System.Net.Http.Formatting.JsonMediaTypeFormatter());
                HttpSelfHostServer _hostServer = new HttpSelfHostServer(config);
                config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
                config.EnableCors(new EnableCorsAttribute("*", "*", "GET, POST, PUT, DELETE, OPTIONS") { SupportsCredentials = true });
                config.Filters.Add(new AuthorFilter());
                config.Filters.Add(new ExceptionFilter());
                config.Routes.MapHttpRoute(
                 name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}",
                defaults: new
                {
                    controller = "Home",
                    action = "Index",
                    id = RouteParameter.Optional
                });
                _hostServer.OpenAsync().Wait();
                Console.WriteLine("服务端口打开成功");
            }
            catch (Exception ex)
            {
                Console.WriteLine("服务端口打开异常:" + JsonConvert.SerializeObject(ex));
            }
            Console.ReadKey();
        }
    }
}

.Net FrameWork4.5 中的过滤器

过滤器的知识基本做2年的后端工程师都会懂,就不做赘述了,但是不同于.net core更好的AOP思想
.net framework里内置的过滤器种类就少了很多,常用的基本就只有一两种,这次的api接口中
使用以下两种过滤器

  • System.Web.Http.Filters.IAuthorizationFilter (权限过滤器)
  • System.Web.Http.Filters.IExceptionFilter (异常过滤器)
    过滤器代码如下
using Microsoft.SqlServer.Server;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.Remoting.Contexts;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Web.Http.Results;

namespace Robot2.OpenApi.V2.Filter
{
    /// <summary>
    /// 请求过滤器(日志记录)
    /// </summary>
    public class AuthorFilter : System.Web.Http.Filters.IAuthorizationFilter
    {
        public class Message
        {
            public string Title { get; set; }
            public string Content { get; set; }
        }
        public bool AllowMultiple => throw new NotImplementedException();

        public async Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
        {
            //Token校验验证
            var datas = await continuation();
            var value = ((System.Net.Http.ObjectContent)datas.Content).Value;
            Message data = new Message()
            {
                Title = "Success",
                Content = JsonConvert.SerializeObject(value)
            };
            string dataStr = JsonConvert.SerializeObject(data);
            var res = new HttpResponseMessage(HttpStatusCode.OK);
            res.Content = new StringContent(dataStr, Encoding.UTF8, "application/json");
            return res;
        }
    }
}

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.Remoting.Contexts;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Filters;
using static Robot2.OpenApi.V2.Filter.AuthorFilter;

namespace Robot2.OpenApi.V2.Filter
{
    public class ExceptionFilter : System.Web.Http.Filters.IExceptionFilter
    {
        public bool AllowMultiple => throw new NotImplementedException();

        public Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
        {

            Message msg = new Message()
            {
                Content = "服务器异常",
                Title = "Error"
            };
            return Task.Run(() =>
            {

                var errormsg = actionExecutedContext.Exception;
                if (errormsg is ApiException)
                {
                    var error = errormsg as ApiException;
                    msg.Content = error.ErrorMessage;
                }
                else
                {
                    Console.WriteLine(errormsg);
                }
                HttpResponseMessage httpResponse = new HttpResponseMessage();
                HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(msg), Encoding.UTF8, "application/json");
                httpResponse.Content = httpContent;
                actionExecutedContext.Response = httpResponse;
            });
        }
    }
}

新增的异常类

很简单的异常类,就是继承Exception,来实现一个自定义异常

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Robot2.OpenApi.V2
{
    /// <summary>
    /// api异常编码
    /// </summary>
    public class ApiException : Exception
    {
        /// <summary>
        /// 状态编码
        /// </summary>
        public int StatusCode { get; set; } = 500;
        /// <summary>
        /// 错误描述
        /// </summary>
        public string ErrorMessage { get; set; }
        /// <summary>
        /// 错误编码
        /// </summary>
        public string ErrorCode { get; set; }
        /// <summary>
        /// 抛出异常错误,返回结果
        /// </summary>
        /// <param name="ErrorMsg"></param>
        /// <returns></returns>
        public static ApiException Oh(string ErrorMsg)
        {
            return new ApiException()
            {
                ErrorMessage = ErrorMsg,
                ErrorCode = "Error"
            };
        }

        /// <summary>
        /// 抛出异常错误,返回结果
        /// </summary>
        /// <param name="ErrorMsg"></param>
        /// <returns></returns>
        public static ApiException Oh(string ErrorCode, string ErrorMsg)
        {
            return new ApiException()
            {
                ErrorMessage = ErrorMsg,
                ErrorCode = ErrorCode
            };
        }
    }
}

新增Controller,编写api代码

Controller代码如下

using Robot2.OpenApi.V2;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;

namespace ConsoleApp2
{
    public class TestController: ApiController
    {
        [HttpPost]
        public string Test1() {
            return "ssss";
        }


         public class sss
        {
            public string text { get; set; }
        }
        [HttpPost]
        public int Test2(sss t)
        {
            throw ApiException.Oh($"{t.text}数据error");
        }

        public Dictionary<string, object> Test3() {
            return new Dictionary<string, object>
            {
                ["sdsds"]="wewewe",
                ["12121"]=3.65
            };
        }
    }
}

Controller 各方法调用截图如下

使用postman调用各个请求方法 ,调用的结果如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

是个很巧妙的构思,希望大家可以一起交流借鉴,也体现了AOP切片思想编程么
如果要在.net core中实现,那就更有趣了
.net core的过滤器种类更多,且分工更细化

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值