【问题标题】:MVC 3 empty query string parameter value is bound as an empty string rather than nullMVC 3空查询字符串参数值绑定为空字符串而不是null
【发布时间】:2012-06-13 20:52:50
【问题描述】:

我有以下几点:

这个动作:

public virtual ActionResult Search(string search, string sort)
{
...
}

使用空查询字符串参数从该 url 调用:

http://myurl.com/mycontroller/search?search=&sort=

现在我的理解是,从 MVC 2 开始,DefaultModelBinder 会将这些值保留为空值。但是,我发现它们实际上设置为空字符串。这实际上是预期的行为吗?这在任何地方都有记录吗?

谢谢

【问题讨论】:

  • 您是否以某种方式覆盖了默认模型绑定器?您是否添加了自定义模型绑定器?

标签: asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-2 defaultmodelbinder


【解决方案1】:

是的,默认行为是将空字符串设置为 null,但可以通过更改 ConvertEmptyStringToNull = false; 来覆盖它

true 如果在表单中回发的空字符串应该转换为 null
否则为假。 默认值为 true

msdn

就像这段代码:

public class SimpleArrayModelBinder : DefaultModelBinder 
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    {
        if (bindingContext.ModelType == typeof(string)) 
        {
            var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            bindingContext.ModelMetadata.ConvertEmptyStringToNull = false;
            if (value == null || value.AttemptedValue.IsNullOrEmpty())
                return "";
            else
                return value.AttemptedValue;
        }
    }
}

另一种更改默认行为的方法是使用模型中属性上方的ConvertEmptyStringToNull 属性。

示例:

public class Person
{
    [DisplayFormat(ConvertEmptyStringToNull = false)]
    public string Lastname { get; set; }
    ...
}

Blog

【讨论】:

  • 好的,我想这就是我迷路的地方。 msdn.microsoft.com/en-us/library/… 这里的文档说这些空字符串被转换为 null。我错过了什么?
  • 我已经读过这几遍了,但也许我只是误解了它。它说“如果在表单中回发的空字符串应转换为 null,则为 true;”我读到传递true(这是默认值)会将空字符串转换为null,而不是相反。
  • 我发现当您的操作需要简单类型时,这并不适用。
  • @tribus。 “这不适用”是什么意思?
  • 将空字符串设置为 null 的默认行为似乎只适用于模型是复杂类型的情况。对于简单类型,从不检查 ModelMetadata.ConvertEmptyStringToNull 属性。
【解决方案2】:

查看 DefaultModelBinder 的源代码后,我发现只有在绑定的模型是复杂模型时才会检查 ModelMetadata.ConvertEmptyStringToNull 属性。对于在操作中公开的原始类型,值按原样检索。对于我原始问题中的示例,这将是一个空字符串。

来自 DefaultModelBinder 源

        // Simple model = int, string, etc.; determined by calling TypeConverter.CanConvertFrom(typeof(string))
        // or by seeing if a value in the request exactly matches the name of the model we're binding.
        // Complex type = everything else.
        if (!performedFallback) {
            bool performRequestValidation = ShouldPerformRequestValidation(controllerContext, bindingContext);
            ValueProviderResult vpResult = bindingContext.UnvalidatedValueProvider.GetValue(bindingContext.ModelName, skipValidation: !performRequestValidation);
            if (vpResult != null) {
                return BindSimpleModel(controllerContext, bindingContext, vpResult);
            }
        }
        if (!bindingContext.ModelMetadata.IsComplexType) {
            return null;
        }

        return BindComplexModel(controllerContext, bindingContext);
    }

据我所知,ModelMetadata.ConvertEmptyStringToNull 仅在绑定复杂类型时适用。

【讨论】:

    【解决方案3】:

    ModelMetadata.ConvertEmptyStringToNull 在将值绑定到作为属性位于Model 内的字符串时,此属性将产生影响。

    例如。

    public class Employee
    {
       public string First{get;set;}
       public string Last{get;set;}
    }
    

    使用 ModelMetadata.ConvertEmptyStringToNull = true(默认)

    当请求不包含这些项目的值时,您将看到 FirstLastnull

    使用 ModelMetadata.ConvertEmptyStringToNull = false

    当请求包含具有空值的参数时,属性将为“”。如果请求本身不包含参数,那么值仍然是null

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-12
      • 2013-07-01
      • 2012-12-29
      • 1970-01-01
      • 2015-11-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多