ASP.NET Core 将 Null 参数传递给控制器端点

问题描述 投票:0回答:2

使用模型绑定器可以将 NULL 复杂类型传递到控制器端点。

该解决方案并不适用于所有控制器端点,重建模型也不是直截了当的。

在 ASP.NET Core 中传递 NULL 复杂类型参数是否有更好的解决方案?

此功能使用 .NET Standard 按预期工作(允许 NULL),无需任何修改。

使用以下

IModelBinder
IModelBinderProvider

public class NullModelBinderProvider : IModelBinderProvider
{
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (context.Metadata.ModelType == typeof(BreakSize))
            {
                return new BinderTypeModelBinder(typeof(NullModelBinder));
            }

            return null;
        }
}

public class NullModelBinder : IModelBinder
{
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
                throw new ArgumentNullException("bindingContext");
            // If null than pass null to the controller - this works
            if (bindingContext.HttpContext.Request.Form.ContainsKey(bindingContext.FieldName) && string.IsNullOrEmpty(bindingContext.HttpContext.Request.Form[bindingContext.FieldName]))
                bindingContext.Result = ModelBindingResult.Success(null);
            else
                
                bindingContext.Result = ModelBindingResult.Success(new BreakSize()); // Todo set values for BreakSize from the form

            return Task.CompletedTask;
        }
}

c# asp.net-core .net-core model-binding
2个回答
0
投票

假设您的控制器操作如下所示:

public void Endpoint(BreakSize size) { /**/ }

ASP.NET Core 默认执行验证,即它会检查 null 并抛出 400。如果你想允许 null,你需要使用将其标记为 nullable:

public void Endpoint(BreakSize? size) { /**/ }

public void Endpoint([MaybeNull] BreakSize size) { /**/ }

0
投票
  1. 可选参数:您的第一道防线

使用 Nullable 或 T? 使这些复杂类型参数可选。这允许空值通过而无需模型绑定器手术。 示例:

public IActionResult MyAction([FromBody] BreakSize? breakSize)
{
    // Handle null or non-null breakSize like a boss
}
  1. 查询参数:偷偷摸摸的回避

对于那些可选的数据忍者,考虑查询参数而不是正文参数。他们自然地拥抱空值。 示例:

public IActionResult MyAction([FromQuery] BreakSize breakSize)
{
// Null or not, you got this
}
  1. 自定义模型绑定:当您需要亲自动手时

创建自定义模型绑定器以显式处理空值,从而使您能够对绑定过程进行精细控制。 示例:

public class BreakSizeModelBinder : IModelBinder
  {
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
      // Implement logic to handle null values and bind properties from request
    }
  }
  1. 动作过滤器:看门人

使用操作过滤器在请求到达操作方法之前拦截请求并修改模型。非常适合自定义空值处理和其他预处理恶作剧。 示例:

public class NullBreakSizeFilter : ActionFilterAttribute
  {
    public override void OnActionExecuting(ActionExecutingContext context)
    {
      // Check for null BreakSize parameter and handle it
    }
  }
  1. 价值提供者(ASP.NET Core 6+):新来的孩子

利用值提供程序进行声明性空值处理,通过依赖注入提供灵活性。 示例:

public IActionResult MyAction([FromServices] IValueProvider<BreakSize> valueProvider)
  {
    BreakSize breakSize = valueProvider.GetValue(bindingContext);
    // Handle null or non-null breakSize
  }

空值的频率:如果空值很常见,可选参数或查询参数可能会更简单。 所需的控制级别:自定义模型绑定或操作过滤器提供更精细的控制。 依赖注入:价值提供者可以作为服务注入以获得更大的灵活性。 可读性和可维护性:选择一种对未来开发人员来说清晰且易于理解的方法。

© www.soinside.com 2019 - 2024. All rights reserved.