代码之家  ›  专栏  ›  技术社区  ›  Major Productions

如何使用数据注释进行MVC2/EF4实体集合验证?

  •  1
  • Major Productions  · 技术社区  · 14 年前

    我终于克服了一个障碍,现在可以成功地创建新的模型数据了。现在又有一个捕获验证。由于我的很多模型数据都是标量值,所以大多数验证似乎都很容易。不过,我链接到的是一种多对多的关系,所以我不确定如何验证这一点。我的模型是(再一次):

    Game (only listing the relevant columns):
        GameID - int (primary key, auto-incr)
    
    Platform:
        PlatformID - int (primary key, auto-incr)
        Name - string
    
    GamePlatform (not a visible entity):
        GameID - int (foreign key from Games)
        PlatformID - int (foreign key from Platforms)
    

    以及我的创作方法(是的,我知道这是草率和业余的- 一个想学的业余爱好者。我肯定会加上错误检查。我只是想了解视图的大局->控制器->验证->在数据库中保持/显示错误过程关闭):

    public ActionResult CreateReview([Bind(prefix = "GameData")]Game newGame, int[] PlatformIDs)
    {
        try
        {
            foreach(int i in PlatformIDs)
            {
                Platform plat = _siteDB.Platforms.Single(p => p.PlatformID == i);
                newGame.Platforms.Add(plat);
            }
    
            newGame.LastModified = Datetime.Now;
    
            _siteDB.Games.AddObject(newGame);
            _siteDB.SaveChanges();
    
            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }
    

    平台数组由我视图中的一组复选框提供。为了使我的游戏有效,它必须与至少一个平台相关联。我只是不知道如何用数据注释来验证它,或者是否有可能这样做。任何帮助都将不胜感激。

    1 回复  |  直到 14 年前
        1
  •  1
  •   nwayve    14 年前

    如果我正确理解您的问题,那么int[]可能包含与DB中某个平台的ID相关联的int,并且您希望确保int[]至少包含一个有效的PlatformID,对吗?

    在进入逻辑之前,你可以马上做一个简单的检查:

    // If there aren't any IDs in Platform that are in PlatformIDs...
    if (!_siteDB.Platforms.Any(p => PlatformIDs.Contains(p.PlatformID)))
        Return RedirectToAction("Index");
        // And probably tell the user to check a box, if they did,
        // One of your checkboxes isn't matching up with your PlatformIDs
    

    理想情况下,您需要将int[]添加到模型中,以便检查模型验证。因为数据库通常不存储int[],所以将其添加到游戏模型中。EF可能会将DB实体放在Models文件夹中,如果您查看它们,就会发现它们是部分类。因此,请将此添加到“模型”文件夹中:

    public partial class Game
    {
        public Dictionary<int, bool> SupportedPlatforms { get; set; }// Edited
    }
    
    // Also add this which you'll see why below
    public partial class Platform
    {
        public static bool IsValidPlatformID(int PlatformID)
        {
            using (SiteDBEntities _siteDB = new SiteDBEntities())
                return _siteDB.Platforms.Any(p => p.PlatformID.Equals(PlatformID));
        }
    }
    

    然后添加自定义ValidationAttribute类:

    public ContainsValidPlatformIDAttribute : ValidationAttribute
    {
    
        public ContainsValidPlatformIDAttribute() { }
    
        public override bool IsValid(object value)
        {
            Dictionary<int, bool> supportedPlatforms = (Dictionary<int, bool>)value;
            if (value == null)
                return true;
            foreach (int i in values)
            {
                if (supportedPlatforms.Values.Any(b => b.Equals(true)))// Edited
                    return false;
            }
            return true;
    }
    

    现在在游戏课上用它装饰你的财产:

    [ContainsValidPlatformID(Error = "You did not select a valid Platform.")]
    public Dictionary<int, bool> SupportedPlatforms { get; set; }// Edited
    

    (已编辑)现在不必为每个平台硬编码复选框,而是添加以下内容:

    <%: Html.CheckboxFor(model => model.SupportedPlatforms[0]) %>
    <%: Html.ValidationMessageFor(model => model.SupportedPlatforms[0]) %>
    

    (已编辑)现在您的复选框绑定到模型,您可以在控制器中验证模型,并且可以从操作方法中删除int[]参数。这一切都是从我的头脑编码到这个编辑器,所以你可能需要调整一些东西这里和那里,但这是方向,你应该在工作时,在视图中的模型。

    另外,看看Scott Guthrie写的关于 MVC Model Validation 在他的博客里。希望通过我的示例和Scott的博客,您将被指向正确的方向。