I need to validate some properties of a model against the retreived data from one Service used in another controller. I used a Validation Attribute as is recomended:
[Section1Validator] [IsValidPetAgainstCategories] public class PetInfoModel { [...]
The definition of this ValidationAttribute uses the ValidationContext to retrieve the ValidationService:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class IsValidPetAgainstCategories : ValidationAttribute { public IsValidPetAgainstCategories() { }
/// <summary> /// Check if string is in an array of accepted values /// </summary> /// <param name="value"></param> /// <param name="validationContext"></param> /// <returns></returns> protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
var validator = (ICategoriesValidation)validationContext .GetService(typeof(ICategoriesValidation)); var categoryService = (ICategoryService)validationContext .GetService(typeof(ICategoryService));
var pet = value as PetInfoModel;
//------------------------ // Checking for Pet Breed type //------------------------
if (pet.PetType.Equals(PetType.NWA_PET_D.ToString())) { if(!validator.isFieldValid(categoryService, pet.PetBreedType, Categories.DOGBREEDTYPE)) return new ValidationResult(PetErrorStrings.INVALID_PET_BREED_TYPE); }[...]
This ICategoriesValidator is just a middleware to make the call to the retriever service and do the validation logic as follows:
public class CategoriesValidation : ICategoriesValidation { public bool isFieldValid(ICategoryService categoryService, string value, string model) { return categoryService.GetCategories(model).Result .Items.Any(x => x.Code.Contains(value)); } }
And the ICategoryService is the Service who retreives the data from an external Endpoint it uses a lot of DI:
public class CategoryService : ICategoryService { private readonly ILogger<CategoryService> logger;
/// <summary> /// Constructor to inject dependencies /// </summary> /// <param name="logger">Object to have a trace</param> public CategoryService(ILogger<CategoryService> logger, IConfiguration config, IMemoryCache cache) { this.logger = logger; this.logger.LogDebug($"Starting dependency injection: {nameof(CategoryService)}");
this.Configuration = config;
this.logger.LogDebug($"Retrieve PL/CAL credentials from appsettings"); //here we load some Config from appsettings, not relevant
this.cache = cache; }
public CategoriesResponse GetCategories(string request) { this.logger.LogDebug($"Request received at {nameof(CategoryService)}.{nameof(GetCategories)}"); this.logger.LogDebug($"Trying to get {0} from cache", request); if (!cache.TryGetValue(request, out var response)) { this.logger.LogDebug($"Failed to retrieve {0} from cache. Asking to endpoint", request);
response = RetrieveFromEndpoint(request);
var cacheEntryOptions = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(TimeSpan.FromHours(24));
this.logger.LogDebug($"Storing {0} to cache", request);
cache.Set(request, response, cacheEntryOptions); } else { this.logger.LogDebug($" {0} retrieved from cache", request); } return response as CategoriesResponse; }
[...]
}
So, all this system is perfectly working on Visual Studio, but when we deploy at DEV environment it throws an exception at CategoriesValidation in the line where we do the call to the GetCategories. It says that categoryService is null....
I tried to avoid using CategoriesValidation as middleware inserting its call to GetCategories directly on the Attribute definition at IsValidPetAgainstCategories, but I get the same error just in DEV, not in local... This is really frustrating... Someone
has some idea what can be happening?
Could you share a simple demo that could reproduce the issue?I try to simplify your code and test it,but `validator` always be null on localhost in the following line.How did you test the Model?
but when we deploy at DEV environment it throws an exception at CategoriesValidation in the line where we do the call to the GetCategories. It says that categoryService is null....
What is your DEV environment?Where did you deploy?
Best Regards,
Rena
.NET forums are moving to a new home on Microsoft Q&A, we encourage you to go to Microsoft Q&A for .NET for posting new questions and get involved today.
None
0 Points
1 Post
.Net Core 2.1 -- MVC API -- ValidationAttribute fails as Service is null
Dec 18, 2019 11:00 AM|Luis Agudo|LINK
Hi all,
I need to validate some properties of a model against the retreived data from one Service used in another controller. I used a Validation Attribute as is recomended:
[Section1Validator]
[IsValidPetAgainstCategories]
public class PetInfoModel
{ [...]
The definition of this ValidationAttribute uses the ValidationContext to retrieve the ValidationService:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class IsValidPetAgainstCategories : ValidationAttribute
{
public IsValidPetAgainstCategories() { }
/// <summary>
/// Check if string is in an array of accepted values
/// </summary>
/// <param name="value"></param>
/// <param name="validationContext"></param>
/// <returns></returns>
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var validator = (ICategoriesValidation)validationContext
.GetService(typeof(ICategoriesValidation));
var categoryService = (ICategoryService)validationContext
.GetService(typeof(ICategoryService));
var pet = value as PetInfoModel;
//------------------------
// Checking for Pet Breed type
//------------------------
if (pet.PetType.Equals(PetType.NWA_PET_D.ToString()))
{
if(!validator.isFieldValid(categoryService, pet.PetBreedType, Categories.DOGBREEDTYPE))
return new ValidationResult(PetErrorStrings.INVALID_PET_BREED_TYPE);
}[...]
This ICategoriesValidator is just a middleware to make the call to the retriever service and do the validation logic as follows:
public class CategoriesValidation : ICategoriesValidation
{
public bool isFieldValid(ICategoryService categoryService, string value, string model)
{
return categoryService.GetCategories(model).Result
.Items.Any(x => x.Code.Contains(value));
}
}
And the ICategoryService is the Service who retreives the data from an external Endpoint it uses a lot of DI:
public class CategoryService : ICategoryService
{
private readonly ILogger<CategoryService> logger;
private readonly IConfiguration Configuration;
private readonly PLHeaderConfiguration RSAHeader;
private readonly PLSecurityConfiguration RSASecurity;
private readonly CategoriesConfiguration CategoriesConfiguration;
private readonly SoapLoggerConfiguration SoapLoggerConfiguration;
private readonly IMemoryCache cache;
/// <summary>
/// Constructor to inject dependencies
/// </summary>
/// <param name="logger">Object to have a trace</param>
public CategoryService(ILogger<CategoryService> logger, IConfiguration config, IMemoryCache cache)
{
this.logger = logger;
this.logger.LogDebug($"Starting dependency injection: {nameof(CategoryService)}");
this.Configuration = config;
this.logger.LogDebug($"Retrieve PL/CAL credentials from appsettings");
//here we load some Config from appsettings, not relevant
this.cache = cache;
}
public CategoriesResponse GetCategories(string request)
{
this.logger.LogDebug($"Request received at {nameof(CategoryService)}.{nameof(GetCategories)}");
this.logger.LogDebug($"Trying to get {0} from cache", request);
if (!cache.TryGetValue(request, out var response))
{
this.logger.LogDebug($"Failed to retrieve {0} from cache. Asking to endpoint", request);
response = RetrieveFromEndpoint(request);
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromHours(24));
this.logger.LogDebug($"Storing {0} to cache", request);
cache.Set(request, response, cacheEntryOptions);
}
else
{
this.logger.LogDebug($" {0} retrieved from cache", request);
}
return response as CategoriesResponse;
}
[...]
}
So, all this system is perfectly working on Visual Studio, but when we deploy at DEV environment it throws an exception at CategoriesValidation in the line where we do the call to the GetCategories. It says that categoryService is null....
I tried to avoid using CategoriesValidation as middleware inserting its call to GetCategories directly on the Attribute definition at IsValidPetAgainstCategories, but I get the same error just in DEV, not in local... This is really frustrating... Someone has some idea what can be happening?
Contributor
2690 Points
874 Posts
Re: .Net Core 2.1 -- MVC API -- ValidationAttribute fails as Service is null
Dec 19, 2019 08:05 AM|Rena Ni|LINK
Hi Luis Agudo,
Could you share a simple demo that could reproduce the issue?I try to simplify your code and test it,but `validator` always be null on localhost in the following line.How did you test the Model?
What is your DEV environment?Where did you deploy?
Best Regards,
Rena