gpt4 book ai didi

c# - Web API 中的依赖注入(inject)验证

转载 作者:可可西里 更新时间:2023-11-01 08:25:32 25 4
gpt4 key购买 nike

在 MVC 中,我可以创建一个可以接受依赖项的模型验证器。我通常为此使用 FluentValidation。例如,这使我可以检查未使用电子邮件地址的帐户注册(注意:这是一个简化的示例!):

public class RegisterModelValidator : AbstractValidator<RegisterModel> {
private readonly MyContext _context;
public RegisterModelValidator(MyContext context) {
_context = context;
}
public override ValidationResult Validate(ValidationContext<RegisterModel> context) {
var result = base.Validate(context);
if (context.Accounts.Any(acc => acc.Email == context.InstanceToValidate.Email)){
result.Errors.Add(new ValidationFailure("Email", "Email has been used"));
}
return result;
}
}

Web API 与 FluentValidation 不存在此类集成。有一个coupleattempts在此,但都没有解决依赖注入(inject)方面的问题,并且只与静态验证器一起工作。

这之所以困难,是因为 MVC 和 Web API 之间 ModelValidatorProvider 和 ModelValidator 的实现不同。在 MVC 中,这些是根据请求实例化的(因此注入(inject)上下文很容易)。在 Web API 中,它们是静态的,并且 ModelValidatorProvider 维护每种类型的 ModelValidators 缓存,以避免对每个请求进行不必要的反射查找。

我一直在尝试自己添加必要的集成,但一直stuck trying to obtain the Dependency Scope .相反,我想我会退后一步,问问是否有任何其他解决方案来解决这个问题——是否有人想出了一个解决方案来执行可以注入(inject)依赖项的模型验证。

我不想在 Controller 中执行验证(我使用 ValidationActionFilter 将其分开),这意味着我无法从 Controller 的构造函数注入(inject)中获得任何帮助。

最佳答案

我能够使用 GetDependencyScope() 从请求中注册然后访问 Web API 依赖项解析器扩展方法。这允许在执行验证过滤器时访问模型验证器。

如果这不能解决您的依赖注入(inject)问题,请随时澄清。

Web API 配置(使用 Unity 作为 IoC 容器):

public static void Register(HttpConfiguration config)
{
config.DependencyResolver = new UnityDependencyResolver(
new UnityContainer()
.RegisterInstance<MyContext>(new MyContext())
.RegisterType<AccountValidator>()

.RegisterType<Controllers.AccountsController>()
);

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}

验证操作过滤器:

public class ModelValidationFilterAttribute : ActionFilterAttribute
{
public ModelValidationFilterAttribute() : base()
{
}

public override void OnActionExecuting(HttpActionContext actionContext)
{
var scope = actionContext.Request.GetDependencyScope();

if (scope != null)
{
var validator = scope.GetService(typeof(AccountValidator)) as AccountValidator;

// validate request using validator here...
}

base.OnActionExecuting(actionContext);
}
}

模型验证器:

public class AccountValidator : AbstractValidator<Account>
{
private readonly MyContext _context;

public AccountValidator(MyContext context) : base()
{
_context = context;
}

public override ValidationResult Validate(ValidationContext<Account> context)
{
var result = base.Validate(context);
var resource = context.InstanceToValidate;

if (_context.Accounts.Any(account => String.Equals(account.EmailAddress, resource.EmailAddress)))
{
result.Errors.Add(
new ValidationFailure("EmailAddress", String.Format("An account with an email address of '{0}' already exists.", resource.EmailAddress))
);
}

return result;
}
}

API Controller 操作方法:

[HttpPost(), ModelValidationFilter()]
public HttpResponseMessage Post(Account account)
{
var scope = this.Request.GetDependencyScope();

if(scope != null)
{
var accountContext = scope.GetService(typeof(MyContext)) as MyContext;
accountContext.Accounts.Add(account);
}

return this.Request.CreateResponse(HttpStatusCode.Created);
}

模型(示例):

public class Account
{
public Account()
{
}

public string FirstName
{
get;
set;
}

public string LastName
{
get;
set;
}

public string EmailAddress
{
get;
set;
}
}

public class MyContext
{
public MyContext()
{
}

public List<Account> Accounts
{
get
{
return _accounts;
}
}
private readonly List<Account> _accounts = new List<Account>();
}

关于c# - Web API 中的依赖注入(inject)验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15092809/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com