0

I am currently creating an attribute similer to the existing "Remote" attribute. The client side validation is stright forward with javascipt calling an action to check (againt our database) that the input is valid. The problem is when it comes to server side validation I cannot work out how I can call the action. The "Remote" attribute is no help since "Does no server-side validation"

No client side code is show since thats working fine.

The attribute

[AttributeUsage(AttributeTargets.Property)]
public class AjaxValidation : Attribute, IModelValidator {

    private readonly string _action;
    private readonly string _area;
    private readonly string _controller;

    public AjaxValidation(string action, string controller = null, string area = null) {
        _action = action;
        _area = area;
        _controller = controller;
    }

    public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context) {

        List<ModelValidationResult> result = new List<ModelValidationResult>();

        //Need to call the action and check the result here

        //Create the controller with reflection?

        //Call the method with reflection?

        if(false was returned) {
            result.Add(new ModelValidationResult("", "{0} is invalid"));
        }

        return result;

    }
}

A model showing it's usage

[AjaxValidation ("Validate", "Home", "Examples")]
public string Value{ get; set; }

and an action that model would call (Also used by the client side)

public ActionResult Validate(string id) {

    if (id.Length == 3) {
        return Json(new { Success = true });
    } else {
        return Json(new { Success = false });
    }

}
James Sullivan
  • 131
  • 1
  • 6

1 Answers1

1

You are mixing various concepts up here in a way that is making things difficult for yourself.

Instead, of having your validation logic captured in a Controller, you should extract your validation logic into a separate service, which you can use in both the controller and attribute without difficulty. There are many ways you could do this using the various built in DataAnnotations etc, but at the very least you can just pull the code into a different service.

First, create your validation service

public class Validator
{
  public bool Validate(string id)
  {
    if (id.Length == 3) {
        return true;
    } else {
        return false;
    }
  }
}

Inject this into your existing controller to return the result as required:

public class ValidationController
{
  private readonly ValidationService _validator;

  public ActionResult Validate(string id) {
    var result = _validator.Validate(id);
    return Json(new { Success = result });
  }
}

You then need to configure your action filters to have the validator similarly injected. I recommend you read up on ASP.NET Core Action Filters and how to inject services at runtime using the ServiceFilter attribute. This answer describes how to achieve what I think you are looking for.

Community
  • 1
  • 1
Sock
  • 4,963
  • 19
  • 29