2011-01-13 3 views
4

Когда я отправляю форму с пустой строкой «» для поля Guid, я получаю сообщение об ошибке «Поле MyGuid обязательно». хотя я не задал атрибут «Обязательный».Привязать пустую строку к Guid.Empty или избежать ошибки состояния модели

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

после модели связывания с Guid является 00000000-0000-0000-0000-000000000000 (потому что это значение по умолчанию), и это правильно. Но ModelState имеет указанную ошибку.

Как я могу избежать этой ошибки?

Дополнительная информация:

[Required(AllowEmptyStrings = true)] не помогает

Я не хочу, чтобы сделать Nullable Guid (Guid?), так как это привело бы к много дополнительного кода (проверка, если это имеет значение , отображение и так далее)

Update:

Хорошо, я понял, что изменения в 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

Есть код, который проверяет, является ли Guid 'DefaultValue'? Имеет смысл проверять значение null/value, чем проверять 'DefaultValue'.И сохранение «DefaultValue» вместо нулевого значения просто путается - это эквивалент сохранения «пустой строки» вместо «». –

+0

Да У меня есть службы и DAO, которые проверяют Guid.Empty. Гиды, которые я использую здесь, предназначены для получения данных или установки ссылок. Я никогда не сохраняю значение по умолчанию Guid – Fabiano

ответ

11

Если тип поля Guid (который является типом значения), то оно должно содержать значение (даже если это все нули). Правильное решение иметь необязательный GUID - использовать Guid? (Nullable Guid).

Ваши причины не желать использовать Nullable не имеют смысла; независимо от того, каким образом вы собираетесь кодировать «пустоту», ваш код должен будет проверить его. Я бы сказал, что Nullable на самом деле делает это проще, в общем.

+0

Спасибо за ваш ответ. Мой код уже правильно обрабатывает по умолчанию Guid (если он вообще должен обрабатывать его). Изменение его на другой тип требует больших изменений. И у меня есть несколько не требуемых инструкций в разных ViewModels. Разве не существует способа сообщить модулю-переплету игнорировать ошибки при попытке привязать «» к Guid? – Fabiano

+3

@Fabiano: Если ваш код обрабатывает GUID всех нулей как специальное значение «null», хотя, по общему признанию, это может работать по большому счету, я бы счел его довольно хакивым и запаха кода. Будущие сторонники вашего кода не могут сказать из типа свойства, что он может содержать это волшебное значение со специальным значением. Если, с другой стороны, вы используете 'Guid?', То сразу же очевидно, что это может быть «null», и что это значит. Поэтому я бы сказал, что изменения, необходимые для вашего кода для размещения типа Nullable, будут стоить того. – Timwi

+0

Хорошо, я сделал несколько тестов с изменением Guids to Guid? Кажется, что он работает с некоторыми изменениями в коде для просмотраModel.MyGuid.GetValueOrDefault() – Fabiano

0

В вашем приложении начало набора событий: DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

Помня об этом, все типы значений не требуются, если они явно не установлены так.

Я согласен с Фабиано. Гид - немного урод с его Гидом.

+0

к сожалению это не помогает – Fabiano

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 
    }