【问题标题】:ASP.NET MVC 3 with JsonResult: ModelState is always valid带有 JsonResult 的 ASP.NET MVC 3:ModelState 始终有效
【发布时间】:2012-09-28 04:12:01
【问题描述】:

我正在尝试使用 ModelState 验证表单,但我的 ModelState 始终显示为有效。例如:当我尝试使用相同的 SSN 保存 2 人 formModel 时,ModelState 返回有效。我正在使用 IValidatableObject 来验证我的表单模型。有什么想法我可能会出错吗?我正在使用 .Net 4.0 和 MVC 3。

public JsonResult LoadOccupantsDetailedInformation()
{
    //Load the personsFormModel with data
    return new JsonpResult(personsFormModel, JsonRequestBehavior.AllowGet);
}

[HttpPost]
public ActionResult SaveOccupantsDetailedInformation(
PersonsFormModel personsFormModel)
    {
//This line is always returning true even if I pass 2 persons with the same ssn
        if (ModelState.IsValid == false)
        {
            var errorList = ModelState.ToDictionary(
                      kvp => kvp.Key,
                      kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()
                );
            return Json(new { Errors = errorList });
        }
        //Save the data in personsFormModel to database
        return Json(new JsonResultViewModel { Success = true });
    }


public partial class PersonsFormModel : List<PersonFormModel>, IValidatableObject
{
    public IEnumerable<System.ComponentModel.DataAnnotations.ValidationResult> Validate(
    ValidationContext validationContext)
    {
        var validationResults
            = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
        if (this.SSNs.Count() > this.SSNs.Distinct().Count())
        {
            validationResults.Add(new System.ComponentModel.DataAnnotations.ValidationResult(
            "All the persons in the household should have a unique SSN\\ITIN number",
                new[] { "SSN" }));
        }
        return validationResults;
    }
    private IEnumerable<string> SSNs
    {
        get
        {
            return this.Select(element => element.SSN);
        }
    }
}
    public class PrequalifyOccupantListPersonDetailedFormModel
{
    [Required(ErrorMessage = "SSN is required")]
    public string SSN { get; set; }
}

【问题讨论】:

  • 我通过手动调用 ValidateViewModel(personsFormModel, this); 解决了这个问题。在检查 ModelState 是否有效之前,在 SaveOccupantsDetailedInformation 控制器操作中。我从 stackoverflow.com 的一个问题中得到了这个函数。

标签: asp.net-mvc modelstate


【解决方案1】:

我写了一个测试来验证你的验证,它看起来不错。

        [Test]
        public void Should_validate_person_form_model()
        {
            var input = new PersonsFormModel();
            input.Add(new PersonFormModel { SSN = "33" });
            input.Add(new PersonFormModel { SSN = "33" });
            _controller.ViewData.ModelState.Clear();

            var results = new List<ValidationResult>();

            bool isValid = Validator.TryValidateObject(input,
                new ValidationContext(input, null, null),
                results,true);

            Assert.IsTrue(!isValid, "Cannot have duplicates.");
        }

所以要么它没有被调用,要么你的数据是有效的。

要测试前者,您是否可以在 Validate 中设置一个断点并确认它被击中。

要测试后者,您能否提供发布的确切数据和涉及的完整模型。

【讨论】:

  • 是的,我已经编写了一个测试用例并且工作正常,但是当从视图调用保存控制器操作时,没有调用 Validate 方法。为了解决这个问题,我们必须将 PersonsFormModel 更改为不从 List 继承,并将 List 作为 UI 视图中的数组传递。我不再需要调用 ValidateViewModel(personsFormModel, this);保存 FormModel 时。
  • @AjitGoel 所以你还需要其他什么,或者它是否已排序?
  • 另请注意,如果模型由于数据注释所需的属性而无效,则表示它不会调用验证器,但会返回无效。
  • 部分类的其余部分是什么?
  • 是的,鸽子,我已经解决了。我已经在下面发布了正确的答案
【解决方案2】:

这就是我解决问题的方法:

***Controller:***
public JsonResult LoadOccupantsDetailedInformation()
{
    //Load the personsFormModel with data
    return new JsonpResult(personsFormModel, JsonRequestBehavior.AllowGet);
}

[HttpPost]
public ActionResult SaveOccupantsDetailedInformation(
PersonsFormModel personsFormModel)
    {
//This line is always returning true even if I pass 2 persons with the same ssn
        if (ModelState.IsValid == false)
        {
            var errorList = ModelState.ToDictionary(
                      kvp => kvp.Key,
                      kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()
                );
            return Json(new { Errors = errorList });
        }
        //Save the data in personsFormModel to database
        return Json(new JsonResultViewModel { Success = true });
    }

***Model:***
public class PersonsFormModel : IValidatableObject
{
    public PersonsFormModel()
    {
        this.Instance = new List<PersonFormModel>();
    }

    public List<PrequalifyOccupantListPersonFormModel> Instance { get; set; }

    public void Add(PersonFormModel personFormModel)
    {
        Instance.Add(personFormModel);
    }

    public IEnumerable<System.ComponentModel.DataAnnotations.ValidationResult> Validate(
    ValidationContext validationContext)
    {
        var validationResults
            = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
        if (this.SSNs.Count() > this.SSNs.Distinct().Count())
        {
            validationResults.Add(new System.ComponentModel.DataAnnotations.ValidationResult(
            "All the persons in the household should have a unique SSN\\ITIN number",
                new[] { "SSN" }));
        }
        return validationResults;
    }
    private IEnumerable<string> SSNs
    {
        get
        {
            return Instance.Select(element => element.SSN);
        }
    }
}

public class PersonFormModel
{
    [Required(ErrorMessage = "SSN is required")]
    public string SSN { get; set; }
}

View: 

// Note, I am passing the "Instance" here. 

 var postData = JSON.stringify({ Instance: list });

            RealPage.DataManager.POST({
                url: "/Approval/SaveOccupantsDetailedInformation"
                , data: postData
                , success: function (data) {
                    if (data && data.Success) {

                    } 
                }
            }); 

【讨论】:

    猜你喜欢
    • 2011-12-31
    • 1970-01-01
    • 2011-02-09
    • 2019-10-24
    • 1970-01-01
    • 1970-01-01
    • 2015-07-09
    • 2017-05-30
    • 1970-01-01
    相关资源
    最近更新 更多