4

I have the following request model :

public class VisitRequest
    {
        public ProviderInfo Provider { get; set; }

        [Required]
        [MaxLength(64)]
        public string PayerId { get; set; }
    }

And i have the custom class as follows :

 public class ProviderInfo
    {
        [Required]
        [MaxLength(15)]
        public string TaxId { get; set; }

        [Required(ErrorMessage = " Qualifier is required.")]
        [MaxLength(15)]
        public string NPI { get; set; }
    }

I am currently using ValidationContext to do the model validations :

var visitData = JsonConvert.DeserializeObject<VisitRequest>(jsonString);
var vc = new ValidationContext(visitData);
var errorResults = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(visitData, vc, errorResults, true);

My demo json request is as follows :

{
'Member': {
  'Qualifier': 'MedicaidID',
  'Identifier': '100'
  },                
  'ExternalVisitID': '123456789',
}

Now I am receiving the ErrorMessage in ErrorResult as :

PayerId is required.

But I am not getting the validations of the custom class. How to implement this in .Net Core Console application? I am quite new to .Net Core so any help would be appreciated.Thanks!


UPDATE :

I followed the answer given by @John H but still there is one issue .

If my request is :

'Provider' : {
      'TaxId' : null
}

it will work fine , because it is able to identify that this is the type ProviderInfo object.

But if my request does not contain any info regarding the Provider :

{
'ExternalVisitID': '123456789',
'EVVMSID': '100', 
}

then it is not able to validate the object.

CoderGuyy
  • 137
  • 1
  • 7

1 Answers1

4

In brief, this doesn't work because TryValidateObject doesn't support the validation of complex nested types. This was also an issue for the .NET Framework version of this type, and @reustmd created a NuGet Package to solve the problem. Unfortunately, it doesn't support .NET Core, but I found there is a package forked from this which does. From the readme:

Installation

Available as NuGet-Package dataannotationsvalidator:

Install-Package dataannotationsvalidator

Usage

See file DataAnnotationsValidator/DataAnnotationsValidator.Tests/DataAnnotationsValidatorTests.cs

Short example:

var validator = new DataAnnotationsValidator.DataAnnotationsValidator();

var validationResults = new List<ValidationResult>();

validator.TryValidateObjectRecursive(modelToValidate, validationResults);

This should solve your problem.

As an aside, I also found this proposal discussing adding this functionality to .NET. If you're interested in a technical design discussion of that proposal, there is a video posted by the .NET Foundation discussing it.

Update

For your scenario above, I've installed the above package, changed the VisitRequest class to make the provider required

public class VisitRequest
{
    [Required]
    public ProviderInfo Provider { get; set; }

    [Required]
    [MaxLength(64)]
    public string PayerId { get; set; }
}

and then ran the following:

var jsonString = @"{
    ""ExternalVisitID"": ""123456789"",
    ""EVVMSID"": ""100""
}";

var modelToValidate = JsonConvert.DeserializeObject<VisitRequest>(jsonString);

var validator = new DataAnnotationsValidator.DataAnnotationsValidator();

var validationResults = new List<ValidationResult>();

validator.TryValidateObjectRecursive(modelToValidate, validationResults);

foreach (var item in validationResults)
{
    Console.WriteLine(item.ErrorMessage);

    foreach (var memberName in item.MemberNames)
    {
        Console.WriteLine($"\t{memberName}");
    }
}

which produces output of:

The Provider field is required.
    Provider
The PayerId field is required.
    PayerId

If you're wanting to list each field of a provider that's missing individually, even though that part of the JSON is empty, I think you'll have to fork the NuGet package and make those changes. But this is probably a reason why .NET hasn't supported this functionality out of the box, because people have different expectations for how it should behave.

John H
  • 14,422
  • 4
  • 41
  • 74
  • 1
    Thank you so much for your help! I was trying to resolve this issue since 2 days. – CoderGuyy Sep 22 '20 at 15:04
  • @VivekSheth No problem. :) – John H Sep 22 '20 at 15:13
  • I am using this package but I am facing an issue can u please look into the UPDATE that I have added in the question. – CoderGuyy Sep 22 '20 at 15:47
  • @VivekSheth If you're wanting the `Provider` property to be required, then you should mark it with `[Required] public ProviderInfo Provider { get; set; }`. That will tell you that it's missing completely. As you have it right now, the `ProviderInfo` properties are only required _if_ you include `provider` in your JSON. – John H Sep 22 '20 at 15:59
  • I have already marked it [Required] but it still doesn't validate it if the JSON request does not contain the property. – CoderGuyy Sep 23 '20 at 04:58