Giter VIP home page Giter VIP logo

customvalidation's Introduction

๐Ÿ‘‘ Custom Validation ๐Ÿ‘‘

This is a custom model validation library for any C# and .NET projects.

โญ Give a star โญ

If you find this library useful to you, please don't forget to encouraging me to do such more stuffs by giving a star (โญ) to this repository. Thank you.

โš™๏ธ Attributes โš™๏ธ

TanvirArjel.CustomValidation contains the following validation attributes:

1. MaxAgeAttribute To validate maximum age against date of birth value of DateTime type.

2. MinAgeAttribute To validate minimum required age against a date of birth value of DateTime type.

3. MaxDateAttribute To set max value validation for a DateTime field.

4. MinDateAttribute To set min value validation for a DateTime field.

5. TextEditorRequiredAttribute To enforce required valiaton attribute on the online text editors like TinyMCE, CkEditor etc.

6. CompareToAttribute To compare one property value against another property value of the same object. Comparison types are: Equal, NotEqual, GreaterThan, GreatherThanOrEqual, SmallerThan, SmallerThanOrEqual

7. RequiredIfAttribute To mark a field required based on the value of another field.

In addition to the above, TanvirArjel.CustomValidation.AspNetCore also contains the following validation attributes:

1. FileAttribute To validate file type, file max size, file min size etc.

2. FileTypeAttribute To validate type of a file.

3. FileMaxSizeAttribute To validate allowed max size of a file.

4. FileMinSizeAttribute To validate allowed min size of a file.

โœˆ๏ธ How do I get started? โœˆ๏ธ

For any C# and .NET Application: First install the lastest version of TanvirArjel.CustomValidation nuget package into your project as follows:

Install-Package TanvirArjel.CustomValidation

For ASP.NET Core Application: First install the lastest version of TanvirArjel.CustomValidation.AspNetCore nuget package into your project as follows:

Install-Package TanvirArjel.CustomValidation.AspNetCore

ASP.NET Core Client Side validation: To enable client client side validation for ASP.NET Core MVC or Razor Pages:

  1. First in the ConfirugeServices method of the Startup class:
using TanvirArjel.CustomValidation.AspNetCore.Extensions;

public static void ConfigureServices(IServiceCollection services)
{
    services.AddAspNetCoreCustomValidation();
    // or
    services.AddSingleton<IValidationAttributeAdapterProvider, TanvirArjelAttributeAdapterProvider>();
}
  1. Then please add the latest version of tanvirarjel.customvalidation.unobtrusive.min.js file as follows:
@section Scripts {
  @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
  <script type="text/javascript" src="~/lib/tanvirarjel-custom-validation-unobtrusive/tanvirarjel.customvalidation.unobtrusive.min.js"></script>
}

Or

<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
<script type="text/javascript" src="~/lib/tanvirarjel-custom-validation-unobtrusive/tanvirarjel.customvalidation.unobtrusive.min.js"></script>

You can download the tanvirarjel.customvalidation.unobtrusive.min.js from here tanvirarjel-custom-validation-unobtrusive-npm

Or using Visusl Studio Libman as follows:

1. wwwroot > lib> Add > Client Side Libray

2. Provider: jsdelivr
   Libray: tanvirarjel-custom-validation-unobtrusive
3. Click install     

๐Ÿ› ๏ธ Usage ๐Ÿ› ๏ธ

Then decorate your class properties with appropriate custom validation attributes as follows:

using TanvirArjel.CustomValidation.Attributes;

pulic class Employee
{
    [Display(Name = "First Number")]
    public int FirstNumber { get; set; }

    [CompareTo(nameof(FirstNumber), ComparisonType.GreaterThanOrEqual)]
    [Display(Name = "Second Number")]
    public int? SecondNumber { get; set; }

    [RequiredIf(nameof(FirstNumber), ComparisonType.Equal, 10)]
    public string ThirdNumber { get; set; }

    [File(FileType.Jpg, MaxSize = 1024)]
    public IFormFile Photo { get; set; }
}

โœ”๏ธ Dynamic Validation โœ”๏ธ

Validation against dynamic values from database, configuration file or any external sources added for the following type: 1. File Type: with ValidateFile() method 1. DateTime Type: with ValidateMaxAge() and ValidateMinAge() method as follows:

public class Employee : IValidatableObject
{
    public DateTime? DateOfBirth { get; set; }
    public IFormFile Photo { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        List<ValidationResult> validationResults = new List<ValidationResult>();
        FileOptions fileOptions = new FileOptions()
        {
            FileTypes = new FileType[] {FileType.Jpeg,FileType.Jpg},
            MinSize = 124,
            MaxSize = Convert.ToInt32(AppSettings.GetValue("DemoSettings:MaxFileSize"))
        };

        ValidationResult minAgeValidationResult = validationContext.ValidateMinAge(nameof(DateOfBirth), 10, 0, 0);
        validationResults.Add(minAgeValidationResult);

        ValidationResult fileValidationResult = validationContext.ValidateFile(nameof(Photo), fileOptions);
        validationResults.Add(fileValidationResult);
        return validationResults;
    }
}

๐Ÿ™ Note ๐Ÿ™

Dont forget to request your desired validation attribute by submitting an issue.

๐Ÿž Bug Report ๐Ÿž

Dont forget to submit an issue if you face. we will try to resolve as soon as possible.

customvalidation's People

Contributors

exluzzzivo avatar khosro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

customvalidation's Issues

Bug: CompareToAttribute client side validation doesn't work for arrays and complex objects

CompareToAttribute client side validation doesn't work for arrays of objects and complex objects in same model with same compare property names.

