1

I am developing an ASP.NET MVC5 project. In my project I am creating remote validation. For that I just created an custom validation attribute to support server-side validation. My remote validator working fine when remote action has to catch only one field. But I am having problems when I try to bind additional field for it. I mean when I validate with extra fields.

Here is my custom remote validation attribute

public class RemoteClientServerAttribute : RemoteAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            // Get the controller using reflection
            Type controller = Assembly.GetExecutingAssembly().GetTypes()
                .FirstOrDefault(type => type.Name.ToLower() == string.Format("{0}Controller",
                    this.RouteData["controller"].ToString()).ToLower());
            if (controller != null)
            {
                // Get the action method that has validation logic
                MethodInfo action = controller.GetMethods()
                    .FirstOrDefault(method => method.Name.ToLower() ==
                        this.RouteData["action"].ToString().ToLower());
                if (action != null)
                {
                    // Create an instance of the controller class
                    //object instance = Activator.CreateInstance(controller);
                    object instance = DependencyResolver.Current.GetService(controller);
                    // Invoke the action method that has validation logic
                    var param = new object[] { value };
                    if(!String.IsNullOrEmpty(this.AdditionalFields))
                    {
                        param = new object[] { value , this.AdditionalFields };           
                    }
                    object response = action.Invoke(instance, param);
                    if (response is JsonResult)
                    {
                        object jsonData = ((JsonResult)response).Data;
                        if (jsonData is bool)
                        {
                            return (bool)jsonData ? ValidationResult.Success :
                                new ValidationResult(this.ErrorMessage);
                        }
                    }
                }
            }

            return ValidationResult.Success;
            // If you want the validation to fail, create an instance of ValidationResult
            // return new ValidationResult(base.ErrorMessageString);
        }

        public RemoteClientServerAttribute(string routeName)
            : base(routeName)
        {
        }

        public RemoteClientServerAttribute(string action, string controller)
            : base(action, controller)
        {
        }

        public RemoteClientServerAttribute(string action, string controller,
            string areaName)
            : base(action, controller, areaName)
        {
        }
    }

This is my remote validation action with an extra field

public JsonResult IsNameUnique(string Name,int Id)
        {
            IEnumerable<Category> categories = categoryRepo.Categories.Where(x => x.Name.Trim() == Name);

            if (Id > 0)
            {
                categories = categories.Where(x => x.Id != Id);
            }
            Category category = categories.FirstOrDefault();
            return Json(category==null, JsonRequestBehavior.AllowGet);
        }

This is how I am setting annotation in view model

[RemoteClientServer("IsNameUnique","Category","Admin",AdditionalFields="Id",ErrorMessage="Name is already taken")]
        public string Name { get; set; }

As you can see I set "Id" for additional field in annotation. But when I submit the form I get the following error in custom validation attribute.

enter image description here

As you can see additional fiels is "Id" as I set in annotation. Not 14 that. 14 is what Id value binded in remote action method.

This is my view

<form method="POST">
@Html.HiddenFor(m=>m.Id)
@Html.TextBoxFor(m => m.Name, new { @class="form-control" })
</form>

How can I catch the value actually binded in remote validation action method in validation attribute? Why is that always "Id". I set "Id" in annotation because I want value of Id binded in action method. How can I solve this problem?

If I convert the type of Id to string in remote action method, its value also become "Id" when I submit the form.

What I think I need to do is I want to retrieve form submitted value using that additional field name. Eg Form["Id"] in validation attribute class. I tried to retrieved property. But it is always zero. How can I retrieve form value using that additional field like this form[AdditionalFields].

halfer
  • 19,824
  • 17
  • 99
  • 186
Wai Yan Hein
  • 13,651
  • 35
  • 180
  • 372
  • You have to get the property using `var propertyName = validationContext.ObjectInstance.GetType().GetProperty("Id");` and then the value using `var propertyValue = propertyName.GetValue(validationContext.ObjectInstance, null);` –  Jun 27 '16 at 05:40
  • Thank u. I get it working. First time I tried, I just used this line var propertyName = validationContext.ObjectInstance.GetType().GetProperty("Id"); to get value. That is my weakness. Thanks for your support. – Wai Yan Hein Jun 27 '16 at 05:48
  • I just hard coded `"Id"`, but in reality you will need to get that from the `AdditionalFields` value (which may include more than one property name) –  Jun 27 '16 at 05:54

0 Answers0