مروری بر Fluent Validation در MVC

دوشنبه 15 آذر 1395

اعتبارسنجیِ داده ها (Data Validation) یکی از ویژگی های کلیدی هر برنامه وب میباشد . اعتباری سنجی معمولا روی مولفه های UI ، برای جلوگیری از بروز خطا و گرفتن اطلاعاتی که لازم است حتما از کاربر گرفته شود ، اعمال میشود . در این مقاله قصد داریم ، اعتبارسنجی داده ها با Fluent Validation را در ASP.Net MVC ارائه دهیم .

مروری بر Fluent Validation در MVC


در برنامه وب  ، همین امر از SQL Injection و Script Injection  جلوگیری میکند . 

همانطور که میدانید در حال حاضر فریمورک های Net. متفاوتی برای اعتبارسنجی ارائه شده است . ما میتوانیم با استفاده از Javascript و jQuery مولفه های UI را در سمت Client اعتبارسنجی کنیم . 

در ASP.Net MVC ، از Data Annotation Validation برای اعتبار سنجی استفاده میکنیم . استفاده از قوانین اعتبار سنجی و ارائه یک پیام در هنگام بروز خطا ، در اینجا ، کار بسیار ساده ای می‌باشد . فقط مشکل آن قوانین اعتبار سنجی است که به View Model ضمیمه شده است .

در برنامه های بزرگ ASP.Net MVC ، ما Entity را از View MOdel جدا میکنیم . دامنه Entity های ما معطوف به همه‌ی برنامه ها میشود اما View Model ها مربوط به یک برنامه خاص هستند . ما در عمل به جای استفاده از تمام دامنه Entity از فیلدهایی که مورد نیاز ما هستند استفاده خواهیم کرد . ما از Automapper در طرح ریزی دامنه Entity در View Model برای ساده و کارآمد کردن View Model استفاده میکنیم . زمانی که شروط اعتبارسنجی را در View Model قرار میدهیم ، آن پیچیده می‌شود . 

اگر برنامه در مقیاس های بزرگ انجام میشود ، اعتبارسنجی ها و Model را در یک کلاس میگذاریم . در اینجا ما قاعده های ، Seprate of Concern و  Single Responsilbility را نقض میکنیم . این باعث بروز یک مشکل در توسعه test driven،برای مشتریان می‌شود .  



برای حل این نوع از مشکلات ، ما یک گزینه داریم ، که آن فریمورکی است با نام Fluent Validation .

ما می‌توانیم قوانین اعتبارسنجی را کاملا از Model جدا کنیم .کتابخانه Fluent Validation راه های ساده ای را برای Unit Test قوانین اعتبارسنجی فراهم می‌آورد ؛ این ، زمانی که ما میخواهیم به قوانین اعتبارسنجی Dependecy ای را Inject کنیم ، به ما کمک خواهد کرد  .

برای مثال ، ما میتوانیم برای اعتبارسنجی فیلدهای UI  و نشان دادن پیام خطا به کاربران ، اطلاعاتی را از یک پایگاه داده یا یک منبع خارجی بخوانیم . زمانی که نیاز است که منطق اعتبارسنجی از مشخصه های Model جدا باشد ، قوانین seperation of Concern و Single Responsilbilty را رعایت میکنیم . Fluent Validation برعکس Unit Testing که کمی دردسر دارد ، بسیار ساده است و ما میتوانیم وابستگی ها را inject کنیم یا یک پایگاه داده یا هرگونه Service دیگر را برای اعتبارسنجی مشخصه هایمان، فراخوانی کنیم . 

آن از تعداد زیادی قوانین از پیش تعریف شده ، پیام های خطای محلی ، استفاده از  Object Data ها در پیام های خطا ، متد های اعتبارسنجی و اعتبار سنجی های شرطی سفارشی شده  ، پشتیبانی میکند . تعدادی از قوانین را تایید میکند ، اگر object data با شرط همخوانی داشت ، مجموعه قوانین - مجموعه ای از قوانین ، اشیاءِ اعتبارسنجی aggregated ، نام مجموعه ها و مشخصه هایی که با نام مشخصه های ASP.Net MVC درگیر است ، را تایید میکند . 

