You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET Core控制器式Web API中处理Supabase Postgrest异常?

处理Supabase Postgrest异常的解决方案

当传入非UUID格式的字符串调用接口时,Supabase的Postgrest客户端会抛出PostgrestException(错误码22P02),当前代码未捕获该异常,导致API返回500内部服务器错误,不符合REST规范。以下是几种可行的处理方式:


方式一:控制器内直接捕获异常

在DatabasesController.cs的GetById方法中添加try-catch块,针对特定错误码返回对应HTTP响应:

using Project.Services;
using Project.Models;
using Microsoft.AspNetCore.Mvc;
using Supabase.Postgrest.Exceptions;

namespace Project.Controllers;

[ApiController]
[Route("[controller]")]
public class DatabasesController : ControllerBase
{
    private readonly DatabasesService _databasesService;

    public DatabasesController(DatabasesService databasesService) =>
        _databasesService = databasesService;

    [HttpGet]
    public async Task<List<Database>> GetAll() =>
        await _databasesService.GetAll();

    [HttpGet("{id}")]
    public async Task<ActionResult<Database>> GetById(string id)
    {
        try
        {
            var response = await _databasesService.GetById(id);
            var database = response.FirstOrDefault();

            return database is not null ? database : NotFound();
        }
        catch (PostgrestException ex)
        {
            if (ex.Code == "22P02")
            {
                return BadRequest(new { Message = "无效的UUID格式,请提供正确的UUID字符串" });
            }
            return StatusCode(StatusCodes.Status500InternalServerError, new { Message = "服务器内部错误", Details = ex.Message });
        }
    }
}

方式二:服务层封装结果(解耦控制器与异常处理)

先定义通用结果类(可放在Models目录下):

namespace Project.Models;

public class ServiceResult<T>
{
    public T? Data { get; set; }
    public string? ErrorMessage { get; set; }
    public string? ErrorCode { get; set; }
    public bool IsSuccess => string.IsNullOrEmpty(ErrorMessage);
}

修改DatabasesService.cs的GetById方法,返回封装后的结果:

using Project.Models;
using Supabase;
using Supabase.Postgrest.Exceptions;

namespace Project.Services;

public class DatabasesService
{
    private readonly Client _supabaseClient;

    public DatabasesService(Client supabaseClient)
    {
        _supabaseClient = supabaseClient;
    }

    public async Task<List<Database>> GetAll()
    {
        var result = await _supabaseClient.From<Database>().Get();
        return result.Models;
    }

    public async Task<ServiceResult<List<Database>>> GetById(string id)
    {
        try
        {
            var result = await _supabaseClient
                .From<Database>()
                .Where(x => x.Id == id)
                .Get();
            return new ServiceResult<List<Database>> { Data = result.Models };
        }
        catch (PostgrestException ex)
        {
            return new ServiceResult<List<Database>> 
            { 
                ErrorMessage = ex.Message, 
                ErrorCode = ex.Code 
            };
        }
    }
}

再修改控制器逻辑,根据结果返回响应:

[HttpGet("{id}")]
public async Task<ActionResult<Database>> GetById(string id)
{
    var result = await _databasesService.GetById(id);

    if (!result.IsSuccess)
    {
        if (result.ErrorCode == "22P02")
        {
            return BadRequest(new { Message = "无效的UUID格式,请提供正确的UUID字符串" });
        }
        return StatusCode(StatusCodes.Status500InternalServerError, new { Message = result.ErrorMessage });
    }

    var database = result.Data?.FirstOrDefault();
    return database is not null ? database : NotFound();
}

方式三:全局异常过滤器(推荐多接口场景)

创建全局异常过滤器类(可放在Filters目录下):

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Supabase.Postgrest.Exceptions;

namespace Project.Filters;

public class PostgrestExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        if (context.Exception is PostgrestException ex)
        {
            ObjectResult result;
            switch (ex.Code)
            {
                case "22P02":
                    result = new BadRequestObjectResult(new { Message = "无效的UUID格式,请提供正确的UUID字符串" });
                    break;
                case "404":
                    result = new NotFoundObjectResult(new { Message = "请求的资源不存在" });
                    break;
                default:
                    result = new ObjectResult(new { Message = "服务器内部错误", Details = ex.Message })
                    {
                        StatusCode = StatusCodes.Status500InternalServerError
                    };
                    break;
            }
            context.Result = result;
            context.ExceptionHandled = true;
        }
    }
}

在Program.cs中注册过滤器:

var builder = WebApplication.CreateBuilder(args);

// ... 其他服务注册代码 ...

builder.Services.AddControllers(options =>
{
    options.Filters.Add<PostgrestExceptionFilter>(); // 添加全局异常过滤器
}).AddNewtonsoftJson();

// ... 其他代码 ...

额外优化:提前验证输入格式

在控制器参数上添加正则验证,提前拦截无效UUID,避免走到数据库查询步骤:

[HttpGet("{id}")]
public async Task<ActionResult<Database>> GetById(
    [RegularExpression(@"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$", 
    ErrorMessage = "无效的UUID格式")] string id)
{
    // ... 方法内容 ...
}

内容的提问来源于stack exchange,提问作者not-a

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 08:25:13