当我为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);
}
}
答案 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。