[Web API] 如何让 Web API 统一回传格式以及例外处理

本文详细记录了如何在WebAPI中实现统一的数据返回格式和异常处理策略,包括自定义返回模型、过滤器的使用以及异常信息的封装。

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

[Web API] 如何让 Web API 统一回传格式以及例外处理

前言

当我们在开发 Web API 时,一般的情况下每个 API 回传的数据型态或格式都不尽相同,如果你的项目从头到尾都是由你一个人独力完成,那也许还可以说声「阿密陀佛」,但如果是有其他人需要和你共享你的 Api ,而回传的数据格式又不一样,相信是会增加使用者的困扰,也大大增加了程序的复杂度与维护上的难度。所以本篇也纪录一下自己在实作上的经验,一方面留个纪录也希望帮助更多人,废物不多说我们开始吧!

了解架构并实作

原本在找数据时找到这篇 使用Asp.Net MVC打造Web Api (16) – 统一输入/出格式以及异常处理策略,不过发现里面的所用到的方法似乎是 For ASP.NET MVC,而非 Web API (不知道笔者这样认知有没有错误,如果有还麻烦前辈们指教),而本篇的思考模式跟这篇是一样的,只是把它改成 Web API 能用的方法而已。

[]

按照上图所示当使用者请求不同的 API 时,返回页面之前会将数据重新打包后再传回页面给使用者,如此一来用户所看到的数据格式就会是固定的。

1.所以首先我们需要先自定义一个 Model 来当作我们的包装的容器,其类别的定义如下:

public class ApiResultModel
{
    public HttpStatusCode Status { get; set; }
    public object Data { get; set; }
    public string ErrorMessage { get; set; }
}

2.相信写过 ASP.NET MVC 的朋友一定会知道,一般我们会将一些在 Action 中固定的逻辑,利用 Filter 来套用到每一个 Action 上面,例如:Authorize。如果你对 Filter 不是很熟悉可以参考一下网络上前辈所写的文章:[VS2010] ASP.NET MVC with Action Filters。 所以这边我们也需要使用同样的技巧来重新打包我们回传的数据格式,我们先新增一个 ApiResultAttribute.cs 的档案,且继承 System.Web.Http.Filters.ActionFilterAttribute,并且复写 OnActionExecuted 的方法,如下:

public class ApiResultAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
       public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
       {
            base.OnActionExecuted(actionExecutedContext);     
       }
}

3.而 OnActionExecuted 会在 Action 执行之后呼叫,也表示我们将资料送进这个方法里面,接着处理我们主要打包的程序逻辑,程序代码如下:

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
    base.OnActionExecuted(actionExecutedContext);
 
    ApiResultModel result = new ApiResultModel();
 
    // 取得由 API 返回的状态代码
    result.Status = actionExecutedContext.ActionContext.Response.StatusCode;
    // 取得由 API 返回的资料
    result.Data = actionExecutedContext.ActionContext.Response.Content.ReadAsAsync<object>().Result;
    // 重新封装回传格式
    actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.Status, result);
}

4.而为了要让所有的 Web API 都能套用我们自定义的 Filter,所以我们需要到 App_Start → WebApiConfig.cs → Register 来注册全局的 Web API Filter。(注意:若要注册 Web API 的 Filter 需在 WebApiConfig.cs 中注册,而非 FilterConfig.cs 中)

config.Filters.Add(new ApiResultAttribute());

5.重新建置之后我们再重新执行一次原先的 Web API 程序,就会看到回传的格式已经变成我们自定义的格式了:

"Status": 200,
    "Data": [
        {
            "Account": "taxi",
            "Mark": "",
            "Name": "王大明",
            "Telephone": "0986540123",
            "AccountStatus": true
        },
        {
            "Account": "taxi2",
            "Mark": "",
            "Name": "方大同",
            "Telephone": "0922335111",
            "AccountStatus": true
        },
        {
            "Account": "q121234567",
            "Mark": null,
            "Name": "0000",
            "Telephone": "0972334334",
            "AccountStatus": true
        }
    ],
    "ErrorMessage": null

例外处理

前面我们已经将讯息打包成我们要的格式了,不过我们还没确切地去处理有关例外的程序代码,一般当程序发生错误产生例外时,我们当然也希望接收端能知道程序发生错误,进而显示该显示的讯息,而不是活生生地看着程序 Crash 或是停顿,这样将带给你的客户不好的体验,而在 ASP.NET MVC 中也有提供专门处理例外的 ExceptionFilterAttribute,所以接着来看看该如何打包我们的例外讯息吧。