حال برای اینکه درک بهتری از Fluent Validation داشته باشید ، یک مثال از آن را برای شما ارائه میدهیم .

همانطور که در زیر نمایش داده شده است ، EmployeeModel را ایجاد کنید :

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
  
namespace FluentValidationDemo.Models  
{  
    public class EmployeeModel  
    {  
        public int EmployeeId { get; set; }  
        public string EmployeeName { get; set; }  
  
        public string DepartmentNo { get; set; }  
        public string Address { get; set; }  
        public int Salary { get; set; }  
  
        public string Email { get; set; }  
    }  
}  

یک کلاس با نام EmployeeValidator و کدهای زیر را درون آن بگذارید :

using FluentValidation;  
using FluentValidationDemo.Models;  
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
  
namespace FluentValidationDemo  
{  
    public class EmployeeValidator : AbstractValidator<EmployeeModel>  
    {  
        public EmployeeValidator()  
        {  
  
            EmployeeEntities e = new EmployeeEntities();  
           
               
            RuleFor(x => x.EmployeeId).NotEmpty().WithMessage("EmployeeId is required");  
            RuleFor(x => x.EmployeeName).NotEmpty().WithMessage("EmployeeName is required");  
  
EmployeeEntities e = new EmployeeEntities();  
            Custom(model =>  
            {  
                var employeevalidation = e.Employees.FirstOrDefault(emp => emp.EmployeeName == model.EmployeeName);  
                if (employeevalidation != null)  
                {  
                    return new FluentValidation.Results.ValidationFailure("EmployeeName", model.EmployeeName+"is a Existing employee.");  
                }  
  
                return null;  
            });  
  
            RuleFor(x => x.EmployeeName).Length(10,20).WithMessage("Name should be between 10 and 20 characters");  
            RuleFor(x => x.DepartmentNo).NotEmpty().WithMessage("DepartmentNo is not valid");  
  
            RuleFor(x => x.Address).NotEmpty().WithMessage("Address is required");  
            RuleFor(x => x.Salary).NotEmpty().WithMessage("Salary is not valid");  
  
            RuleFor(x => x.Email)  
              .Matches(@"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$").WithMessage("Not  a valid email")  
              .NotEmpty();  
            Custom(model=>  
                {  
                    var employeevalidation=e.Employees.FirstOrDefault(emp=>emp.Email==model.Email);  
                    if(employeevalidation!=null)  
                    {  
                        return new FluentValidation.Results.ValidationFailure("Email", "Email is already in Use Please try another EMail ");  
                    }  
  
                    return null;  
                 });  
               
        }  
    }  
}  

کلاس EmployeeValidator  ، کلاس EmployeeModel  را به عنوان ورودی دریافت میکند 

 AbstractValidator<EmployeeModel>

در اینجا ما اعتبارسنجی های مختلفی همانند required , lenght , range و regular expression برای EmployeeModel در نظر میگیریم .

RuleFor(x => x.EmployeeId).NotEmpty().WithMessage("The EmployeeId field is required");  
  
RuleFor(x => x.EmployeeName).NotEmpty().WithMessage("EmployeeName is required"); 


ما متوانیم در سمت سرور داده ها را اعتبارسنجی کنیم ، مقداد داده ها را قبل از ذخیره سازی در پایگاه داده چک کنیم . برای مثال ، Email یا Username ، که میتوانند از قبل در پایگاه داده وجود داشته باشند ، برای جلوگیری از ورود داده های تکراری میتوانید از تکه کد زیر استفاده کنید :

EmployeeEntities e = new EmployeeEntities();  
Custom(model =>   
{  
    var employeevalidation = e.Employees.FirstOrDefault(emp => emp.EmployeeName == model.EmployeeName);  
    if (employeevalidation != null)  
    {  
        return new FluentValidation.Results.ValidationFailure("EmployeeName", model.EmployeeName + "is a Existing employee.");  
    }  
    return null;  
});

حال ، ما EmployeeEntity را که یک entity از یک جدول Employee از پایگاه داده است را فراخوانی میکنیم :

آموزش asp.net mvc

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید