控制器在内部调用IValidatableObject.Validate
并传递ValidationContext
个对象作为参数。我想使用validationContext.GetService()
方法获取服务对象并使用它。
我可以使用AutoFac(DI Injection dll)将此服务作为依赖项传递给控制器构造函数。如何使其可用于ValidationContext
对象?
此stackoverflow问题可能包含答案,但我完全不理解:Asp.Net MVC3: Set custom IServiceProvider in ValidationContext so validators can resolve services
以下是代码:
模特:员工
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace ValidationContextDemo.Models
{
public class Employee : IValidatableObject
{
public int Id { get; set; }
public string Name { get; set; }
public int DepartmentId { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var result = new List<ValidationResult>();
var EmployeeService = (Service.EmployeeService)validationContext.GetService(typeof(Service.EmployeeService));
if (!EmployeeService.IsValidDepartment(this.DepartmentId))
{
result.Add(new ValidationResult("This DepartmentId does not exists"));
}
return result;
}
}
}
存储库:EmployeeRepository
using System.Collections.Generic;
using System.Linq;
namespace ValidationContextDemo.Models
{
public class EmployeeRepository
{
public EmployeeRepository()
{
Employees = new List<Employee>() {
new Employee{Id=1, Name="Alpha", DepartmentId=1},
new Employee{Id=2, Name="Beta", DepartmentId=1},
new Employee{Id=3, Name="Gamma", DepartmentId=1}
};
}
public List<Employee> Employees { get; set; }
public void AddEmployee(Employee e)
{
Employees.Add(e);
}
public void UpdateEmployee(int id, Employee e)
{
Employee emp = Employees.Where(x => x.Id == id).FirstOrDefault();
emp.Name = e.Name;
emp.DepartmentId = e.DepartmentId;
}
public void DeleteEmployee(Employee e)
{
Employees.Remove(e);
}
}
}
验证来源:Enum
namespace ValidationContextDemo.Enums
{
public enum Department
{
Engineering=1,
Sales=2,
Shipping=3,
HumanResources=4
}
}
服务:EmployeeService
using System;
using System.Linq;
namespace ValidationContextDemo.Service
{
public class EmployeeService
{
public bool IsValidDepartment(int departmentId)
{
return Enum.GetValues(typeof(Enums.Department)).Cast<Enums.Department>().Contains((Enums.Department)departmentId);
}
}
}
IServiceProvider:EmployeeServiceProvider
using System;
namespace ValidationContextDemo.Service
{
public class EmployeeServiceProvider: IServiceProvider
{
public object GetService(Type serviceType)
{
if (serviceType==typeof(EmployeeService))
{
return new EmployeeService();
}
return null;
}
}
}
Controller:EmployeeController
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using ValidationContextDemo.Models;
using ValidationContextDemo.Service;
namespace ValidationContextDemo.Controllers
{
public class EmployeeController : ApiController
{
EmployeeRepository _repository;
EmployeeServiceProvider _serviceProvider;
public EmployeeController()
{
_repository = new EmployeeRepository();
_serviceProvider = new EmployeeServiceProvider();
}
public IHttpActionResult Get()
{
return Json(_repository.Employees);
}
public HttpResponseMessage Post(Employee e)
{
ValidationContext vContext = new ValidationContext(e, _serviceProvider, null);
e.Validate(vContext);
_repository.AddEmployee(e);
return new HttpResponseMessage(HttpStatusCode.Created);
}
}
}
注意Employee模型的Validate方法中的ValidationContext参数。在模型绑定之前,验证发生时,ValidationContext的IServiceProvider部分为空。
因此,在模型绑定之后,当代码到达我的Controller Action“Post”内部时,我使用_serviceProvider创建另一个ValidationContext并再次调用Validate。
我的问题是,如何在模型绑定之前在我的ValidationContext中使用此_serviceProvider。
如果仍然不清楚,请告诉我。
注意:为了这个问题我创建了这个例子,在这个例子中我没有使用Autofac作为DI容器。
答案 0 :(得分:0)
首先,您的上述代码示例与您所面临的问题无关,因为您可以通过在Employee模型中进行简单的空检查来解决问题,因为您明确地验证了它:
ValidationContext vContext = new ValidationContext(e, _serviceProvider, null);
e.Validate(vContext);
我认为(理想情况下)你不想明确地这样做,不幸的是没有简单的方法。您必须设置相当数量的管道(即模型绑定器等)以挂接到MVC / WebApi管道。如果您有时间关注它,This solution很可能会对您有用:)。
PS:解决方案迎合了MVC,但我没有看到任何可以为API调整的原因。