1.新增一个 ApiErrorHandleAttribute.cs 并且继承 System.Web.Http.Filters.ExceptionFilterAttribute,接着复写 OnException 当例外发生时执行的方法,程序代码如下:

public class ApiErrorHandleAttribute : System.Web.Http.Filters.ExceptionFilterAttribute
{
       public override void OnException(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext)
       {
           base.OnException(actionExecutedContext);
       }
}

2.透过 OnException 的方法能让我们捕捉当例外发生时要处理的事情,一般系统我们也会在这边将发生错误的时间、登入的用户以及错误的状况记录下来 (例如:系统事件、存入数据库、写入 .txt 档 … 等),不过这边不是我们讨论的重点,我们先来看看该如何打包我们的例外讯息,程序代码如下:

public override void OnException(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext)
{
    base.OnException(actionExecutedContext);
    
    // 取得发生例外时的错误讯息
    var errorMessage = actionExecutedContext.Exception.Message;
 
    var result = new ApiResultEntity()
    {
        Status = HttpStatusCode.BadRequest,
        ErrorMessage = errorMessage
    };
 
    // 重新打包回传的讯息
    actionExecutedContext.Response = actionExecutedContext.Request
        .CreateResponse(result.Status, result);
}

 

3.而因为程序丢出例外后会先回到 OnActionExcuted 在进到例外的处理,所以我们稍微修改一下原本的 OnActionExcuted 这个方法,让发生例外时就直接跳过不再这边打包我们的讯息,程序代码如下:

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
    // 若发生例外则不在这边处理
    if (actionExecutedContext.Exception != null)
    return;
    
    base.OnActionExecuted(actionExecutedContext);
 
    ApiResultModel result = new ApiResultModel();
 
    // 取得由 API 返回的状态代码
    result.Status = actionExecutedContext.ActionContext.Response.StatusCode;
    // 取得由 API 返回的资料
    result.Data = actionExecutedContext.ActionContext.Response.Content.ReadAsAsync<object>().Result;
    // 重新封装回传格式
    actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(result.Status, result);
}

3.接着我们一样要将此自定义的 Filter 注册到程序当中,所以一样到 App_Start → WebApiConfig.cs → Register 来注册我们的 Filter:

config.Filters.Add(new ApiErrorHandleAttribute());

4.重新建置后,当我们程序发生例外时也会依照我们的格式回传给使用者:

{
    "Status": 400,
    "Data": null,
    "ErrorMessage": "尝试以零除。"
}

总结

就这样我们又成功解决了一个简单的案例,不过这边也需要提醒一下读者,一般在处理例外这边是不会直接将例外讯息回传给用户的,因为如果假设你今天丢出的例外有包含了一些比较敏感的信息,例如:数据库名称或数据表名称…等等,这样一来你的程序就间接的有了漏洞了,所以如果真的要用此程序代码记得后面例外捕捉那边还要在包装一下。

