Dependency Injection (DI) in ASP.NET Core / MVC 6 ViewModel

I successfully use ASP.NET 5 / MVC 6 DI in my controllers using constructor injection.

Now I have a script in which I want my view models to utilize the service in the Validate method when implementing the IValidatableObject.

Embedding a constructor in a ViewModel does not work because they need a constructor without parameters without parameters. Checking Context.GetService also does not work.

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

always causes MyService to be null.

ASP.NET 4, I would create a ValidatableObjectAdapter, register it through DataAnnotationsModelValidatorProvider.RegisterDefaultValidatableObjectAdapterFactory, and then I could use validationContext to reference objects for services.

I am currently using the assembly in the DI container for ASP.NET 5, at some stage I will move on to the structure structure), but it does not matter.

My special check is that the property of the object (like username) is unique. I want to delegate this test to the service level.

+4
source share
2 answers

Like ASP.NET RC2, [FromServices] has been removed.

If you want the DI in your view to be modeled exclusively for IValidatableObject.Validate, you can use validationContext.GetService (type) to get your service. This does not work in RC1

E.G.

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

Here is a general extension method to make it more enjoyable.

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

Thanks @odeToCode for the answer. For the sake of completeness, I re-posted his comment as an answer with my (working) example. Magic is the [FromServices] attribute.

 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); } } 
+1
source

Source: https://habr.com/ru/post/1263308/


All Articles