WebAPi返回类型到底应该是什么才合适,这是个问题?
前言
有些问题只有真正遇到或者用到并且多加思考才会想到,平常若作为自学的心态去学习则不会考虑太多,我慢慢明白对于那些有太多要学的东西或者说的更加明确而且具体一点的话,如果对于你现在不是迫切要学或者需要掌握的技能,那就暂且放在一边吧,比如现在比较火的angular和react,我之前也花时间去学了,但是公司压根不用或者有专门的前端你学多了貌似没什么很大的实际用途,其实仅仅做一点基本的了解即可,至少别人问起也知道一二,不要看到别人学什么或者火了什么就盲目跟风,还是根据自身实际情况来学习才是王道。这不刚说到根据自身来学习,脑袋妄想着正在做的项目,突然冒出一个想法,为什么那不可以,为什么它又存在呢?这篇文章就出来了。
话题介绍
我们知道在WebAPi中对于响应结果我们都是这样用的:
public HttpResponseMessage GetResult<T>(T t) { return Request.CreateResponse<T>(HttpStatusCode.OK, t); }
在项目中前端为了和其他统一,封装了一套响应的结果和状态码,要求直接返回对象,于是将上述修改成比如如下:
public Result<List<Person>> GetResult() { var result = new Result<List<Person>>(); return result; } public class Result<T> : BaseResult { public T Data; } public class BaseResult { public string Message; public int Status; public ErrorCode ErrorCode; } public enum ErrorCode { ...... }
统观以上两种方法,一种是WebAPi内置响应的结果,另外一种则是直接返回自定义响应结果。
于是乎,我开始思索这两种方法虽然都能得到我们想要的结果,但是有什么区别没有呢?说的更加明确一点的是,二者在数据响应上有没有性能上的差异呢?
WebAPi响应结果和自定义响应结果二者性能差异
以上则是需要返回对象来进行处理,而有些我们则不需要返回任何对象来进行处理例如直接返回void,而在WebAPi中对应需要返回 IHttpActionResult 例如自定义返回则是如下:
public void GetFirst() {.....}
在WebAPi中则是进行如下返回:
public IHttpActionResult GetSecond() { return OK(); }
下面我们在控制台中分别来测试这二者在WebHost以及在SelfHost上的差异,我们如何获取其差异呢?我们通过对void方法和http方法在控制台中发出1000个请求来获取其总共花费时间来进行比较。
SelfHost
[HttpGet] public void GetFirst() { StringBuilder stringbuilder = new StringBuilder(); for (int i = 0; i < 20; i++) { stringbuilder.Append("something"); } } [HttpGet] public IHttpActionResult GetSecond() { StringBuilder stringbuilder = new StringBuilder(); for (int i = 0; i < 20; i++) { stringbuilder.Append("something"); } return Ok(); }
在控制台中方法如下:
private const string voidUrl = "http://localhost:8080/api/home/GetFirst"; private const string httpUrl = "http://localhost:8080/api/home/GetSecond"; private static List<TimeSpan> voidTimes = new List<TimeSpan>(); private static List<TimeSpan> httpTimes = new List<TimeSpan>(); static void Main(string[] args) { Console.WriteLine("Start Test...."); for (int i = 0; i < 1000; i++) { voidTimes.Add(getResponse(voidUrl)); Thread.Sleep(10); Console.WriteLine("void Test " + i); } Console.WriteLine("Finished Void Test"); for (int i = 0; i < 1000; i++) { httpTimes.Add(getResponse(httpUrl)); Thread.Sleep(10); Console.WriteLine("http Test " + i); } Console.WriteLine("Finished Http Test"); var voidTotalTime = voidTimes.Sum(t => t.Milliseconds); Console.WriteLine("void方法发出1000个请求总共需要时间:" + voidTotalTime); Console.WriteLine("void方法平均每一个请求需要时间:" + voidTotalTime / 1000.00 + "秒"); var httpTotalTime = httpTimes.Sum(t => t.Milliseconds); Console.WriteLine("http方法发出1000个请求总共需要时间: " + httpTotalTime); Console.WriteLine("http方法平均每一个请求需要时间: " + httpTotalTime / 1000.00 + "秒"); Console.Read(); } static TimeSpan getResponse(string url) { var stopWatch = new Stopwatch(); stopWatch.Start(); var httpClient = new HttpClient(); httpClient.BaseAddress = new Uri(url); var task = httpClient.GetAsync(httpClient.BaseAddress).Result; var result = task.Content.ReadAsAsync(typeof(object)); var timeSpan = stopWatch.Elapsed; stopWatch.Stop(); return timeSpan; }
下面我们来直观演示整个过程:
从上看出似乎由http方法节约一点时间,我们将上述中的方法循环次数,进行如下修改:
for (int i = 0; i < 200000; i++) { stringbuilder.Append("something"); }
这时候我们再来看看结果:
当有二十万条数据时此时时间又多节约一点点。接下来我们再来测试WebHost。
WebHost
在WebHost中我们利用特性来管理请求方法:
[HttpGet] [Route("test/void")] public void GetFirst() { StringBuilder stringbuilder = new StringBuilder(); for (int i = 0; i < 20; i++) { stringbuilder.Append("something"); } } [HttpGet] [Route("test/IHttpActionResult")] public IHttpActionResult GetSecond() { StringBuilder stringbuilder = new StringBuilder(); for (int i = 0; i < 20; i++) { stringbuilder.Append("something"); } return Ok(); }
此时将控制台请求地址进行对应修改即可:
private const string voidUrl = "http://localhost:2531/test/void"; private const string httpUrl = "http://localhost:2531/test/IHttpActionResult";
此时演示结果如下:
此时快了接近一秒。此时我们将数据增加到同样20万时再看看:
此时还是快了1秒。到了这里是不是就算结束了呢,我们再来看看
当我们请求void方法时返回的状态码为如下:
此时利用http来进行响应则是如下:
其返回状态也不同,我们则需要有对应的处理方式。
总结
在演示void方法和http方法时有时也会出现http方法时间比void方法慢的原因,不知是何缘故,理论上来说用HttpResponseMessage来作为响应结果会快一点,因为HttpResponseMessage内置对于一些异常都做了处理并返回对应的状态码而void方法则未做任何处理。但是从另外一个角度看,若我们自定义一套返回的状态码来进行处理也并非不可,个人觉得利用WebAPi内置的HttpResponseMessage响应机制来进行结果响应最佳,期待各位的批评和答案,同时不知上述测试是否合理。当时想到这个问题时也查了相关资料,还真有做过类似测试的,于是借用了一下。

为了方便大家在移动端也能看到我分享的博文,现已注册个人公众号,扫描上方左边二维码即可,欢迎大家关注,有时间会及时分享相关技术博文。
感谢花时间阅读此篇文章,如果您觉得这篇文章你学到了东西也是为了犒劳下博主的码字不易不妨打赏一下吧,让楼主能喝上一杯咖啡,在此谢过了!
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!
本文版权归作者和博客园共有,来源网址:http://www.cnblogs.com/CreateMyself)/欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构