How to fix it:

  1. Create local variable in AddValidation method:
    var comparePropertyModelName = "*."+ComparePropertyName
    and change ComparePropertyName to this local variable in all AddAttribute items.
  2. Add some code from jquery.validate.unobtrusive.js to your custom js, that generates the right property names and validation rules based on it (for example see equalto validation).

Bug: Localized error messages don't work in CompareTo Attribute

Localized error messages don't work in CompareTo Attribute because ErrorMessage is used instead of ErrorMessageString in lines like:

private string EqualityErrorMessage => ErrorMessage ?? "The {0} is not equal to {1}.";

If ErrorMessageResourceType and ErrorMessageResourceName are set, then ErrorMessage is always null.

If I change ErrorMessage to ErrorMessageString everything works as expected.

ComparisonType.GreaterThan and ComparisonType.GreaterThanOrEqual are mixed up

Comparison logic is mixed up in file CompareToAttribute.cs. For example:

line 163
if (ComparisonType == ComparisonType.GreaterThan)
and line 177
if ((DateTime)value <= (DateTime)comparePropertyValue)
line 177 should be
if ((DateTime)value < (DateTime)comparePropertyValue)

line 192
if (ComparisonType == ComparisonType.GreaterThanOrEqual)
and line 206
if ((DateTime)value < (DateTime)comparePropertyValue)
line 206 should be
if ((DateTime)value <= (DateTime)comparePropertyValue)

Or just change comparison type in if statement:)

I haven't checked other comparison types so there could be some errors too.

Exception when using CompareTo

When using the CompareTo attribute, I am getting the following error when the view tries to load.
It happens when it executes the input tag helper on the server.

FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
System.Text.ValueStringBuilder.AppendFormatHelper(IFormatProvider provider, string format, ParamsArray args)

I tested using another attribute (RequiredIf) to make sure I set everything up correctly and its working just fine.

I am using...

  • TanvirArjel.CustomValidation.AspNetCore 1.2.1
  • .NET 5 with Razor Pages

I can provide more details if its helpful.

Bug: InvalidOperationException: Either ErrorMessageString or ErrorMessageResourceName must be set, but not both.

Hi,

I get an exception when I use ErrorMessageResourceType and ErrorMessageResourceName to set an error message, e.g.:

[Display(Name = "Second Number")]
[CompareTo(nameof(FirstNumber), ComparisonType.GreaterThan, ErrorMessageResourceType = typeof(Common), ErrorMessageResourceName = "GreaterThanError")]
public int? SecondNumber { get; set; }

InvalidOperationException: Either ErrorMessageString or ErrorMessageResourceName must be set, but not both.

A temp workaround is manually setting ErrorMessage to an empty string in validation attribute:

[CompareTo(nameof(FirstNumber), ComparisonType.GreaterThan, ErrorMessageResourceType = typeof(Common), ErrorMessageResourceName = "GreaterThanError", ErrorMessage = "")]

I think the solution to this problem is to check ErrorMessageResourceType and ErrorMessageResourceName before setting the default error message in attribute classes

Change AttributeAdapter classes access modifiers as public

Thanks @ExLuzZziVo for this great project.
I think it would be better to declare all AttributeAdapter classes as public, then we can use them in our custom impl of ValidationAttributeAdapterProvider.
Because maybe we have other custom attributes and also we want to use your custom attributes, and for localization we must have our ValidationAttributeAdapterProvider, then we can not use your impl of ValidationAttributeAdapterProvider.

Feature request: RequiredIf validation attribute

I think this is good idea for next release. For example you toggle checkbox/select some enum value, and another field becomes required.
I found some implementation on stackoverflow and have modified it a little:

    [AttributeUsage(AttributeTargets.Property)]
    public class RequiredIfValidationAttribute: RequiredAttribute, IClientModelValidator
    {
        public string OtherPropertyName { get; private set; }
        public object OtherPropertyValue { get; private set; }

        public RequiredIfValidationAttribute(string otherPropertyName, object otherPropertyValue)
        {
            OtherPropertyName = otherPropertyName;
            OtherPropertyValue = otherPropertyValue;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if(OtherPropertyName.IsNullOrEmptyOrWhiteSpace())
                return new ValidationResult($"Other property name is empty");
            var otherPropertyInfo = validationContext.ObjectType.GetProperty(OtherPropertyName);
            if (otherPropertyInfo == null)
                return new ValidationResult($"Unknown property: {OtherPropertyName}");

            var otherValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);

            if (Equals(OtherPropertyValue, otherValue))
                return base.IsValid(value, validationContext);

            return null;
        }

        public void AddValidation(ClientModelValidationContext context)
        {
            AddAttribute(context.Attributes, "data-val", "true");
            AddAttribute(context.Attributes,"data-val-requiredif-opn", "*."+OtherPropertyName);
            AddAttribute(context.Attributes,"data-val-requiredif-opv", OtherPropertyValue.ToString());
            var errorMessage = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
            AddAttribute(context.Attributes,"data-val-requiredif", errorMessage);
        }

        private static void AddAttribute(IDictionary<string, string> attributes, string key, string value)
        {
            if (!attributes.ContainsKey(key))
            {
                attributes.Add(key, value);
            }
        }

    }

JS:

//getModelPrefix(), appendModelPrefix(), escapeAttributeValue() methods are from jquery.validate.unobtrusive.js

$.validator.unobtrusive.adapters.add("requiredif",
        ["opn", "opv"],
        function(options) {
            const prefix = getModelPrefix(options.element.name);
            const other = options.params.opn;
            const fullOtherName = appendModelPrefix(other, prefix);
            const element = $(options.form).find(":input").filter(`[name='${escapeAttributeValue(fullOtherName)}']`)[0];
            return element && $(element).val() == options.params.opv;
        });

But it needs a further testing

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.