Привязать пустую строку к Guid.Empty или избежать ошибки состояния модели - PullRequest
5 голосов
/ 14 января 2011

Когда я отправляю форму с пустой строкой "" для поля 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 пытается связать nullGuid.Решение было бы переопределить 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 ]

12 голосов
/ 14 января 2011

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

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

1 голос
/ 07 июля 2015

в смысле моего ответа https://stackoverflow.com/a/31268941/4985705 на ASP.NET MVC: типы, приведенные к привязке модели , приведенные ниже вернут значения 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
    }
0 голосов
/ 14 января 2011

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

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

Я согласен с Фабиано, хотя.Guid - это немного странно с Guid.Empty.

...