{"id":200,"date":"2015-10-19T01:46:46","date_gmt":"2015-10-18T21:46:46","guid":{"rendered":"http:\/\/infobs.athn.ru\/?p=200"},"modified":"2015-10-19T01:46:46","modified_gmt":"2015-10-18T21:46:46","slug":"uslovnaya-validatsiya","status":"publish","type":"post","link":"https:\/\/infobase.athn.ru\/program\/2015\/10\/uslovnaya-validatsiya\/","title":{"rendered":"\u0423\u0441\u043b\u043e\u0432\u043d\u0430\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f"},"content":{"rendered":"<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043e\u0434\u043d\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445.<\/p>\n<p>\u041e\u0442\u0441\u044e\u0434\u0430: https:\/\/gist.github.com\/elizabeth-young\/5875161<br \/>\n<!--more--><\/p>\n<pre>\npublic enum Comparison\n{\n    IsEqualTo,\n    IsNotEqualTo\n}\n\/\/\/ <summary>\n\/\/\/ Validation attribute for required value if another property is set\n\/\/\/ <\/summary>\n[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]\npublic sealed class RequiredIfAttribute : ValidationAttribute, IClientValidatable\n{\n    private const string DefaultErrorMessageFormatString = \"The {0} field is required.\";\n    public string OtherProperty { get; private set; }\n    public Comparison Comparison { get; private set; }\n    public Object Value { get; private set; }\n\n    public RequiredIfAttribute(string otherProperty, Comparison comparison, object value)\n    {\n        if (string.IsNullOrEmpty(otherProperty))\n        {\n            throw new ArgumentNullException(\"otherProperty\");\n        }\n\n        OtherProperty = otherProperty;\n        Comparison = comparison;\n        Value = value;\n    }\n\n    public override string FormatErrorMessage(string name)\n    {\n        return string.Format(ErrorMessageString, name, OtherProperty);\n    }\n\n    public bool Validate(object actualPropertyValue)\n    {\n        switch (Comparison)\n        {\n            case Comparison.IsNotEqualTo:\n                return actualPropertyValue == null ? Value != null : !actualPropertyValue.Equals(Value);\n            default:\n                return actualPropertyValue == null ? Value == null : actualPropertyValue.Equals(Value);\n        }\n    }\n\n    protected override ValidationResult IsValid(object value, ValidationContext validationContext)\n    {\n        if (value == null)\n        {\n            try\n            {\n                var property = validationContext.ObjectInstance.GetType().GetProperty(OtherProperty);\n                var propertyValue = property.GetValue(validationContext.ObjectInstance, null);\n\n                if (Validate(propertyValue))\n                {\n                    return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));\n                }\n            }\n            catch (Exception e)\n            {\n                if (OtherProperty.Contains('_'))\n                {\n                    var prop = OtherProperty.Split('_');\n\n                    var property = validationContext.ObjectInstance.GetType().GetProperty(prop.Last());\n                    var propertyValue = property.GetValue(validationContext.ObjectInstance, null);\n\n                    if (!Validate(propertyValue))\n                    {\n                        return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));\n                    }\n                }\n            }\n        }\n        return ValidationResult.Success;\n    }\n\n    public IEnumerable GetClientValidationRules(ModelMetadata metadata,\n                                                                           ControllerContext context)\n    {\n        return new[]\n            {\n                new ModelClientValidationRequiredIfRule(\n                    FormatErrorMessage(metadata.GetDisplayName()), OtherProperty, Comparison, Value, metadata,\n                    context)\n            };\n    }\n}\n\npublic class ModelClientValidationRequiredIfRule : ModelClientValidationRule\n{\n    public ModelClientValidationRequiredIfRule(string errorMessage, string otherProperty, Comparison comparison,\n                                               object value, ModelMetadata metadata, ControllerContext context)\n    {\n        ErrorMessage = errorMessage;\n        ValidationType = \"requiredif\";\n        ValidationParameters.Add(\"other\", BuildDependentPropertyId(metadata, context as ViewContext, otherProperty));\n        ValidationParameters.Add(\"comp\", comparison.ToString().ToLower());\n        ValidationParameters.Add(\"value\", value.ToString().ToLower());\n    }\n\n    private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext, string otherProperty)\n    {\n        return QualifyFieldId(metadata, otherProperty, viewContext);\n    }\n\n    protected string QualifyFieldId(ModelMetadata metadata, string fieldId, ViewContext viewContext)\n    {\n        \/\/ build the ID of the property\n        string depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(fieldId);\n        \/\/ unfortunately this will have the name of the current field appended to the beginning,\n        \/\/ because the TemplateInfo's context has had this fieldname appended to it. Instead, we\n        \/\/ want to get the context as though it was one level higher (i.e. outside the current property,\n        \/\/ which is the containing object (our Person), and hence the same level as the dependent property.\n        var thisField = metadata.PropertyName + \"_\";\n        if (depProp.StartsWith(thisField))\n            \/\/ strip it off again\n            depProp = depProp.Substring(thisField.Length);\n        else if (depProp.Contains(thisField))\n        {\n            depProp = depProp.Remove(depProp.IndexOf(thisField), thisField.Length);\n        }\n        return depProp;\n    }\n}\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043e\u0434\u043d\u0438\u0445 \u043f\u043e\u043b\u0435\u0439 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445. \u041e\u0442\u0441\u044e\u0434\u0430: https:\/\/gist.github.com\/elizabeth-young\/5875161<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[31,32],"tags":[154],"class_list":["post-200","post","type-post","status-publish","format-standard","hentry","category-aspnet","category-csharp","tag-validatsiya"],"_links":{"self":[{"href":"https:\/\/infobase.athn.ru\/program\/wp-json\/wp\/v2\/posts\/200","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/infobase.athn.ru\/program\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/infobase.athn.ru\/program\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/infobase.athn.ru\/program\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/infobase.athn.ru\/program\/wp-json\/wp\/v2\/comments?post=200"}],"version-history":[{"count":0,"href":"https:\/\/infobase.athn.ru\/program\/wp-json\/wp\/v2\/posts\/200\/revisions"}],"wp:attachment":[{"href":"https:\/\/infobase.athn.ru\/program\/wp-json\/wp\/v2\/media?parent=200"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/infobase.athn.ru\/program\/wp-json\/wp\/v2\/categories?post=200"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/infobase.athn.ru\/program\/wp-json\/wp\/v2\/tags?post=200"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}