使用异常验证 Asp.net MVC 中的业务逻辑

2024-01-28

我对在 asp.net mvc 中用于进行业务规则验证的方法有疑问。

目前我有一个异常类,看起来像这样

public class ValidationException : Exception 
{
    private ModelStateDictionary State { get; set; }
    public ValidationException(ModelStateDictionary state)
    {
        State = state;
    }
    public void MergeModelStates(ModelStateDictionary state)
    {
        state.Merge(this.State);
    }
}

和一个看起来像这样的验证器

public void Validate(IEntity entity)
{
    ModelStateDictionary state = new ModelStateDictionary();
    if (entity.Contact != null && _service.GetBy(entity.Contact.Id) == null)
        state.AddModelError("Contact", "Invalid Contact.");
    if (entity.Title.Length > 8)
        state.AddModelError("title", "Title is too long...");
    ... etc
    if (!state.IsValid)
        throw new ValidationException(state);
}

和一个执行类似操作的控制器

public ActionResult Add()
{
    var entity = new InputModel;
    try
    {
        TryUpdateMode(inputModel);
        ..... Send input to a Repository (Repository calls Validate(entity);
    }
    catch (ValidationException validationException)
    {
       validationException.MergeModelStates(this.ModelState);
       TryUpdateModel(inputModel);
       return View("Add",inputModel);
    }
    return View("List");
}

使用异常来做这样的事情是错误的吗? 有更好方法的例子吗?我真的不想将验证添加到模型实体本身。我见过的唯一其他方法是将控制器 ModelState 注入到存储库层,但这对我来说似乎很草率。

谢谢你的帮助


异常通常应该用于特殊情况,而不是处理程序正常执行期间可能经常发生的事情。造成这种情况的原因有很多——以下是我经常遇到的一些原因:

  1. 性能问题 - 异常通常是相当昂贵的操作 - 如果定期抛出异常,您的性能可能会受到影响。
  2. 处理未捕获的验证异常 - 如果您碰巧使用代码而不处理异常,您将显示验证错误直至“黄屏”或崩溃处理程序 - 可能不是最好的用户体验。
  3. 异常的结构方式无法提供良好的面向用户的信息。看一下异常类 - 没有太多设置可以提供良好的面向用户的信息,而您需要将信息转发回用户。每当我尝试以这种方式使用异常时,我都会得到一大堆带有附加属性的子类,而这些属性对于异常来说并没有多大意义。

我通常喜欢做的一种方法是提供一个公共 Validate 方法,该方法返回错误列表(但从不抛出异常本身),然后提供一个 Save 方法,该方法调用 Validate() 并在出现任何错误时抛出异常。您将行为从“如果模型无效则抛出”切换为“如果代码在模型处于无效状态时尝试保存则抛出”。

为了解决下面有关 Validate 与 Save 中抛出的性能的评论 - 在 Save() 中抛出将具有与在 Validate() 中抛出完全相同的性能损失。然而,关键的区别是这种情况永远不应该发生——您是在防止开发人员不正确地使用您的类,而不是使用异常作为验证方法。如果编写正确,调用 save 方法的代码应类似于:

ValidationResult result = obj.Validate();
if (result.IsValid) {
   obj.Save();
} else {
   // display errors to the user
}

仅当开发人员在保存之前忘记检查验证状态时才会引发异常。这样做的好处是既可以在不使用异常的情况下进行验证,又可以通过不允许保存无效实体来保护数据库。理想情况下,您根本不会捕获控制器中的异常,并让一般错误处理例程处理它,因为问题不再是用户输入,而是开发人员的错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用异常验证 Asp.net MVC 中的业务逻辑 的相关文章

  • Ajax.BeginForm 无法与 Html.ValidationSummary 一起使用

    我正在尝试使用 Ajax BeginForm 将数据发布到控制器 如果出现特定错误 表单应重新呈现并显示添加到 ModelState 的自定义错误消息 由于某种原因 错误消息未显示 我什至正在尝试以下不起作用的测试用例 我是否遗漏了什么 E
  • Django GenericIPAddress 字段未验证输入

    你好 我有以下 Django 模型 class AccessPointIPAddress models Model Model for storing AccessPoint IP Addresses ap models ForeignKe
  • 如何降低圈复杂度?

    我正在开发一个将 RequestDTO 发送到 Web 服务的类 我需要在发送请求之前验证该请求 请求可以从 3 个不同的地方发送 并且每个 请求类型 有不同的验证规则 例如请求1必须有姓名和电话号码 请求2必须有地址等 我有一个 DTO
  • 如何使用 ASP.NET MVC 进行 HTTP 调用?

    我正在尝试做的事情 我试图练习进行 HTTP 调用 如果这就是它的名字 来自一个简单的 ASP NET MVC Web 应用程序 为此 我尝试从以下位置获取天气详细信息打开天气地图 http openweathermap org appid
  • 将 VS2015 中的 ASP.NET Identity 中的 User Id 类型更改为 int

    默认情况下 VS 2015 中的 ASP NET Identity 使用字符串作为 AspNet 表的主键 我想使用 int 类型的 id 来代替 经过一些研究后发现 框架开箱即用地支持不同类型的 ID 在下面的答案中 我将展示要实现这一目
  • Spring MVC - 自动查找验证器

    假设我有一个像这样的示例实体类 public class Address 和相应的验证器 Component public AddressValidator implements Validator Override public bool
  • Django 和自定义表单验证

    我正在尝试创建一个自定义表单字段并对其进行验证 这是 Django 1 0 版本 这是我的表单对象 class UsernameField forms CharField def clean self values print 我是这样称呼
  • 用于 mvc3 日期格式和日期验证的文本框

    我决定开始使用 MVC 3 并且在尝试将我的一个 Web 应用程序重做为 MVC3 时遇到了这个问题 我的项目是这样设置的 public class Project public int ProjectID get set Required
  • ASP.Net MVC 上的防伪系统

    当我输入以下代码时 using Html BeginForm LogOff Account FormMethod Post new id logoutForm Html AntiForgeryToken a href Log off a t
  • 在 Spring 中为 @Pathvariable 添加类级别验证

    在发布这个问题之前 我已经做了很多研究并尝试了很多可用的解决方案 这是我陷入的棘手情况 我有一个 Spring 控制器 它有多个请求映射 它们都有 PathVariables 控制器如下所示 Controller EnableWebMvc
  • 如何确定异常是否属于特定类型

    我有一段 try catch 代码 try catch Exception ex ModelState AddModelError duplicateInvoiceNumberOrganisation The combination of
  • ViewModel 的列表在操作中为 null

    我正在开发我的第一个 ASP NET MVC 3 应用程序 我有一个如下所示的视图 model IceCream ViewModels Note NotesViewModel using Html BeginForm Html Valida
  • ASCII“../”是 PHP 中指示目录遍历的唯一字节序列吗?

    我有一个 PHP 应用程序 它使用 GET参数来选择文件系统上的 JS CSS 文件 如果我拒绝输入字符串包含的所有请求 或者可见 7 位 ASCII 范围之外的字节 当路径传递到 PHP 的底层 基于 C 文件函数时 这是否足以防止父目录
  • ASP.NET Core 与现有的 IoC 容器和环境?

    我想运行ASP NET 核心网络堆栈以及MVC在已托管现有应用程序的 Windows 服务环境中 以便为其提供前端 该应用程序使用 Autofac 来处理 DI 问题 这很好 因为它已经有一个扩展Microsoft Extensions D
  • 角度 4 单击按钮功能未触发

    我正在尝试检查文本输入是否为空或不在角度 4 中 我没有为此使用表单 这只是一个输入字段 当我在下面的按钮中执行 addLocaton 函数时 需要进行检查 我的输入字段
  • 无法加载文件或程序集“Newtonsoft.Json”或其依赖项之一

    首先 它不仅仅是重复的 以下问题的答案都不适合我 http goo gl tS40cn http goo gl tS40cn http goo gl pH6v2T http goo gl pH6v2T 我刚刚使用 Nuget 包管理器更新了
  • 使用 OWIN Identity 注册来自多个 API 客户端的 Web API 2 外部登录

    我想要以下架构 我为本示例编写了产品名称 在一台服务器上运行的 Web API 2 应用程序 http api prettypictures com http api prettypictures com 在另一台服务器上运行的 MVC 5
  • 如何对我的自定义验证属性进行单元测试

    我有一个自定义的 asp net mvc 类验证属性 我的问题是如何对其进行单元测试 测试类是否具有该属性是一回事 但这实际上并不能测试其中的逻辑 这就是我想测试的 Serializable EligabilityStudentDebtsA
  • Asp.Net Mvc 无法注销

    这是我的登录代码 var expire DateTime Now AddDays 7 Create a new ticket used for authentication var ticket new FormsAuthenticatio
  • 如何在 DropDownList 中保留空格 - ASP.net MVC Razor 视图

    我在视图中通过以下方式绑定我的模型 问题是我的项目文本是格式化文本 单词之间有空格 如下所示 123 First 234 00 123 AnotherItem 234 00 123 Second 234 00 我想保留此项目文本中的空格 即

随机推荐