问题
This question is the consequence of this question.
I am developing an ASP.NET MVC Web Application. In my project I am doing remote validation using data annotation to my view model class. I know default remote attribute does not support server validation. I can validate it again in action method. But I do not want to do that it is violating separation of concerns.
So I tried to create custom server client remote validation attribute. I found a code online and I used it. But it is giving me error when server validation is occurred. I am using Ninject for dependency injection. Error occurred because Ninject cannot inject dependencies in validation attribute.
This 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);
// Invoke the action method that has validation logic
object response = action.Invoke(instance, new object[] { value });
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 controller class
public class CategoryController : Controller
{
private ICategoryRepo categoryRepo;
public CategoryController()
{
}
public CategoryController(ICategoryRepo categoryParam)
{
this.categoryRepo = categoryParam;
}
.
.
//remote validation action
public JsonResult IsNameUnique(string Name)
{
IEnumerable<Category> categories = categoryRepo.Categories.Where(x => x.Name.Trim() == Name);
Category category = categories.FirstOrDefault();
return Json(category==null, JsonRequestBehavior.AllowGet);
}
}
When validation passed client side and came to server side, it starts throwing error.
This is the error
Yes, it is throwing no method found exception because it cannot find constructor without parameters.
I added parameterless constructor like this
public CategoryController()
{
categoryRepo = new CategoryRepo();
}
But the problem is if I do that, the reason I am using Ninject does not make any sense at all. It is making dependency. But if I don't do this way, categoryRepo will throw null exception in IsNameUnique action. So how can I make Ninject work in my custom remote validation attribute?
回答1:
Try to replace :
object instance = Activator.CreateInstance(controller);
with
object instance = DependencyResolver.Current.GetService(controller);
I must point that this is an usage of the controversial ServiceLocator pattern. But I hardly see how to do it differently in this attribute.
来源:https://stackoverflow.com/questions/37947539/ninject-is-not-working-in-custom-validation-attribubte-in-asp-net-mvc