ModelState.IsValid == ложь

Я работаю над страницей входа в систему, и что бы я ни делал, я не могу заставить свой ModelState.IsValid вернуть true, чтобы я мог войти в систему. У меня есть этот код в моем контроллере:

[AllowAnonymous]
[HttpPost]
public ActionResult ValidateLogon(LogonModel logon)
{
    if (ModelState.IsValid)
    {
        StaffModel staff;
        if (staffAuthenticationService.ValidateLogon(logon.UserName, logon.Password, out staff, out logon))
        {
            staffAuthenticationService.SignIn(staff);
            return Json(new { success = true, redirect = "/Home/ModuleIndex", staff = staff });
        }
        ModelState.AddModelError("", "Username and/or Password may be incorrect");
    }

    return Json(new { errors = GetErrorsFromModelState() });   
}

Моя модель входа в систему имеет модель персонала и модель пользователя, моему методу службы validateLogon передается модель входа. Я пытался использовать:

var errors = ModelState.SelectMany(x => x.Value.Errors.Select(z => z.Exception));

и регистрирую ошибки, но я не вижу ошибок, и действительность всегда ложна.

Есть ли лучший способ проверить пользователя, чем с помощью этого объекта словаря, или обходной путь, который я не нашел. Я искал пару часов.

Обновление:

public class LogonModel
{
    [Display(Name = "User")]
    [DataType("UserModel")]
    public UserModel User { get; set; }

    [Display(Name = "Staff")]
    [DataType("StaffModel")]
    public StaffModel Staff { get; set; }

    [Required(ErrorMessage = "Please enter your password")]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [Required(ErrorMessage = "Please enter your username")]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Display(Name = "Terms Of Use Signed")]
    public bool IsTermsOfUseSigned { get; set; }

    [Display(Name = "Privacy Agreement Signed")]
    public bool IsPrivacyAgreementSigned { get; set; }

    [Display(Name= "System Message")]
    public string SystemLoginMessage { get; set; }

    [Display(Name="Version")]
    public string DatabaseVersion { get; set; }

    [Display(Name="Copyright Date")]
    public string CopyrightDate { get; set; }

    [Display(Name="Web Server")]
    public string WebServer { get; set; }

    [Display(Name = "Last Name")]
    [DataType(DataType.Text)]
    [Required(ErrorMessage = "Required")]
    [StringLength(50, ErrorMessage = "Value cannot exceed 50 characters")]
    public string LastName { get; set; }

    [Display(Name = "Date of Birth")]
    [DataType(DataType.Text)]
    [Required(ErrorMessage = "Required")]
    [StringLength(50, ErrorMessage = "Value cannot exceed 50 characters")]
    public string DateOfBirth { get; set; }

    [Display(Name = "Last 4 digits of XXXX SSN")]
    [DataType(DataType.Text)]
    [Required(ErrorMessage = "Required")]
    [StringLength(50, ErrorMessage = "Value must be 4 numbers")]
    public string SsnSuffix { get; set; }

    public int LogonValidationStep { get; set; }
}

Это то, что я вижу в отладчике, когда я наводил курсор на оператор if: IsValid = false, затем, когда я вхожу в функцию, она попадает прямо в сообщение об ошибке.


person Guyute    schedule 19.03.2014    source источник
comment
Можете ли вы опубликовать свой класс LogonModel? Можете ли вы установить точку останова и посмотреть, какая ошибка в состоянии модели возвращает false. Вы можете увидеть, что определенное поле не заполняется, что может потребоваться или что-то в этом роде.   -  person    schedule 20.03.2014
comment
Поставьте точку останова в своем действии и проверьте свойство this.ModelState, особенно ключи и значения. Значения могут не обязательно содержать исключение.   -  person mxmissile    schedule 20.03.2014
comment
Чтобы добавить к этому, вот полезный фрагмент, чтобы получить все ошибки: var errorList = ModelState.Values.SelectMany(v => v.Errors);   -  person Khepri    schedule 20.03.2014
comment
@Guyute Если вы используете MVC 3 или выше, просто используйте SimpleMembrshipProvider, который на самом деле интегрирован с одним из готовых шаблонов для MVC. Что касается ModelState, нам нужно увидеть модель, которую вы передаете своему View, а также вам нужно проверить значение logon, когда результат возвращается из представления, и попытаться найти, что именно нарушает модель.   -  person Leron_says_get_back_Monica    schedule 20.03.2014
comment
Я установил разрыв в строке 131 моего контроллера, и именно здесь я вижу, что мой ModelState.IsValid имеет значение false, когда я нахожусь над ним и вращаю стрелку вниз.   -  person Guyute    schedule 20.03.2014
comment
@Guyute Чтобы получить false форму ModelState.IsValid, одно или несколько ваших полей Required должны быть заполнены неверными данными. Поэтому убедитесь, что: LastName заполнен строкой не длиннее 50 букв, DateOfBirth заполнен и на самом деле является строкой, а не объектом DateTime, SsnSuffix заполнен строкой не длиннее 50 букв. Обязательно сделайте это и попробуйте еще раз. На самом деле просто временно удалите Required из DateOfBirth и отправьте форму, оставив ее пустой, и посмотрите, пройдете ли вы проверку.   -  person Leron_says_get_back_Monica    schedule 20.03.2014
comment
@Leron, вот и все, спасибо, я не хотел включать это обязательное поле в свою модель.   -  person Guyute    schedule 20.03.2014


Ответы (1)


Если ваш чек:

if (ModelState.IsValid)

возвращает false, что, скорее всего, означает, что одно из обязательных полей в вашей модели, используемое в представлении, заполнено неверным результатом. После того, как вы разместили свою модель, поле DateOfBirth показалось наиболее подозрительным, поэтому удаление атрибута Required позволило нам выяснить причину проблемы и временно решить проблему.

С этого момента у вас есть два варианта — просто оставить все как есть (я этого не рекомендую) или продолжить расследование, почему вы не получаете ожидаемые данные для этого поля. Другими словами, не избегайте проблем, а старайтесь их решать и учиться на них.

Если мой пост помог вам, вы также можете принять его как ответ.

person Leron_says_get_back_Monica    schedule 19.03.2014
comment
Спасибо за вашу помощь, мое долгосрочное решение состоит в том, чтобы создать другую модель, которая будет использоваться для процесса восстановления пароля. У нас есть штатные пользователи и нештатные пользователи, и они оба восстанавливают свои пароли, используя один и тот же рабочий процесс, поэтому общая модель пригодится, когда я туда доберусь. Я пытался втиснуть все случаи регистрации в одну модель, просмотр и контроль. а также скрывать и отображать представления по мере выполнения или невыполнения условий. Иногда я думаю, что вы не можете получить все одним махом. Я все еще начинающий программист, поэтому иногда склонен слишком много думать. - person Guyute; 20.03.2014
comment
@Guyute Как я уже писал в своем комментарии к вашему исходному сообщению, действительно стоит использовать встроенные инструменты MVC для членства, такие как SimpleMembershipProvider, Identity или что-то еще, что вы можете найти более подходящим. Они довольно расширяемы и предлагают множество вещей, которые вам придется делать из коробки. И не в последнюю очередь, кривая обучения не так уж велика, поэтому оно того стоит, поскольку это одна из наиболее распространенных задач для каждого разработчика/приложения. - person Leron_says_get_back_Monica; 20.03.2014