【问题标题】:Dependency Injection (DI) in ASP.NET Core/MVC 6 ViewModelASP.NET Core/MVC 6 ViewModel 中的依赖注入 (DI)
【发布时间】:2016-02-20 02:38:38
【问题描述】:

我正在使用构造函数注入在我的控制器中成功使用 ASP.NET 5/MVC 6 DI。

我现在有一个场景,我希望我的视图模型在实现 IValidatableObject 时使用 Validate 方法中的服务。

ViewModel 中的构造函数注入不起作用,因为它们需要默认的无参数构造函数。验证 Context.GetService 也不起作用。

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        MyService myService = (MyService)validationContext.GetService(typeof(MyService));

总是导致 MyService 为空。

ASP.NET 4,我将创建 ValidatableObjectAdapter,通过 DataAnnotationsModelValidatorProvider.RegisterDefaultValidatableObjectAdapterFactory 注册它,然后我可以使用 validationContext 对象对服务的引用。

我目前正在为 ASP.NET 5 使用构建在 DI 容器中,将在某个阶段移至结构图)这不重要。

我的具体验证是对象的属性(例如,用户名)是唯一的。我想将此测试委托给服务层。

【问题讨论】:

  • ViewModel 不应包含业务逻辑。在这种情况下,你应该有一个 ValidatorProcessor,你没有理由不能使用构造函数注入。
  • 我并不是说 viewModel 会有业务逻辑。该模式要么是 If (myService.IsDuplicate(Name)) {yieldReturn new validationResult,要么是 return myService.ValidateCanCreate(Name, Type, SomeOtherProperty) - 无论如何,ValidatorProcessor 是什么?我似乎找不到任何相关的参考资料。
  • 您说“视图模型中的构造函数注入”。我不明白你为什么需要这样做,我不明白为什么你不能在那里进行构造函数注入,如果你有正当理由这样做的话。
  • @mason - 见最后一句话 - 对象名称必须是唯一的。
  • 使用视图模型属性的 [FromServices] 属性在模型绑定期间使用属性注入。 odetocode.com/blogs/scott/archive/2016/02/18/…

标签: asp.net asp.net-mvc asp.net-core asp.net-core-mvc


【解决方案1】:

从 ASP.NET RC2 开始,[FromServices] 已被删除。

如果您希望视图模型中的 DI 纯粹用于 IValidatableObject.Validate,那么您可以使用 validationContext.GetService(type) 来获取您的服务。这在 RC1 中不起作用

EG

MyService myService = (MyService)validationContext.GetService(typeof(myService));

这是一个通用的扩展方法,让处理起来更愉快。

public static class ValidationContextExtensions
{
    public static T GetService<T>(this ValidationContext validationContext)
    {
        return (T)validationContext.GetService(typeof(T));
    }
}

【讨论】:

  • 现在这是 ASP.Net Core 1 的正确答案。扩展方法也很棒。
【解决方案2】:

感谢@odeToCode 的回答。为了完整起见,我用我的(工作)示例重新发布他的评论作为答案。神奇的是 [FromServices] 属性。

public class CreateDynamicMappingProfileViewModel : IValidatableObject
{

    [Display(Name = "Name", Order = 1), Required, MaxLength(50, ErrorMessage = "The name field allows a maximum of 50 characters")]
    public string Name { get; set; }

    [Display(Name = "Data Format", Order = 2), Required]
    public DataFormat DataFormat { get; set; }

    [Display(Name = "Data Context", Order = 3), Required]
    public DataContextType DataContextType { get; set; }

    [FromServices]
    public IMappingProfileServices MappingProfileServices { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        IMappingProfile mappingProfile = new DynamicMappingProfile(Name, DataFormat, DataContextType);
        return MappingProfileServices.ValidateCanSave(mappingProfile);
    }
}

【讨论】:

  • 很棒的属性,谢谢你的回答,我想发布我的,但找到了你的。 :) 问候。
  • FromServices 在最新的 ASP.NET Core 1.0 中不再存在
  • 请注意,至少根据最新的 MVC 核心文档,[FromServices] 仍然存在(但不适用于属性) - 请参阅 docs.asp.net/en/latest/mvc/controllers/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-16
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多