首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >增加ValidationContext项的MVC和EF验证

增加ValidationContext项的MVC和EF验证
EN

Stack Overflow用户
提问于 2017-03-13 13:12:19
回答 4查看 1.6K关注 0票数 9

我有一个场景,我希望向ValidationContext中添加一个项,并在EF触发的实体验证中检查它。我是在向导中这样做的,所以我只能在特定的步骤上验证某些事情。(如果有一个好的模式,请分享)。

问题是验证是在控制器操作被击中之前触发的,实际上是两次。我希望我能理解为什么。在这种情况发生之前,我不知道如何在ValidationContext中获得该项,因此我无法告诉验证我正在执行的步骤。

此外,如果我只在通过检查下面代码中的项来触发保存更改时进行自定义验证,那么页面刷新时不会显示自动模型验证错误。

在我的自定义上下文中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public WizardStep Step { get; set; }

protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
    items.Add("ValidationStep", Step);
    return base.ValidateEntity(entityEntry, items);
}

设置实体的服务:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void SaveChanges(WizardStep step)
{
    _context.Step = step;
    _context.SaveChanges();
}

在我的实体里

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
    // Step will only be present when called from save changes.  Calls from model state validation won't have it
    if (validationContext.Items.ContainsKey("ValidationStep"))
    {
        var validationStep = (WizardStep)validationContext.Items["ValidationStep"];
        if (validationStep == WizardStep.Introduction)
        {
            if (criteria)
            {
                yield return new ValidationResult($"Error message  ", new[] { "field" });
            }
        }
    }
}

主计长:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public ActionResult MyAction(HomeViewModel vm)
{
    try
    {
        _incidentService.AddOrUpdate(vm.Enttiy);
        _incidentService.SaveChanges(WizardStep.Introduction);
    }
    catch (Exception ex)
    {
        return View(vm);
    }
    return RedirectToAction("Index");
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-03-22 05:22:33

第一个验证是在传递给控制器的MVC创建模型上进行的。MVC使用一个ModelBinder类来构造、填充和验证客户端http表单数据到模型中。任何失败的验证都将返回给客户端。然后,控制器可以更改有效的模型,因此保存时由EF进行第二次验证。我相信保存时,只有当属性是新的或有不同数据的原始值时,才会触发EF验证。

从理论上讲,应该有一个定制的MVC ModelValidator并拦截验证方法来设置ValidationContext项。但是,我想不出该怎么做。然而,我确实找到了一个对我有用的稍微不同的解决方案。也许它可以适应你的需要。

在我的例子中,我希望EF DbContext (在我的代码中命名为CmsEntities)可以用于验证方法,这样我就可以查询数据库(并进行丰富的复杂业务逻辑验证)。控制器具有DbContext,但是模型验证在传递给控制器操作之前由ModelBinder调用。

我的解决办法是:

1)向我的实体添加一个DbContext属性(使用部分类,或者在所有实体继承的基本实体中)

2)创建一个自定义ModelBinder,从控制器获取DbContext并将其填充到模型中

3)在ModelBinder ()中注册自定义ModelBinder

现在,在任何验证方法中,模型都有一个填充的DbContext。

