استفاده از Fluent Validation در برنامههای ASP.NET Core - قسمت چهارم - اعتبارسنجی Async سمت کلاینت و یا همان Remote Client Side Validation
نویسنده: وحید نصیری
تاریخ: ۱۳۹۹/۰۴/۰۲ ۱۱:۲۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
<input dir="ltr" class="form-control input-validation-error" type="email" data-val="true" data-val-email="'آدرس ایمیل' is not a valid email address." data-val-remote="این آدرس ایمیل هم اکنون مورد استفادهاست" data-val-remote-url="/Home/ValidateUniqueEmail" data-val-required="'آدرس ایمیل' must not be empty." id="Email" name="Email" >
using System.ComponentModel.DataAnnotations;
namespace FluentValidationSample.Models
{
public class UserModel
{
[Display(Name = "نام کاربری")]
public string Username { get; set; }
[Display(Name = "سن")]
public int Age { get; set; }
[Display(Name = "سابقه کار")]
public int Experience { get; set; }
[DataType(DataType.EmailAddress)]
[Display(Name = "آدرس ایمیل")]
public string Email { get; set; }
}
} using System.Linq;
namespace FluentValidationSample.Services
{
public interface IUsersService
{
bool IsUniqueEmail(string emailAddress);
}
public class UsersService : IUsersService
{
public bool IsUniqueEmail(string emailAddress)
{
string[] registedEmails = {
"email@site.com",
"test@gmail.com"
};
return !registedEmails.Contains(emailAddress);
}
}
} namespace FluentValidationSample.Web
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IUsersService, UsersService>(); using FluentValidation.Validators;
using FluentValidationSample.Services;
namespace FluentValidationSample.ModelsValidations
{
public class UniqueEmailValidator : PropertyValidator
{
private readonly IUsersService _usersService;
public UniqueEmailValidator(IUsersService usersService)
: base("این آدرس ایمیل هم اکنون مورد استفادهاست")
{
_usersService = usersService;
}
protected override bool IsValid(PropertyValidatorContext context)
{
return context.PropertyValue != null &&
_usersService.IsUniqueEmail((string)context.PropertyValue);
}
}
} using FluentValidation;
using FluentValidationSample.Services;
namespace FluentValidationSample.ModelsValidations
{
public static class CustomValidatorExtensions
{
public static IRuleBuilderOptions<T, string> UniqueEmail<T>(
this IRuleBuilder<T, string> ruleBuilder, IUsersService usersService)
{
return ruleBuilder.SetValidator(new UniqueEmailValidator(usersService));
}
}
}
using FluentValidation;
using FluentValidationSample.Models;
using FluentValidationSample.Services;
namespace FluentValidationSample.ModelsValidations
{
public class UserModelValidator : AbstractValidator<UserModel>
{
public UserModelValidator(IUsersService usersService)
{
RuleFor(x => x.Username).NotNull();
RuleFor(x => x.Age).NotNull();
RuleFor(x => x.Experience).LowerThan(nameof(UserModel.Age)).NotNull();
RuleFor(x => x.Email).EmailAddress().NotNull().UniqueEmail(usersService);
}
}
} using FluentValidation;
using FluentValidation.AspNetCore;
using FluentValidation.Internal;
using FluentValidation.Resources;
using FluentValidation.Validators;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace FluentValidationSample.ModelsValidations
{
public class RemoteClientValidator : ClientValidatorBase
{
public string RemoteUrl { set; get; }
public RemoteClientValidator(PropertyRule rule, IPropertyValidator validator) :
base(rule, validator)
{
}
public override void AddValidation(ClientModelValidationContext context)
{
MergeAttribute(context.Attributes, "data-val", "true");
MergeAttribute(context.Attributes, "data-val-remote", GetErrorMessage(context));
MergeAttribute(context.Attributes, "data-val-remote-url", RemoteUrl);
}
private string GetErrorMessage(ClientModelValidationContext context)
{
var formatter = ValidatorOptions.MessageFormatterFactory().AppendPropertyName(Rule.GetDisplayName());
string messageTemplate;
try
{
messageTemplate = Validator.Options.ErrorMessageSource.GetString(null);
}
catch (FluentValidationMessageFormatException)
{
messageTemplate = ValidatorOptions.LanguageManager.GetStringForValidator<NotEmptyValidator>();
}
return formatter.BuildMessage(messageTemplate);
}
}
} <input dir="ltr" class="form-control input-validation-error" type="email" data-val="true" data-val-email="'آدرس ایمیل' is not a valid email address." data-val-remote="این آدرس ایمیل هم اکنون مورد استفادهاست" data-val-remote-url="/Home/ValidateUniqueEmail" data-val-required="'آدرس ایمیل' must not be empty." id="Email" name="Email" >
namespace FluentValidationSample.Web
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IUsersService, UsersService>();
services.AddControllersWithViews().AddFluentValidation(
fv =>
{
fv.RegisterValidatorsFromAssembly(Assembly.GetExecutingAssembly());
fv.RegisterValidatorsFromAssemblyContaining<RegisterModelValidator>();
fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
fv.ConfigureClientsideValidation(clientSideValidation =>
{
// ...
clientSideValidation.Add(
validatorType: typeof(UniqueEmailValidator),
factory: (context, rule, validator) =>
new RemoteClientValidator(rule, validator)
{
RemoteUrl = "/Home/ValidateUniqueEmail"
});
});
}
);
} namespace FluentValidationSample.Web.Controllers
{
public class HomeController : Controller
{
private readonly IUsersService _usersService;
public HomeController(IUsersService usersService)
{
_usersService = usersService;
}
// ...
public IActionResult ValidateUniqueEmail(string email)
{
return Ok(_usersService.IsUniqueEmail(email));
}
}
} <script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script> <script src="~/lib/jquery-validation/dist/jquery.validate.js"></script> <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script> <script src="~/js/site.js" asp-append-version="true"></script>