Aspnetcore.docs: How to do Business Validation with ObjectGraphDataAnnotationsValidator & complex types?

Created on 27 Aug 2020  ยท  2Comments  ยท  Source: dotnet/AspNetCore.Docs

Making complex types validation with the ObjectGraphDataAnnotationsValidator works.

But how do you add custom errors with the CustomValidator to do business validation?
I tried to add error with the key ShipDescription.ShortDescription key, eg:

errors.Add("ShipDescription.ShortDescription", new List<string>() { "Some error" });
customValidator.DisplayErrors(errors);

But it didn't work.
I assume that was the key since the form models property path is starship.ShipDescription.ShortDescription.


Document Details

โš  Do not edit this section. It is required for docs.microsoft.com โžŸ GitHub issue linking.

Blazor P0 Source - Docs.ms doc-bug

Most helpful comment

Hello @Assassinbeast ... Sorry for the delay. I've been ๐Ÿƒ๐Ÿ˜… lately. I'll take a look at this and get back to you soon.

All 2 comments

Hello @Assassinbeast ... Sorry for the delay. I've been ๐Ÿƒ๐Ÿ˜… lately. I'll take a look at this and get back to you soon.

Ok ... It went well, except I did discover a nit along the way.

I set up a test like this ...

public class ShipDescription
{
    [Required]
    [StringLength(40, ErrorMessage = "Description too long (40 char).")]
    public string ShortDescription { get; set; }

    [Required]
    [StringLength(240, ErrorMessage = "Description too long (240 char).")]
    public string LongDescription { get; set; }
}

... with ...

[ValidateComplexType]
public ShipDescription ShipDescription { get; set; } = new ShipDescription();

... on my Starship class. NIT ... The current example doesn't new up the ShipDescription, so the code example from the topic fails if it isn't created somewhere before the fields are bound to the form. It could be done in the component, too, like this ...

private Starship starship = new Starship()
                            {
                                ProductionDate = DateTime.UtcNow,
                                ShipDescription = new ShipDescription()
                            };

The simplest way to go tho is just to add a = new ShipDescription(); in the class to make it happy and load the component without an NRE.

I use the same CustomValidator component described earlier in the topic.

The form gets ...

<EditForm Model="@starship" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ObjectGraphDataAnnotationsValidator />
    <CustomValidator @ref="customValidator" />
    <ValidationSummary />

    ...

... with ...

<p>
    <label>
        Long Description:
        <InputTextArea @bind-Value="starship.ShipDescription.LongDescription" />
    </label>
</p>
<p>
    <label>
        Short Description:
        <InputTextArea @bind-Value="starship.ShipDescription.ShortDescription" />
    </label>
</p>

... and ...

private CustomValidator customValidator;

I then add a custom check to see if the LongDescription starts with a capital letter ...

private void HandleValidSubmit()
{
    customValidator.ClearErrors();

    var errors = new Dictionary<string, List<string>>();

    char[] ldesc = starship.ShipDescription.LongDescription.ToCharArray();
    var startsUppercase = char.IsUpper(ldesc[0]);

    if (!startsUppercase)
    {
        errors.Add(nameof(starship.ShipDescription.LongDescription),
            new List<string>() { "The Long Description must start with an uppercase character." });
    }

    if (errors.Count() > 0)
    {
        customValidator.DisplayErrors(errors);
    }
    else
    {
        formStatus = "The form processed successfully!";
    }
}

..... sooooo .... It's all just about as expected with the explanation provided in the Business logic validation section.

I do want to fix that nit.

In the code that you showed, I used nameof to avoid the magic string. nameof(starship.ShipDescription.LongDescription) evaluates to ...

LongDescription

... that's it. If you prefer that โœจ magic string โœจ, try it as ...

errors.Add("ShortDescription", new List<string>() { "Some error" });

Leave this issue open. It will close when the PR merges for that nit that I identified.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fabich picture fabich  ยท  3Comments

Rick-Anderson picture Rick-Anderson  ยท  3Comments

wgutierrezr picture wgutierrezr  ยท  3Comments

nenmyx picture nenmyx  ยท  3Comments

Raghumu picture Raghumu  ยท  3Comments