Controller 在内部调用 IValidatableObject.Validate 并将 ValidationContext 对象作为参数传递。我想使用 validationContext.GetService() 方法来获取服务对象并使用它。

我可以使用 AutoFac(DI Injection dll) 将此服务作为依赖项传递给 Controller ​​构造函数。我如何使它可用于 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;
        }
    }
}

存储库:员工存储库
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);
        }
    }
}

验证来源:枚举
namespace ValidationContextDemo.Enums
{
    public enum Department
    {
        Engineering=1,
        Sales=2,
        Shipping=3,
        HumanResources=4
    }
}

服务:员工服务
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 : 员工服务提供者
using System;

namespace ValidationContextDemo.Service
{
    public class EmployeeServiceProvider: IServiceProvider
    {

        public object GetService(Type serviceType)
        {
            if (serviceType==typeof(EmployeeService))
            {
                return new EmployeeService();
            }
            return null;
        }
    }
}

Controller :员工 Controller
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 参数。在模型绑定(bind)之前,当验证发生时,ValidationContext 的 IServiceProvider 部分为 null。

因此,在模型绑定(bind)之后,当代码到达我的 Controller 操作“Post”内部时,我使用 _serviceProvider 创建另一个 ValidationContext 并再次调用 Validate。

我的问题是,如何在模型绑定(bind)之前在我的 ValidationContext 中拥有这个 _serviceProvider。

如果这还不清楚,请告诉我。

注意:我为了这个问题创建了这个例子,在这个例子中我没有使用 Autofac 作为 DI 容器。

最佳答案

对于初学者,您上面的代码示例与您面临的问题非常无关,因为您可以通过在 Employee 模型中进行简单的空检查来解决问题,因为您正在明确验证它:

ValidationContext vContext = new ValidationContext(e, _serviceProvider, null);
e.Validate(vContext);

我假设(理想情况下)您不想明确地这样做,不幸的是没有简单的方法。您必须设置大量管道(即模型绑定(bind)器等)以连接到 MVC/WebApi 管道。如果您有时间遵循 This solution 很可能会为您工作:)。

PS:该解决方案面向 MVC,但我看不出有任何理由可以针对 API 对其进行调整。

关于c# - 如何在 IValidatableObject.Validate 方法的 ValidationContext 参数中提供 IServiceProvider,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30213330/

10-12 03:28