将空字符串绑定到Guid.Empty或避免模型状态错误

时间:2011-01-13 23:39:57

标签: c# asp.net-mvc asp.net-mvc-2 validation model-binding

当我为Guid字段发布带有空字符串“”的表单时,我收到错误“MyGuid字段是必需的”。虽然我没有设置“必需”属性。

//NOT Required   
public Guid MyGuid { get; set; }

模型绑定后,Guid为00000000-0000-0000-0000-000000000000(因为它是默认值)并且这是正确的。但ModelState有上述错误。

如何避免此错误?

其他信息

[Required(AllowEmptyStrings = true)]无效

我不想让Guid可以为空(Guid?),因为这会导致很多额外的代码(检查它是否有值,映射等)

更新

好的,我发现在我的视图模型中对Guid?的更改不会导致比我预期的更多更改(有些调用MyGuid.GetValueOrDefault()或某些检查MyGuid.HasValue并致电MyGuid.Value)。

但是,如果帖子请求没有提供有效的Guid,则添加模型错误的原因是DefaultModelBinder尝试将null绑定到Guid。解决方案是覆盖DefaultModelBinder。并且不会将错误添加到模型状态

public class MyModelBinder : DefaultModelBinder
{
    protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
    {
        if (propertyDescriptor.PropertyType == typeof(Guid) && value == null)
        {
            value = Guid.Empty;
        }
        base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);

    }
}

3 个答案:

答案 0 :(得分:12)

如果字段的类型是Guid(这是一种值类型),那么它必须包含一个值(即使它全为零)。拥有非必需GUID的正确解决方案是使用Guid?(Nullable Guid)。

你不想使用Nullable的原因没有意义;无论你以哪种方式编码“空虚”,你的代码都必须检查它。我认为Nullable实际上通常会让这更容易。

答案 1 :(得分:1)

https://stackoverflow.com/a/31268941/4985705上的答案ASP.NET MVC: types cast in model binding而言 如果需要,以下内容将返回Guid.Empty值或Guid参数。

public class NullableGuidBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(Guid?))
        {
            var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

            string input = valueResult.AttemptedValue;
            if (string.IsNullOrEmpty(input) || input == "0")
            {
                // return null, even if input = 0
                // however, that is dropdowns' "guid.empty")
                // base.BindModel(...) would fail converting string to guid, 
                // Guid.Parse and Guid.TryParse would fail since they expect 000-... format

                // add the property to modelstate dictionary
                var modelState = new ModelState { Value = valueResult };
                bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
                return Guid.Empty;
            }
        }

        return base.BindModel(controllerContext, bindingContext);
    }
}

在控制器中进行如下绑定

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> SelectAction(
        [ModelBinder(typeof(NullableGuidBinder))] Guid? id)
    {
        // your stuff
    }

答案 2 :(得分:0)

在您的应用程序启动事件集中:DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

请记住,除非明确设置,否则不会要求所有值类型。

我同意法比亚诺的观点。 Guid有点怪,Guid.Empty。