在具有 3 层架构的 ASP.NET MVC 应用程序中验证业务规则的更好方法是啥?

Posted

技术标签:

【中文标题】在具有 3 层架构的 ASP.NET MVC 应用程序中验证业务规则的更好方法是啥?【英文标题】:What is better way to validate business rules in ASP.NET MVC application with 3 layer architecture?在具有 3 层架构的 ASP.NET MVC 应用程序中验证业务规则的更好方法是什么? 【发布时间】:2011-09-07 16:20:48 【问题描述】:

我正在开发一个具有 3 层经典架构的 ASP.NET MVC 应用程序 1. 数据访问(存储库) 2.业务逻辑(服务) 3.应用层(MVC控制器类) 任务是跟随有领域类Learner,学习者可以参加考试,参加考试产生一个订单(Order class),学习者参加考试后,我们需要为每个学习者发布考试结果(这意味着给一个分数和等级)并且有一些需要验证的业务规则 1.结果尚未公布 2.所有有状态的学习者都应该有标记 3. 应确定评分界限(考试分数和等级) 当用户发布结果时,所有这些规则都应该验证,如果某些规则不满足应该显示错误消息。 我决定所有与验证业务规则相关的逻辑都保留在 Service 类中,如果任何规则未通过,则抛出特定异常,在控制器类中,此异常将捕获并向客户端显示错误。这是代码

服务类

    public void ReleaseResults(long orderId)
    
        var order =orderRepository.Get(orderId);

        Check.Require(order != null, "Order was not found");


        if (IsOrderReleased(order))
        
            throw new ReleaseResultsException("The results has been already released", order.OrderNo);
        

        if (AllLearnersHasStatusPresentAndMark(order))
        
            throw new ReleaseResultsException("One or more learners unmarked", order.OrderNo);
        
        if (!GradingBoundaryConfirmed(order))
        
            throw new ReleaseResultsException("The Grading boundary needs to be confirmed", order.OrderNo);
        



        foreach (var learnerDetail in order.LearnerDetails)
        
            if (HasNotStatusPresent(learnerDetail))
            
                continue;
            
            learnerDetail.SetReleasedResults();

        

        orderRepository.SaveOrUpdate(order);
    

控制器类

        public ActionResult Release(EncryptedId orderId)
    
        Check.Require(orderId != null, "The parameter orderId was null");

        try
        
            orderReleaseResultsService.ReleaseResults(orderId);
        
        catch (ReleaseResultsException e)
        
            return Content(string.Format("Error: 0", e.Message));
        

        return Content(MUI.TheResultsHasBeenReleased);
    

我不确定这是否是验证业务规则的最佳方式,谁能帮助我提出建议或更好地解决这个问题? 提前致谢!

【问题讨论】:

【参考方案1】:

我会避免将异常用于验证目的,而是使用返回 true/false 的方法。显然,对于验证是数据层数据的某些任务(例如强制数据库约束),您可以使用异常。

你可以看看下面关于validating at the service layer的教程。

【讨论】:

这是一个很好的解决方案,但在项目中我应该参考使用 System.Web.Mvc;命名空间 @Serghei,不,没有必要。服务层需要的只是IValidationDictionary 接口。将传递给服务构造函数的ModelStateWrapper 实现将在Web 层中定义。正如您在示例中看到的那样,ProductService 构造函数在其构造函数中采用 IValidationDictionary,因此无需引用 System.Web.Mvc。 同意,使用 ModelStateDictionary 将错误传回是更好的方法 @DarinDimitrov,请在this question 上帮助我。谢谢【参考方案2】:

首先,不要将抛出异常作为验证数据的一种方式 - 这是一种过于昂贵的操作,而不是优雅地处理无效数据。

通常,在使用 MVC/ASP.NET Web 应用程序时,您通常希望在客户端和服务器端进行验证。虽然您当前的自定义验证很简单,但您必须在客户端和服务器上复制它,这很烦人 - 现在您有两个地方可以维护一个验证例程。

因此,通过模型属性上的属性使用数据注释非常方便。签出:http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx

此外,您似乎需要进行自定义验证,而不仅仅是简单的必需/最大长度检查。为此,您可以定义自己的自定义属性。查看:http://msdn.microsoft.com/en-us/library/cc668224.aspx 和 How to create custom validation attribute for MVC

您可能还想利用远程验证。签出:http://bradwilson.typepad.com/blog/2010/01/remote-validation-with-aspnet-mvc-2.html 和 http://weblogs.asp.net/imranbaloch/archive/2011/02/05/new-validation-attributes-in-asp-net-mvc-3-future.aspx

【讨论】:

我需要验证输入的业务规则不正确或其他数据。 好的,同样的想法仍然适用。您的自定义/删除验证器可以根据必要的业务规则进行验证。 关于异常成本太高的论点在这种情况下无效,这不是避免异常的原因,继续,测试每秒可以抛出多少异常 我并不是说它们不能被处理。但与优雅地处理无效数据相比,它仍然是一项更昂贵的操作。 DataAnnotations 也可用于验证业务规则。

以上是关于在具有 3 层架构的 ASP.NET MVC 应用程序中验证业务规则的更好方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

具有服务层和存储库层的 ASP.NET MVC,应该在哪里定义接口?

asp.net三层架构与asp.net MVC各自的区别,各自应该应用在啥场合,在啥情况下用三层,啥情况下用MVC

MVC(ASP.NET MVC)带3层架构如何协同工作?

ASP.NET MVC 的三层架构 + EF数据模型

使用 MEF 构建具有 n 层松散耦合的 MVC ASP.NET 应用程序

ASP.NET MVC 的三层架构 + EF数据模型