防止 ASP.NET WebAPI 2 将空字符串查询参数视为 null

Prevent ASP.NET WebAPI 2 from treating empty string query parameter as null

我有一个 RESTful 网络服务,使用 ASP.NET WebAPI 2 构建。

我在控制器中有这个方法:

[Route("{DocNum:int}")]
public object Patch(int DocNum, string str = null)
{
    if(str == null)
    {
        //do something when parameter has NOT been passed...
    }
    else
    {
        //do something when parameter has been passed...
    }
}

如果我不传str,在方法里就是null

如果我传str=abc,方法里面就是"abc"

如果我传递str=(空字符串),它在方法中为空。

即ASP.NETWebAPI 2将空字符串查询参数视为null!

似乎是设计使然,但有没有办法将空字符串视为空字符串

HTML中没有null这样的东西。输入有一些值或空值。甚至没有办法仅通过查看查询参数来判断该值是字符串还是数字。

HTML 表单的默认行为是在提交时包含所有字段。因此,即使输入没有值,它仍将作为查询的一部分包含在内。 www.example.com/xxx?str=www.example.com/xxx 都是表示没有为 str 字段输入值的有效语法。

但是您可以包含一个隐藏字段

<input name="IsEmptyString" type="hidden"/>

在您的表单中并使用 JavaScript 根据您用来确定它是空还是空的任何逻辑来设置值。

我发现了这个很棒的解决方案,它是从 复制并改进的。这是web应用程序全局配置中的自定义。

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        //treat query string parameters of type string, that have an empty string value,
        //(e.g. http://my/great/url?myparam=) as... empty strings!
        //and not as null, which is the default behaviour
        //see 
        GlobalConfiguration.Configuration.BindParameter(typeof(string), new EmptyStringModelBinder());

        //...
    }
}

/// <summary>
/// Model binder that treats query string parameters that have an empty string value
/// (e.g. http://my/great/url?myparam=) as... empty strings!
/// And not as null, which is the default behaviour.
/// </summary>
public class EmptyStringModelBinder : System.Web.Http.ModelBinding.IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, System.Web.Http.ModelBinding.ModelBindingContext bindingContext)
    {
        var vpr = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (vpr != null)
        {
            //parameter has been passed
            //preserve its value!
            //(if empty string, leave it as it is, instead of setting null)
            bindingContext.Model = vpr.AttemptedValue;
        }

        return true;
    }
}