Web应用程序验证设计决策

时间:2012-11-24 16:28:12

标签: c# asp.net-mvc web-applications architecture validation

我的项目中有这个结构 EmployeeController层调用调用EmployeeBusinessLogic(bll)Layer的EmployeeApi层。

控制器与EmployeeModel一起使用,bll与EmployeeEntity(nhibernate)一起使用。
API层将模型从Model转换为实体并赋予bll 验证在控制器(MVC)上工作,并进入已经验证的BLL 我需要在bll上再次验证实体吗?因为如果某人开发并重新使用我的bll,他可能会向其发送未经验证的数据。 我应该两次验证数据吗?在BLL和控制器上?
对我而言,它似乎是一种双重性,因为模型与实体的相似度为80% 这里的解决方法是什么? 感谢

2 个答案:

答案 0 :(得分:3)

我总是在BLL上验证,因为它是你系统的核心。由于您的系统将通过最终可能无法控制或由具有不同需求的应用程序使用的服务公开,因此无论数据来自何处,都可以确保您的数据有效。

例如,想想这个例子:

  

MVC应用程序|内部cmd工具|第三方申请

     

服务层

     

业务层

     
    

首先,在核心业务和服务层之上创建MVC应用程序。然后有人认为创建一个可以对应用程序核心执行某些操作的内部命令行工具是个好主意。如果您未在业务层验证,则需要重复MVC应用程序完成的验证。您可以接受这一点,但如果您将服务暴露给第三方,您的服务层的消费者甚至可能无法控制。因此,最终完全信任您的数据的唯一方法是在持久化之前在业务层中进行验证。

  

此外,根据应用程序,在ASP MVC应用程序上的控制器或客户端验证等其他一些层上添加验证也很有用。这样操作就会尽快失败,并尽快通知用户错误。

  

例如,在MVC应用程序中,简单验证将使用jquery验证和MVC不显眼验证在客户端工作,因此当发现错误时,它甚至不需要将数据发送回服务器并等待响应。您还可以在控制器操作中执行另一个验证步骤,在该操作中将验证您的视图模型。如果在控制器上发现任何错误,它将被添加到ModelState,并且用户通常会被重定向到显示错误并可​​以采取措施的屏幕。最后,您的应用程序核心将验证进入的数据,发现的任何错误都将在堆栈中重新发送。

正如您所说,似乎您将重复大量的验证码,但有一些方法可以最大限度地减少这种影响。当你使用ASP MVC时,一个例子可能是混合数据注释和你的验证库:

  • 您可以在模型和业务对象上使用数据注释 用于最简单的验证,如必需或常规 表达式。您还可以开发自己的数据注释 验证属性。

    public class EmployeeModel
    {
        [Required]
        public string Name {get; set;}
        ...
    }
    
    public class EmployeeEntity: BaseEntity
    {
        [Required]
        public string Name {get; set;}
        ...
    }
    
  • 对于您的业务层,请创建一个基础 仅考虑数据注释的验证器 属性。 (类似于此处描述的方法: http://odetocode.com/blogs/scott/archive/2011/06/29/manual-validation-with-data-annotations.aspx

    public class BaseValidator<T> where T: BaseEntity
    {
        public virtual ValidationResult Validate(T entity)
        {
             ... validate data annotations here ...
        }
    }
    
  • 这将为您提供客户端,控制器和的相同基本规则集 业务层,主要与用户有关 输入。

  • 对于任何具有更复杂验证逻辑的实体派生 业务层上的特定验证器来自唯一的验证器 考虑数据注释属性。为该实体类型添加特定且更复杂的验证逻辑。

    public class EmployeeValidator: BaseValidator<EmployeeEntity>
    {
        public override ValidationResult Validate(EmployeeEntity entity)
        {
             base.Validate(entity);
    
             ... perform complex BLL calculations ...
        }
    }
    
  • 最后,在控制器层添加一些代码,将业务层中引发的任何验证错误添加到ModelState中。例如,您可以在基本控制器类上添加这样的方法:

    public void AddValidationsToModelState(ValidationResult validationResult)
    {
        foreach(var error in validationResult.Errors)
        {
            ModelState.AddModelError(error.property, error.message);
        }
    }
    

最后,您将获得业务层的数据注释属性和特定验证过程的公共共享库。 希望它有所帮助!

答案 1 :(得分:0)

就个人而言,我永远不会相信跨越服务边界的数据。如果您的业务逻辑层设计为共享,则再次进行验证。是的,这是重复,但我在这里看不到任何替代方案。