<think>好的,我现在要处理用户关于Web Audio API的询问。用户之前问过Unity WebGL下音频重采样的问题,现在转向Web Audio API,可能是想了解浏览器原生的音频处理方式,或者比较两者的优劣。首先,我需要回忆Web Audio API的基本概念和功能,确保信息准确。 用户可能的需求是什么?他们可能是在开发网页音频应用,需要实处理、合成或分析音频。需要介绍Web Audio API的核心功能、使用场景、基本架构,以及可能的应用示例。考虑到用户之前接触过Unity,可能需要强调Web Audio API与Unity方案的对比,比如性能、兼容性、易用性等方面。 接下来,要组织回答的结构。用户之前的问题回答结构清晰,分步骤说明,这次可能也期望类似的结构。需要先概述Web Audio API,然后讲解节点化架构,再介绍关键模块,接着给出使用步骤和示例,最后注意事项和优势分析。同,用户可能需要代码示例,所以应包含简单的例子,比如加载音频、添加效果等。 需要注意的是,用户可能对音频处理的基础概念有一定了解,但可能需要更具体的API使用指导。因此,在解释各个模块,要简明扼要,突出关键点,如AudioContext、AudioNode的类型和作用。同,提到性能优化和兼容性问题,这对实际开发很重要。 另外,用户之前的问题中提到了内存限制和浏览器兼容性,这里也需要强调Web Audio API同浏览器中的支持情况,以及处理大音频数据的注意事项。可能需要对比Web Audio API与Unity WebGL方案的优缺点,帮助用户做出选择。 检查是否有遗漏的部分。比如,Web Audio API的实分析能力、音频可视化、3D音效支持等高级功能是否得提及。这些功能可能在游戏或交互式应用中非常有用,应该涵盖到。此外,安全限制,如自动播放策略,也是开发中常遇到的坑,需要提醒用户。 最后,确保回答符合之前用户要求的格式:使用中文,结构清晰,分步骤,代码用正确格式,行内公式用$符号。虽然当前问题涉及数学公式,但如果有涉及的地方,比如音频处理算法,可能需要使用正确的LaTeX格式。但根据当前问题,可能需要数学公式,但需保持代码块的正确标记。 总结,回答应包括:概述、架构、关键模块、使用步骤、示例代码、注意事项、优势与应用场景。确保信息准确,结构清晰,满足用户的实际开发需求。</think>以下是关于Web Audio API的详细介绍: 一、基本概念 Web Audio API是浏览器原生提供的音频处理接口,支持: - 音频播放与控制 - 实音频处理 - 音频可视化 - 3D空间音效 - 音频合成与采样 二、节点化架构 $$输入源 \rightarrow 效果器 \rightarrow 输出$$ 所有音频处理通过连接同节点实现,形成音频路由图 三、核心模块 1. AudioContext(音频上下文) ```javascript const audioCtx = new AudioContext(); // 或webkitAudioContext ``` 2. 输入源类型: - `AudioBufferSourceNode`(预加载音频) - `MediaElementAudioSourceNode`(\<audio>元素) - `OscillatorNode`(生成波形) - `MediaStreamAudioSourceNode`(麦克风输入) 3. 常用处理节点: ```javascript const gainNode = audioCtx.createGain(); // 音量控制 const filter = audioCtx.createBiquadFilter(); // 滤波器 const compressor = audioCtx.createDynamicsCompressor(); // 压缩器 ``` 四、典型使用流程 1. 加载音频文件 ```javascript async function loadAudio(url) { const response = await fetch(url); const arrayBuffer = await response.arrayBuffer(); return audioCtx.decodeAudioData(arrayBuffer); } ``` 2. 创建播放链路 ```javascript const source = audioCtx.createBufferSource(); source.buffer = audioBuffer; // 从loadAudio获取 source.connect(gainNode) .connect(filter) .connect(audioCtx.destination); source.start(); ``` 五、高级功能示例 1. 实音频分析(可视化) ```javascript const analyser = audioCtx.createAnalyser(); analyser.fftSize = 2048; const dataArray = new Uint8Array(analyser.frequencyBinCount); function updateVisualizer() { analyser.getByteTimeDomainData(dataArray); requestAnimationFrame(updateVisualizer); } ``` 2. 3D音效定位 ```javascript const panner = audioCtx.createPanner(); panner.setPosition(1, 0, 0); // 设置声源位置(x,y,z) panner.panningModel = 'HRTF'; // 头部相关传递函数 ``` 六、性能优化技巧 1. 使用`OfflineAudioContext`预处理 ```javascript const offlineCtx = new OfflineAudioContext(2, 44100*5, 44100); // 渲染完成后获取AudioBuffer ``` 2. 节点复用策略 - 对重复使用的效果器保持长连接 - 动态节点按需创建/销毁 七、浏览器兼容性 1. 支持情况: - Chrome ≥28 - Firefox ≥25 - Safari ≥14.1 - Edge ≥79 2. 特性检测模式 ```javascript const AudioContext = window.AudioContext || window.webkitAudioContext; ``` 八、安全限制 1. 自动播放策略: - Chrome:需要用户交互后解锁音频 - Safari:默认静音需用户授权 2. CORS限制:跨域音频资源需要正确响应头 九、与Unity WebGL对比 | 特性 | Web Audio API | Unity WebGL | |--------------------|-----------------------|---------------------| | 3D音效 | 原生支持 | 需自定义实现 | | 处理延迟 | ≤50ms | 通常≥100ms | | 内存占用 | 浏览器托管 | 受WebGL内存限制 | | 音频可视化 | 直接支持 | 需回传CPU数据 | 十、典型应用场景 1. 在线音乐播放器(带音效调节) 2. 网页游戏音效系统 3. 语音聊天应用 4. 音频可视化艺术项目 5. 在线音频编辑器 注意事项: 1. 采样率限制:浏览器通常使用硬件支持的采样率(通常44100Hz) 2. 移动端性能:复杂音频图可能导致卡顿 3. 内存泄漏:及断开未使用的节点连接 4. 间精度:使用`audioCtx.currentTime`而非`Date.now()` 扩展学习资源: - MDN文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Audio_API - 官方示例库:https://webaudio.github.io/web-audio-api/ - Web Audio可视化工具:https://web-audio-api-playground.vercel.app/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值