Preferred methods of checking a business object in an enterprise

Let me preface this question and state that using the Entity Framework is not an option for us.

In our financial organization, we have business units that will be used in all decisions. Some have a user interface that is not. Validation and business rules must be contained within the entity.

I encode the DALs and DTOs that are created for me, and these DALs use procs to run CRUD in the database (maybe SQL may be Oracle).

So, when I create MVC, WCF, console applications, etc., the question was glaring if the best validation method were implemented.

Here are some typical properties of an entity object:

[DefaultValue("")] public string Branch { get { return _branch; } set { if (value != null && value == _branch) return; const string propertyName = "Branch"; ValidationInstance.Clear(propertyName); ValidationInstance.ValidateRequired(propertyName, value); ValidationInstance.ValidateNumeric(propertyName, value); ValidationInstance.ValidateLength(propertyName, value, 2); _branch = value; if (EntityState != EntityStateType.New) EntityState = EntityStateType.Changed; } } [DefaultValue(0)] public decimal HighDefermentMargin { get { return _highDefermentMargin; } set { if (value == _highDefermentMargin) return; const string propertyName = "HighDefermentMargin"; ValidationInstance.Clear(propertyName); ValidationInstance.ValidateRange(propertyName, value); _highDefermentMargin = value; if (EntityState != EntityStateType.New) EntityState = EntityStateType.Changed; } } 

As you can see, there is a combination of data annotations and explicit calls to the validation class to perform an increasingly detailed validation.

In the MVC application, we carefully duplicate the validation in the ViewModel, so we get the client-side and server-side validation. Here is the version of ViewModel of the same property on top:

 [Required] [Range(0.0, 99.99)] [Display(Name = "High Deferment Margin")] public decimal HighDefermentMargin { get; set; } 

The main difference here is that the check essentially loads the errors into the error collection in the Validation class, which can be requested at the moment the object is sent for storage. If (! IsValid), then create a custom exception containing an array of errors. The controller moves around them and adds them to the ModelState.

I am starting to work on some classes that have literally a couple of hundred fields. Even if they are broken down into OO, the number of fields is still very large. These are credit certificates, etc., which contain a lot of data for one record. To write validation that many properties make me want to vomit. I can't just write a utility for creating entities and validating, because business rules are what govern the validation, not the database. The field value can be nullified in db, but it is not allowed to remain in it as null based on business rules, or the field can be empty, but only if a separate field has a value, etc.

So, you can only use data annotations in the view model. And does entity essentially achieve the same results? I can write custom validators for custom validation, and then business rules for more complex things. Will verification errors be thrown to a higher level from the object, so that the user interface can inform the user in the same convenient way as ModelState? What are others doing in the same situation?

+4
source share
1 answer

In general, a property validation attribute can get different validation results (validation check or not) depending on whether it is evaluated at the user interface level, BUsiness or DAL level. Consider, for example, the Required attribute, if it is used in the ViewModel, it can fail, but then in the business layer it can pass simply because the value that the user did not provide was provided from other sources. However, validation rules such as email format ... always get the same result. However, there are high-security issues that may require a repeat of validation at the business level ... simply because the web server is more vulnerable to attacks and more vulnerable. However, repeating twice the same validation does not mean that you need to write code twice. You can collect all the attributes that you would like to apply in several layers in a common DLL, where you define the MetaDataType that you apply to different versions (ViewModel, BL, DAL) of the same conceptual object. Thus, you comply with security requirements without duplicating code.

As suggested by saravanan, you can use exceptions to pass validation errors found in other layers to the user interface level (you can also configure WCF to pass exception information to the client)

+3
source

Source: https://habr.com/ru/post/1401239/


All Articles