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

如何让API自动解析GET路由参数为自定义领域对象?

可以将领域对象用作API GET路由参数吗?

完全可以,你可以通过自定义模型绑定器或类型转换器实现字符串到自定义Id领域对象的自动转换,从而在一处统一完成值的验证,避免重复代码。以下是具体实现方案:

方案一:使用自定义模型绑定器(推荐API场景)

模型绑定器能更好地处理参数转换时的错误,并将验证错误反馈到ModelState,方便返回标准化的错误响应。

1. 实现自定义模型绑定器

创建一个实现IModelBinder的类,处理字符串到Id对象的转换及异常捕获:

public class IdModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
            throw new ArgumentNullException(nameof(bindingContext));

        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (valueProviderResult == ValueProviderResult.None)
            return Task.CompletedTask;

        bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
        string rawValue = valueProviderResult.FirstValue;

        try
        {
            var id = new Id(rawValue);
            bindingContext.Result = ModelBindingResult.Success(id);
        }
        catch (ArgumentNullException ex)
        {
            bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, ex.Message);
        }
        catch (ValidationException ex)
        {
            bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, ex.Message);
        }

        return Task.CompletedTask;
    }
}

2. 关联模型绑定器与Id类

通过[ModelBinder]属性标记Id类,指定使用自定义绑定器:

[ModelBinder(BinderType = typeof(IdModelBinder))]
public class Id
{
    public string Value { get; }

    public Id(string value)
    {
        if (string.IsNullOrEmpty(value))
        {
            throw new ArgumentNullException("value");
        }

        if (value.Length > 10)
        {
            throw new ValidationException("Invalid length");
        }

        Value = value.Trim();
    }
}

3. 修改API动作

直接将参数类型改为Id,并校验ModelState:

public async Task<IActionResult> CancelOnlineMeeting(Id id)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    // 业务逻辑:使用id.Value
    return Ok($"Processing cancellation for meeting ID: {id.Value}");
}

方案二:使用类型转换器

如果不需要精细的错误反馈,类型转换器是更简洁的选择:

1. 实现类型转换器

public class IdTypeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string strValue)
        {
            return new Id(strValue);
        }
        return base.ConvertFrom(context, culture, value);
    }
}

2. 标记Id类

添加[TypeConverter]属性指定转换器:

[TypeConverter(typeof(IdTypeConverter))]
public class Id
{
    // 原构造函数和属性不变
}

3. 使用API动作

同样直接使用Id作为参数即可,不过转换异常会直接抛出,需要全局异常处理来捕获并返回响应。

核心优势

  • 统一验证:所有使用Id参数的API动作都会自动应用构造函数中的验证逻辑,无需重复编写。
  • 领域驱动设计:将验证逻辑封装在领域对象内部,符合DDD的设计原则,保持业务逻辑的内聚性。
  • 代码简洁:API动作无需再处理字符串验证,专注于业务逻辑实现。

内容的提问来源于stack exchange,提问作者Sam Jones

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 05:35:02