2

平台: Windows 7 Ultimate
IDE: Visual Studio 2010 Ultimate
Web 环境: ASP.NET MVC 2
数据库: SQL Server 2008 R2 Express
数据访问: Entity Framework 4
表单验证: DataAnnotations
示例应用程序: Wrox Pro ASP.NET MVC 2 的 NerdDinner
书籍: Wrox Professional MVC 2
第 1 章的问题 - 部分: “将验证和业务规则逻辑与模型类集成”(第 33 至 35 页)

错误概要: NerdDinner 表单验证错误,带有 DataAnnotations 和 db null。

当数据库字段设置为不允许空值时,示例代码中的 DataAnnotations 不起作用。

书中的代码和从 codeplex 下载的示例代码会发生错误。

帮助!对此我真的很沮丧!!我不敢相信这么简单的事情根本行不通???

重现错误的步骤:

  1. 将数据库字段设置为不允许 NULL (见图)
  2. 将 NerdDinnerEntityModel 晚餐类字段的 Nullable 属性设置为 false (见图)
  3. 为 Dinner_Validation 类添加 DataAnnotations (代码 A)
  4. 创建晚餐存储库类(代码 B)
  5. 将 CREATE 操作添加到 DinnerController (代码 C)
  6. 这是张贴前的空白表格(见图)
  7. 发布应由 Dinner_Validation 类 DataAnnotations 截获的空白表单时会发生此空错误。注意错误消息说“此属性不能设置为空值。WTH??? (见图)
  8. 下一个错误发生在编辑过程中。这是编辑控制器操作(代码 D)
  9. 这是“编辑”表单,故意输入错误以测试晚餐验证数据注释(见图)
  10. 发布带有空白表单字段的编辑表单时再次发生错误。发布请求应该被 Dinner_Validation 类 DataAnnotations 拦截。相同的空条目错误。么么哒???(见图)

请参阅以下位置的屏幕截图:

http://www.intermedia4web.com/temp/nerdDinner/StackOverflowNerdDinnerQuestionshort.png

代码 A:

    [MetadataType(typeof(Dinner_Validation))]
    public partial class Dinner { }

    [Bind(Include = "Title, EventDate, Description, Address, Country, ContactPhone, Latitude, Longitude")] 
    public class Dinner_Validation
    {
        [Required(ErrorMessage = "Title is required")]
        [StringLength(50, ErrorMessage = "Title may not be longer than 50 characters")]
        public string Title { get; set; }

        [Required(ErrorMessage = "Description is required")]
        [StringLength(265, ErrorMessage = "Description must be 256 characters or less")]
        public string Description { get; set; }

        [Required(ErrorMessage="Event date is required")]
        public DateTime EventDate { get; set; }

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

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

        [Required(ErrorMessage = "Contact phone is required")]
        public string ContactPhone { get; set; }

        [Required(ErrorMessage = "Latitude is required")]
        public double Latitude { get; set; }

        [Required(ErrorMessage = "Longitude is required")]
        public double Longitude { get; set; }
    }

代码 B:

    public class DinnerRepository
    {
        private NerdDinnerEntities _NerdDinnerEntity = new NerdDinnerEntities();

        // Query Method
        public IQueryable<Dinner> FindAllDinners()
        {
            return _NerdDinnerEntity.Dinners;
        }

        // Query Method
        public IQueryable<Dinner> FindUpcomingDinners()
        {
            return from dinner in _NerdDinnerEntity.Dinners
                   where dinner.EventDate > DateTime.Now
                   orderby dinner.EventDate
                   select dinner;
        }

        // Query Method
        public Dinner GetDinner(int id)
        {
            return _NerdDinnerEntity.Dinners.FirstOrDefault(d => d.DinnerID == id);

        }

        // Insert Method
        public void Add(Dinner dinner)
        {
            _NerdDinnerEntity.Dinners.AddObject(dinner);
        }

        // Delete Method
        public void Delete(Dinner dinner)
        {
            foreach (var rsvp in dinner.RSVPs)
            {
                _NerdDinnerEntity.RSVPs.DeleteObject(rsvp);
            }

            _NerdDinnerEntity.Dinners.DeleteObject(dinner);
        }

        // Persistence Method
        public void Save()
        {
            _NerdDinnerEntity.SaveChanges();
        }
    }

代码 C:

        // **************************************
        // GET: /Dinners/Create/
        // **************************************
        public ActionResult Create()
        {
            Dinner dinner = new Dinner() { EventDate = DateTime.Now.AddDays(7) };
            return View(dinner);
        }

        // **************************************
        // POST: /Dinners/Create/
        // **************************************
        [HttpPost]
        public ActionResult Create(Dinner dinner) {
            if (ModelState.IsValid) 
            {               
                dinner.HostedBy = "The Code Dude";
                _dinnerRepository.Add(dinner);
                _dinnerRepository.Save();
                return RedirectToAction("Details", new { id = dinner.DinnerID });
            }
            else
            {
                return View(dinner);   
            }
        }

代码 D:

        // **************************************
        // GET: /Dinners/Edit/{id}
        // **************************************
        public ActionResult Edit(int id)
        {
            Dinner dinner = _dinnerRepository.GetDinner(id);
            return View(dinner);
        }

        // **************************************
        // POST: /Dinners/Edit/{id}
        // **************************************
        [HttpPost]
        public ActionResult Edit(int id, FormCollection formValues)
        {
            Dinner dinner = _dinnerRepository.GetDinner(id);
            if (TryUpdateModel(dinner)){
                _dinnerRepository.Save();
                return RedirectToAction("Details", new { id=dinner.DinnerID });
            }
            return View(dinner);
        }

我已经向 Wrox 和其中一位作者发送了帮助请求,但没有收到任何人的回复。由于这些错误,本书的读者甚至无法继续完成第 1 章的其余部分。即使我从 Codeplex 下载了最新版本,它仍然有相同的错误。有人可以帮助我并告诉我需要修复什么吗?谢谢 - 埃德。

4

2 回答 2

2

终于找到了这本书的Wrox论坛有答案。答案实际上是令人惊讶的。它与 Visual Studio 2010 中的调试器有关。

基本上只需按 F5 继续,一切正常。

这是论坛主题的链接,其中包含更多答案: http:
//p2p.wrox.com/book-professional-asp-net-mvc-2/79788-constraintexception-unhandled-user-code.html#post259245

于 2010-08-15T01:35:13.810 回答
2

工具 -> 选项 ->(展开)调试 ->(常规)启用异常助手。

这只是 Visual Studio 试图提供帮助!:) 一开始也吓到我了……我以为代码有什么问题。是的,只需恢复执行,一切都会好起来的。验证内部将捕获异常(this 以及其他,例如转换、范围等)并将其记录在 ModelState.Errors 集合中。

于 2010-12-23T16:52:14.633 回答