自定义ModelBinder

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class CmsModelBinder : DefaultModelBinder
{
    protected override bool OnModelUpdating(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // Copy CmsEntities from Controller to the Model (Before we update and validate the model)
        var modelPropertyInfo = bindingContext.Model.GetType().GetProperty("CmsEntities");
        if (modelPropertyInfo != null)
        {
            var controllerPropertyInfo = controllerContext.Controller.GetType().GetProperty("CmsEntities");
            if (controllerPropertyInfo != null)
            {
                CmsEntities cmsEntities = controllerPropertyInfo.GetValue(controllerContext.Controller) as CmsEntities;
                modelPropertyInfo.SetValue(bindingContext.Model, cmsEntities);
            }
        }            
        return base.OnModelUpdating(controllerContext, bindingContext);
    }

Global.asax.cs

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    protected void Application_Start()
    {
        ...
        ModelBinders.Binders.DefaultBinder = new CmsModelBinder();
    }
票数 3
EN

Stack Overflow用户

发布于 2017-03-22 15:32:40

首先,您应该考虑WizardStep是否属于上下文或在单独的步骤中被修改的对象?另一件事是为什么不使用ie。在不同步骤上处理验证逻辑的策略?

关于验证,我看到你混合了两件事。

一个是对上下文的验证,在这里您应该处理上下文中的每个实体类型的验证逻辑。

二是IValidatableObject.Validate的实现,在SaveChanges上自动调用实体。

我会决定并选择一种方法,从你给我们的信息来看,我认为只有IValidatableObject.Validate更有意义,但是你要么将步骤放入正在验证的实体中,要么以某种方式将该步骤注入其他方法以进行验证。

票数 0
EN

Stack Overflow用户

发布于 2017-03-23 00:20:45

你可以这样做:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
try
{
  //write code

} 
catch (System.Data.Entity.Validation.DbEntityValidationException ex)
            {
                var outputLines = new List<string>();
                foreach (var eve in ex.EntityValidationErrors)
                {
                    outputLines.Add(string.Format(
                        "{0}: Entity of type \"{1}\" in state \"{2}\" has the following validation errors:",
                        DateTime.Now, eve.Entry.Entity.GetType().Name, eve.Entry.State));
                    foreach (var ve in eve.ValidationErrors)
                    {
                        outputLines.Add(string.Format(
                            "- Property: \"{0}\", Error: \"{1}\"",
                            ve.PropertyName, ve.ErrorMessage));
                    }
                }
                System.IO.File.AppendAllLines(@"c:\temp\errors.txt", outputLines);
            }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42773522

复制
相关文章
向量数据库入坑指南:初识 Faiss,如何将数据转换为向量(一)
我们日常使用的各种 APP 中的许多功能,都离不开相似度检索技术。比如一个接一个的新闻和视频推荐、各种常见的对话机器人、保护我们日常账号安全的风控系统、能够用哼唱来找到歌曲的听歌识曲,甚至就连外卖配送的最佳路线选择也都有着它的身影。
Zilliz RDS
2022/11/07
8.8K0
Python列表长度
确定列表长度 # 定义一个汽车品牌数组 cars = ['bmw', 'audi', 'benz'] # 输出列表长度 print('列表长度是:') print(len(cars)) 输出 列表长度是: 3
py3study
2020/01/10
1.4K0
如何将Pandas数据转换为Excel文件
将数据导出到Excel文件通常是任何用户阅读和解释一组数据的最优先和最方便的方式。通过使用Pandas库,可以用Python代码将你的网络搜刮或其他收集的数据导出到Excel文件中,而且步骤非常简单。
玖柒的小窝
2021/11/01
7.6K0
将列表分成指定长度的列表
在工作或参加面试过程中,经常遇到将一个列表,按指定长度分割成多个列表的问题。详细实现过程,看如下具体实例:
TalkPython
2019/05/24
2.9K0
不同列不同行的数据如何进行转置?
案例模拟文件下载 http://gofile.me/4KHV7/SUo5ywXxC
逍遥之
2020/03/24
2.9K0
不同列不同行的数据如何进行转置?
获取不同长度的UUID[通俗易懂]
在公司,有时候让处理一些命名规则时,要使用一个唯一标识,还是十六进制的,需要多少位看领导心情.
全栈程序员站长
2022/09/22
3.5K0
列表长度与索引
借助llength命令可获取列表的长度(列表所包含的元素的个数,不难发现很多跟列表相关的命令都是以英文单词l(其大写为L)开头的)。图1显示列表a的长度为3。
Lauren的FPGA
2019/10/30
1.5K0
如何将ownCloud转换为Nextcloud
ownCloud的核心开发团队中一部分人员启动了一个名为Nextcloud的项目。虽然ownCloud将继续开发,但您可能想了解新项目的功能。Nextcloud和ownCloud共享一个公共代码库,这意味着将现有的ownCloud安装迁移到Nextcloud中。
小铁匠米兰的v
2018/08/02
2.6K0
【转】URL最大长度问题
今天在测试Email Ticket的时候发现在进行Mark as Read/Unread操作时,请求是通过GET方式进行的。URL中列出了所有参与该操作的Ticket Id。于是,我想起GET请求是有最大长度限制的。遂输入超长一串Ticket Id进行请求,结果页面报错如下:
ZhangXianSheng
2019/07/02
2.7K0
如何将Array转换为List?
可以使用 Arrays.asList() 方法, 该方法接受一个数组作为输入,并返回一个列表作为输出。
程序你好
2018/07/23
1.4K0
python如何将一个多位数数值转换为列表类型
现在:a = 10,由于暂时没找到更好的方法,且使用下面的方法进行转换。 目标:转化为['10'] 以下为错误尝试: 1.直接转换,提示整型对象不可迭代。 2.先转换为字符串,再转换为列表,发现被分成
逆向小白
2018/09/12
1.8K0
python如何将一个多位数数值转换为列表类型
如何将文字转换为对应的PathGeometry
其实我们可以使用FormattedText的BuildGeometry将字符串转成对应的Geometry
黄腾霄
2020/06/10
1.6K0
Python 元组转换为列表
结论:当给定一个可迭代对象(如列表、元组、集合、范围等)时,list() 和 tuple() 返回一个新的列表和元组
Python学习者
2023/07/17
2780
策略模式:处理不同策略具有不同参数的情况
策略模式确实在处理不同策略需要不同参数的情况下会显得有些复杂。然而,这并不意味着策略模式不能在这种情况下使用。有几种可能的解决方案:
运维开发王义杰
2023/08/16
6700
策略模式:处理不同策略具有不同参数的情况
java如何将String转换为enum
已知枚举对应的String值,希望得到对应的枚举值。例如,已知"A",希望得到对应的枚举——Blah.A,应该怎么做? Enum.valueOf()是否能实现以上目的,如果是,那我如何使用?
硬核编程
2020/07/23
3.9K0
向量数据库的四大优势
其一,高效的向量查询:传统的关系型数据库查询主要是基于条件和逻辑运算,而向量数据库的查询是基于向量相似性的匹配。通过使用向量相似度算法,向量数据库能够更快地查询与某个向量最相似的数据;其二,良好的扩展性:向量数据库通常能够支持大规模向量数据的存储和查询,而且可以轻松地通过添加更多的节点来扩展系统的性能;
LCHub低代码社区
2023/06/21
8330
向量数据库的四大优势
如何将Altium画的PCB转换为Allegro
PCB(Printed-Circuit Board)设计软件种类有很多种,但是最常用的是Altium Designer、mentor pads、cadence allegro这三个软件,既然是常用的,那就可能会遇到相互转换的时候,下面为具体步骤:
用户10191012
2022/11/18
2.3K0
如何将Altium画的PCB转换为Allegro
如何将视频轻松转换为 GIF
有时看到一条有意思的视频想发到朋友圈,但朋友圈有限制时长,而且也不方便,这时可以把视频转GIF(再做成表情包也可以),再发到朋友圈或者微博(不用像视频一样需要等待审核)。
苏生不惑
2020/02/26
1.8K0
如何将pdf转换为word 2.0
再次以《新冠肺炎诊疗方案(试行第七版)》为例,该文件为图片性pdf,文字不可复制。
生信菜鸟团
2020/06/04
2.6K0
点击加载更多

相似问题

我可以从命令行向github添加问题吗?

64

可以从命令行传递关键字参数吗?

10

如何从命令行向Makefile传递参数?

51

从命令行向Java类传递参数

10

如何从命令行向gradle传递参数

12
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文