【问题标题】:C#, Valid ModelState fails .isValidC#,有效的 ModelState 失败 .isValid
【发布时间】:2012-04-01 13:38:15
【问题描述】:

C# 有效的 ModelState 失败 .isValid

搜索控制器

//
// GET: /Search/Create
public ActionResult Create()  { return View();  } 

//
// POST: /Search/Create
[HttpPost]
public ActionResult Create(Search search)
{
    search.Created = DateTime.Now;

    search.SearchSet = "test data";
    search.URLParameter = 1432567389;

    if (ModelState.IsValid)
    {
        _db.Searchs.Add(search);
        _db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(search); 
}

搜索类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace TalentProfile.Models
{
    public class Search
    {
        public int Id { get; set; }
        [Required]
        public int URLParameter { get; set; }
        [Required, MaxLength(50, ErrorMessage = "Client must be 50 characters or less")]
        public string Client { get; set; }
        [DataType(DataType.MultilineText), StringLength(150, ErrorMessage = "{0} must be {1} characters or less")]
        public string Notes { get; set; }
        [Required]
        public string SearchSet { get; set; }
        [Required]
        public DateTime Created { get; set; }
    }
}

如果我在调试中运行,类中的所有字段都已正确设置,但它会失败 ModelState.IsValid。如果我深入了解ModelState.IsValid,这是错误的。进一步深入我发现错误“SearchSet 字段是必需的”。 SearchSet 字段正确设置为“测试数据”。如果我删除了ModelState.IsValid,请检查保存到数据库是否成功。

如果字段包含有效数据,为什么我会收到“必填字段”错误。

人才控制器

//
// GET: /Talent/Create
public ActionResult Create()
{
    return View();
}

//
// POST: /Talent/Create
[HttpPost]
public ActionResult Create(Talent talent)
{
    talent.Modified = talent.Created = DateTime.Now;

    if (ModelState.IsValid)
    {
        _db.Talents.Add(talent);
        _db.SaveChanges();
        CreatePhoto(talent.Id);
        return RedirectToAction("Index");
    }

    return View(talent);
}

更新:搜索控制器和创建视图

//
// GET: /Search/Create
public ActionResult Create()
{ 
    Search search = new Search();
    search.SearchSet = "test Data";
    return View(search);
}

//
// POST: /Search/Create
[HttpPost]
public ActionResult Create(Search search)
{
    search.Created = DateTime.Now;

    search.URLParameter = 1435267836;

    if (ModelState.IsValid)
    {
        _db.Searchs.Add(search);
        _db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(search);
}

观点:@Html.HiddenFor(model => model.SearchSet)

【问题讨论】:

  • +1 为命名空间 TalentProfile.Models :) 听起来你正在为时装秀做一个网站...

标签: c# asp.net-mvc


【解决方案1】:

这里有几点需要注意:

1) 在值类型上放置Required 属性是没有意义的。值类型必须始终包含一个值,它们不能为空。因此,Required 将始终为它们传递。

具体来说,DateTime 是一种值类型。此外,您的 UrlParameter 是一个 int,它也是一个值类型。它总是至少包含一个默认值。必需是多余的。

2) 正如其他人所说,ModelState 仅在数据绑定期间设置。数据绑定仅在调用方法之前发生,或者在调用 UpdateModel 或 TryUpdateModel 时发生。无论您是否有其他错误,如果您没有调用 UpdateModel 或 TryUpdateModel,您都无法更新模型并期望 ModelState 反映更改。

3) 客户端已按要求设置,但您似乎没有设置它。因此,如果您设置 Client 和 SearchSet 然后执行 TryUpdateModel(search) 它应该是有效的。

4) Talent 之所以有效,是因为,就像在搜索中一样,talent.Modifiedtalent.CreatedDateTimes 并且不可为空,因此即使您没有设置值,它们也永远不会失败验证(请参阅你自己,删除分配,看看它是如何验证的)。您在 Talent 上可能拥有的任何其他必填字段也可能是值类型。

【讨论】:

  • 是的,伙计,我在上次发帖后得出了同样的结论。当表单回发到 POST 操作时,会创建一个 Search 对象。 Created 和 URLParameter 是 DateTime,int 字段不可为空,默认设置为 01/01/0001 和 0。 SearchSet 是一个默认为 null 的字符串,因此 ModelState 在 SearchSet 上失败。深入到 ModleState 显示它只检查字符串字段(Client、Notes 和 SearchSet),在视图中设置了 Client 和 Notes。这就是为什么您可以在 POST 操作中设置 DateTime 和 int 但不能设置字符串字段的原因。
  • 在 GET 操作中向视图传递 SearchSet 字段设置为非空值的 Search 对象,然后使用 @Html.HiddenFor 公开 SearchSet 可以解决问题。使用修改后的代码查看更新后的帖子。您对Required 属性提出了一些好处,我会重新考虑这些,特别是因为我将在代码中设置 SearchSet、URLParameter 和 Created 的值。
【解决方案2】:

ModelState 在模型绑定期间被解析,因此传递给CreateSearch 对象必须设置SearchSet 值。 IE。如果在模型绑定期间值为空,则在控制器中设置 SearchSet 不会使模型有效。

【讨论】:

    【解决方案3】:

    使用 TryUpdateModel(搜索);在您的 ModelState 检查之前。所以应该是:

    [HttpPost]
    public ActionResult Create(Search search)
    {
        search.Created = DateTime.Now;
        search.SearchSet = "test data";
        search.URLParameter = 1432567389;
    
        TryUpdateModel(search);
    
        if (ModelState.IsValid)
        {
            _db.Searchs.Add(search);
            _db.SaveChanges();
            return RedirectToAction("Index");
        }
    
        return View(search); 
    }
    

    【讨论】:

    • TryUpdateModel(搜索);没有任何区别。 .isValid 仍然失败。见我的其他 cmets。相同的代码适用于另一个控制器。
    【解决方案4】:

    MVC 运行时在执行您的操作之前已经验证了模型,并且在您在操作中本地设置参数后它没有重新验证它。

    所以我们的想法是你在其中发布一个包含搜索模型的帖子,例如从一个 html 表单中,MVC 在开始你的操作之前检查有效性,所以你不必:)

    【讨论】:

    • 查看对 friism 的评论。我的视图是 Talent 和 Search Create 视图的 Html 表单。天赋有效,搜索失败。您有搜索操作的建议代码吗?
    • HELLO MODERATOR、friism、Mystere Man 和 appclay 都为答案做出了贡献。为什么我只能将其中一个标记为答案,这三个都是答案的一部分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    • 2015-11-23
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多