Created
November 11, 2011 16:25
-
-
Save AlexBar/1358426 to your computer and use it in GitHub Desktop.
CustomValidator MvcExtensions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Web.Mvc; | |
| namespace MvcExtensions | |
| { | |
| public class CustomValidationMetadata<TValidator> : ModelValidationMetadata where TValidator : CustomValidator, new() | |
| { | |
| public Action<TValidator> ConfigureValidator { get; set; } | |
| protected override ModelValidator CreateValidatorCore(ExtendedModelMetadata modelMetadata, ControllerContext context) | |
| { | |
| var validator = new TValidator(); | |
| PopulateErrorMessage(validator); | |
| if (ConfigureValidator != null) | |
| { | |
| ConfigureValidator(validator); | |
| } | |
| return new CustomValidatorDecorator(modelMetadata, context, validator); | |
| } | |
| public void PopulateErrorMessage(CustomValidator customValidator) | |
| { | |
| Invariant.IsNotNull(this, "customValidator"); | |
| string errorMessage = null; | |
| if (ErrorMessage != null) | |
| { | |
| errorMessage = ErrorMessage(); | |
| } | |
| if (!String.IsNullOrEmpty(errorMessage)) | |
| { | |
| customValidator.ErrorMessage = ErrorMessage; | |
| } | |
| else if ((ErrorMessageResourceType != null) && | |
| (!String.IsNullOrEmpty(ErrorMessageResourceName))) | |
| { | |
| customValidator.ErrorMessageResourceType = ErrorMessageResourceType; | |
| customValidator.ErrorMessageResourceName = ErrorMessageResourceName; | |
| } | |
| } | |
| } | |
| public abstract class CustomValidator | |
| { | |
| public abstract bool Validate(ValidatorContext context); | |
| public Func<string> ErrorMessage { get; set; } | |
| public string ErrorMessageResourceName { get; set; } | |
| public Type ErrorMessageResourceType { get; set; } | |
| } | |
| public class ValidatorContext | |
| { | |
| public ValidatorContext(object model, ExtendedModelMetadata metadata) | |
| { | |
| Model = model; | |
| Metadata = metadata; | |
| } | |
| public object Model { get; set; } | |
| public ExtendedModelMetadata Metadata { get; set; } | |
| } | |
| public class CustomValidatorDecorator : ModelValidator | |
| { | |
| private readonly CustomValidator _customValidator; | |
| public CustomValidatorDecorator(ExtendedModelMetadata metadata, ControllerContext controllerContext, CustomValidator customValidator) | |
| : base(metadata, controllerContext) | |
| { | |
| _customValidator = customValidator; | |
| } | |
| public override IEnumerable<ModelValidationResult> Validate(object container) | |
| { | |
| var md = (ExtendedModelMetadata) Metadata; | |
| var list = new List<ModelValidationResult>(); | |
| if (!_customValidator.Validate(new ValidatorContext(container, md))) | |
| { | |
| list.Add(new ModelValidationResult | |
| { | |
| //MemberName = md.PropertyName, --- do not need to set name here | |
| Message = _customValidator.ErrorMessage() | |
| }); | |
| } | |
| return list; | |
| } | |
| public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() | |
| { | |
| var clientValidatable = _customValidator as IClientValidatable; | |
| if (clientValidatable == null) | |
| { | |
| yield break; | |
| } | |
| foreach (ModelClientValidationRule rule in clientValidatable.GetClientValidationRules(Metadata, ControllerContext)) | |
| { | |
| yield return rule; | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| namespace MvcExtensions | |
| { | |
| using System; | |
| using System.ComponentModel; | |
| using System.Diagnostics; | |
| /// <summary> | |
| /// Defines a base class to fluently configure metadata. | |
| /// </summary> | |
| public class ModelMetadataItemBuilder<TValue> : IFluentSyntax | |
| { | |
| // ... | |
| /// <summary> | |
| /// Adds custom validator | |
| /// </summary> | |
| /// <param name="errorMessage">The error message.</param> | |
| /// <returns></returns> | |
| /// <typeparam name="TValidator"></typeparam> | |
| /// <returns></returns> | |
| public virtual ModelMetadataItemBuilder<TValue> AddCustomValidator<TValidator>(Func<string> errorMessage) where TValidator : CustomValidator, new() | |
| { | |
| return AddCustomValidator<TValidator>(null, errorMessage, null, null); | |
| } | |
| /// <summary> | |
| /// Adds custom validator | |
| /// </summary> | |
| /// <param name="configure"></param> | |
| /// <param name="errorMessage">The error message.</param> | |
| /// <returns></returns> | |
| /// <typeparam name="TValidator"></typeparam> | |
| /// <returns></returns> | |
| public virtual ModelMetadataItemBuilder<TValue> AddCustomValidator<TValidator>(Action<TValidator> configure, Func<string> errorMessage) where TValidator : CustomValidator, new() | |
| { | |
| return AddCustomValidator(configure, errorMessage, null, null); | |
| } | |
| /// <summary> | |
| /// Adds custom validator | |
| /// </summary> | |
| /// <param name="configure"></param> | |
| /// <param name="errorMessage">The error message.</param> | |
| /// <param name="errorMessageResourceType">Type of the error message resource.</param> | |
| /// <param name="errorMessageResourceName">Name of the error message resource.</param> | |
| /// <returns></returns> | |
| /// <typeparam name="TValidator"></typeparam> | |
| /// <returns></returns> | |
| protected virtual ModelMetadataItemBuilder<TValue> AddCustomValidator<TValidator>(Action<TValidator> configure, Func<string> errorMessage, Type errorMessageResourceType, string errorMessageResourceName) where TValidator : CustomValidator, new() | |
| { | |
| var customValidator = Item.GetValidationOrCreateNew<CustomValidationMetadata<TValidator>>(); | |
| customValidator.ConfigureValidator = configure; | |
| customValidator.ErrorMessage = errorMessage; | |
| customValidator.ErrorMessageResourceType = errorMessageResourceType; | |
| customValidator.ErrorMessageResourceName = errorMessageResourceName; | |
| return This; | |
| } | |
| // ... | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.ComponentModel.DataAnnotations; | |
| using System.Web.Mvc; | |
| namespace Demo.Web | |
| { | |
| using MvcExtensions; | |
| public class ProductEditModel | |
| { | |
| public int Id { get; set; } | |
| public string Name { get; set; } | |
| public Category Category { get; set; } | |
| public Supplier Supplier { get; set; } | |
| public decimal Price { get; set; } | |
| } | |
| public class ProductEditModelConfiguration : ModelMetadataConfiguration<ProductEditModel> | |
| { | |
| public ProductEditModelConfiguration() | |
| { | |
| Configure(model => model.Id).Hide(); | |
| Configure(model => model.Name).DisplayName(() => LocalizedTexts.Name) | |
| .Required(() => LocalizedTexts.NameCannotBeBlank) | |
| .AddCustomValidator<CustomValidatorTest>(() => "WTF?") | |
| .MaximumLength(64, () => LocalizedTexts.NameCannotBeMoreThanSixtyFourCharacters); | |
| Configure(model => model.Category).DisplayName(() => LocalizedTexts.Category) | |
| .Required(() => LocalizedTexts.CategoryMustBeSelected) | |
| .AsDropDownList("categories", () => LocalizedTexts.SelectCategory); | |
| Configure(model => model.Supplier).DisplayName(() => LocalizedTexts.Supplier) | |
| .Required(() => LocalizedTexts.SupplierMustBeSelected) | |
| .AsListBox("suppliers"); | |
| Configure(model => model.Price).DisplayName(() => LocalizedTexts.Price) | |
| .FormatAsCurrency() | |
| .Required(() => LocalizedTexts.PriceCannotBeBlank) | |
| .Range(10.00m, 1000.00m, () => LocalizedTexts.PriceMustBeBetweenTenToThousand); | |
| } | |
| public class CustomValidatorTest : CustomValidator | |
| { | |
| public override bool Validate(ValidatorContext context) | |
| { | |
| var m = (ProductEditModel) context.Model; | |
| if (m.Name == "aaa") | |
| return false; | |
| return true; | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment