方法ValidationContext参数可用的IService

方法ValidationContext参数可用的IService

本文介绍了我怎样才能在IValidatableObject.Validate方法ValidationContext参数可用的IServiceProvider的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

控制器调用 IValidatableObject.Validate 内部并传递 ValidationContext 对象作为参数。我想用 validationContext.GetService()方法来获得一个服务对象,并使用它。

Controller calls IValidatableObject.Validate internally and passes a ValidationContext object as an argument. I want to use validationContext.GetService() method to get a service object and use it.

我可以通过这个服务作为一个依赖使用AutoFac(DI注入DLL)中的控制器构造。我如何使它availale到 ValidationContext 对象?

I can pass this service as a dependency to controller constructor using AutoFac(DI Injection dll). How do i make it availale to the ValidationContext object?

这个计算器的问题可能包含答案,但我不完全理解:Asp.Net MVC3:在ValidationContext设置自定义的IServiceProvider这样验证可以解决服务

This stackoverflow question might contain the answer but i do not understand it fully : Asp.Net MVC3: Set custom IServiceProvider in ValidationContext so validators can resolve services

下面是code:

型号:员工

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

Repository : 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);
        }
    }
}

验证来源:枚举

namespace ValidationContextDemo.Enums
{
    public enum Department
    {
        Engineering=1,
        Sales=2,
        Shipping=3,
        HumanResources=4
    }
}

服务:的EmployeeService

Service : 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

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;
        }
    }
}

控制器:EmployeeController

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);
        }

    }
}

通知员工模型验证方法的ValidationContext参数。模型之前绑定,当验证发生,ValidationContext的IServiceProvider的部分为null。

Notice the ValidationContext parameter in Validate method of Employee model. Before model binding, when the validation happens, the IServiceProvider part of ValidationContext is null.

所以,模型绑定后,当code里面我的控制器动作邮报的达到,我创建另一个ValidationContext有_serviceProvider并再次调用验证。

So, after model binding, when the code reaches inside my Controller Action "Post", i create another ValidationContext with a _serviceProvider and call Validate again.

我的问题是,我怎么能模型绑定之前有这个_serviceProvider我ValidationContext。

My question is , how can i have this _serviceProvider in my ValidationContext before model binding.

请让我知道,如果这还不清楚。

Please let me know if this is still not clear.

请注意:我创建了这个例子这一问题的缘故,我没有使用Autofac在这个例子中DI容器

Note: I created this example for the sake of this question, i am not using Autofac as a DI container in this example.

推荐答案

首先你上面code例子是pretty无关,你所面临的,因为你可能会解决此问题黑客通过简单的空问题检查员工的模型,你明确地验证它:

For starters your above code example is pretty irrelevant to the problem you are facing because you can potentially hack around the issue by a simple null check in the Employee model as you are validating it explicitly:

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

我假设(理想情况下)你不想这样做,明确和遗憾的是没有简单的方法。你必须建立一个公平的量的管道(即模型粘合剂等)的挂钩到MVC /管道的WebAPI。 这个解决方案会为你最有可能的工作,如果你必须遵循它的时候。)

I assume (ideally) you don't want to do that explicitly and unfortunately there is no easy way. You have to set up a fair amount of plumbing (i.e. model binders etc) to hook into the MVC/WebApi pipelines. This solution will most likely work for you if you have the time to follow it :).

PS:该解决方案迎合对MVC,但我看不出有任何理由可以调整为API

PS: The solution is catered towards MVC but I don't see any reason why it can be tweaked for the API.

这篇关于我怎样才能在IValidatableObject.Validate方法ValidationContext参数可用的IServiceProvider的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 10:38