Skip to content

Commit f264aec

Browse files
authored
fix: Add null checks, set lists to empty if null (#434)
1 parent 4ae007d commit f264aec

File tree

5 files changed

+41
-34
lines changed

5 files changed

+41
-34
lines changed

src/Digdir.Domain.Dialogporten.Application/Common/Extensions/Enumerables/General.cs

+2
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ namespace Digdir.Domain.Dialogporten.Application.Common.Extensions.Enumerables;
66
internal static class General
77
{
88
internal static bool IsNullOrEmpty([NotNullWhen(false)] this ICollection? values) => values is null || values.Count == 0;
9+
10+
internal static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T>? enumerable) => enumerable ?? Enumerable.Empty<T>();
911
}

src/Digdir.Domain.Dialogporten.Application/Common/Extensions/FluentValidation/FluentValidation_Enumerable_Extensions.cs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using FluentValidation;
22
using FluentValidation.Internal;
33
using System.Linq.Expressions;
4+
using Digdir.Domain.Dialogporten.Application.Common.Extensions.Enumerables;
45

56
namespace Digdir.Domain.Dialogporten.Application.Common.Extensions.FluentValidation;
67

@@ -14,6 +15,11 @@ public static IRuleBuilderOptions<T, IEnumerable<TProperty>> UniqueBy<T, TProper
1415
{
1516
return ruleBuilder.Must((parent, enumerable, ctx) =>
1617
{
18+
if (enumerable is null)
19+
{
20+
return true;
21+
}
22+
1723
comparer ??= EqualityComparer<TKey>.Default;
1824
var duplicateKeys = enumerable
1925
.Select(keySelector)
@@ -34,7 +40,7 @@ public static IRuleBuilderOptions<T, TDependent> IsIn<T, TDependent, TPrincipal,
3440
Func<TPrincipal, TKey> principalKeySelector,
3541
IEqualityComparer<TKey>? comparer = null)
3642
{
37-
return ruleBuilder.Must((parrent, dependent, ctx) =>
43+
return ruleBuilder.Must((parent, dependent, ctx) =>
3844
{
3945
comparer ??= EqualityComparer<TKey>.Default;
4046
var dependentKey = dependentKeySelector(dependent);
@@ -45,7 +51,8 @@ public static IRuleBuilderOptions<T, TDependent> IsIn<T, TDependent, TPrincipal,
4551
.AppendArgument("DependentKey", dependentKey)
4652
.AppendArgument("PrincipalName", name);
4753
return dependentKey is null ||
48-
func(parrent)
54+
func(parent)
55+
.EmptyIfNull()
4956
.Any(principal => comparer
5057
.Equals(principalKeySelector(principal), dependentKey));
5158
})

src/Digdir.Domain.Dialogporten.Application/Externals/IDialogDbContext.cs

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Elements;
55
using Digdir.Domain.Dialogporten.Domain.Outboxes;
66
using Digdir.Library.Entity.Abstractions.Features.Identifiable;
7-
using Digdir.Library.Entity.Abstractions.Features.Versionable;
87
using Microsoft.EntityFrameworkCore;
98
using System.Linq.Expressions;
109

src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogCommandValidator.cs

+16-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Digdir.Domain.Dialogporten.Application.Common.Extensions.FluentValidation;
1+
using Digdir.Domain.Dialogporten.Application.Common.Extensions.Enumerables;
2+
using Digdir.Domain.Dialogporten.Application.Common.Extensions.FluentValidation;
23
using Digdir.Domain.Dialogporten.Application.Features.V1.Common.Localizations;
34
using Digdir.Domain.Dialogporten.Domain.Common;
45
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions;
@@ -63,33 +64,31 @@ public CreateDialogCommandValidator(
6364
.IsInEnum();
6465

6566
RuleFor(x => x.Content)
66-
.NotNull()
67-
.DependentRules(() =>
68-
{
69-
RuleFor(x => x.Content)
70-
.UniqueBy(x => x.Type)
71-
.Must(content => DialogContentType.RequiredTypes
72-
.All(requiredContent => content
73-
.Select(x => x.Type)
74-
.Contains(requiredContent)))
75-
.WithMessage("Dialog must contain the following content: " +
76-
$"[{string.Join(", ", DialogContentType.RequiredTypes)}].")
77-
.ForEach(x => x.SetValidator(contentValidator));
78-
});
67+
.UniqueBy(x => x.Type)
68+
.Must(content => DialogContentType.RequiredTypes
69+
.All(requiredContent => content
70+
.EmptyIfNull()
71+
.Select(x => x.Type)
72+
.Contains(requiredContent)))
73+
.WithMessage("Dialog must contain the following content: " +
74+
$"[{string.Join(", ", DialogContentType.RequiredTypes)}].")
75+
.ForEach(x => x.SetValidator(contentValidator));
7976

80-
RuleForEach(x => x.SearchTags)
81-
.SetValidator(searchTagValidator);
8277
RuleFor(x => x.SearchTags)
83-
.UniqueBy(x => x.Value, StringComparer.InvariantCultureIgnoreCase);
78+
.UniqueBy(x => x.Value, StringComparer.InvariantCultureIgnoreCase)
79+
.ForEach(x => x.SetValidator(searchTagValidator));
8480

8581
RuleFor(x => x.GuiActions)
8682
.Must(x => x
83+
.EmptyIfNull()
8784
.Count(x => x.Priority == DialogGuiActionPriority.Values.Primary) <= 1)
8885
.WithMessage("Only one primary GUI action is allowed.")
8986
.Must(x => x
87+
.EmptyIfNull()
9088
.Count(x => x.Priority == DialogGuiActionPriority.Values.Secondary) <= 1)
9189
.WithMessage("Only one secondary GUI action is allowed.")
9290
.Must(x => x
91+
.EmptyIfNull()
9392
.Count(x => x.Priority == DialogGuiActionPriority.Values.Tertiary) <= 5)
9493
.WithMessage("Only five tertiary GUI actions are allowed.")
9594
.ForEach(x => x.SetValidator(guiActionValidator));

src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Update/UpdateDialogCommandValidator.cs

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Digdir.Domain.Dialogporten.Application.Common.Extensions.FluentValidation;
1+
using Digdir.Domain.Dialogporten.Application.Common.Extensions.Enumerables;
2+
using Digdir.Domain.Dialogporten.Application.Common.Extensions.FluentValidation;
23
using Digdir.Domain.Dialogporten.Application.Features.V1.Common.Localizations;
34
using Digdir.Domain.Dialogporten.Domain.Common;
45
using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions;
@@ -56,32 +57,31 @@ public UpdateDialogDtoValidator(
5657
.IsInEnum();
5758

5859
RuleFor(x => x.Content)
59-
.NotNull()
60-
.DependentRules(() =>
61-
{
62-
RuleFor(x => x.Content)
63-
.UniqueBy(x => x.Type)
64-
.Must(content => DialogContentType.RequiredTypes
65-
.All(requiredContent => content
66-
.Select(x => x.Type)
67-
.Contains(requiredContent)))
68-
.WithMessage("Dialog must contain the following content: " +
69-
$"[{string.Join(", ", DialogContentType.RequiredTypes)}].")
70-
.ForEach(x => x.SetValidator(contentValidator));
71-
});
60+
.UniqueBy(x => x.Type)
61+
.Must(content => DialogContentType.RequiredTypes
62+
.All(requiredContent => content
63+
.EmptyIfNull()
64+
.Select(x => x.Type)
65+
.Contains(requiredContent)))
66+
.WithMessage("Dialog must contain the following content: " +
67+
$"[{string.Join(", ", DialogContentType.RequiredTypes)}].")
68+
.ForEach(x => x.SetValidator(contentValidator));
7269

7370
RuleFor(x => x.SearchTags)
7471
.UniqueBy(x => x.Value, StringComparer.InvariantCultureIgnoreCase)
7572
.ForEach(x => x.SetValidator(searchTagValidator));
7673

7774
RuleFor(x => x.GuiActions)
7875
.Must(x => x
76+
.EmptyIfNull()
7977
.Count(x => x.Priority == DialogGuiActionPriority.Values.Primary) <= 1)
8078
.WithMessage("Only one primary GUI action is allowed.")
8179
.Must(x => x
80+
.EmptyIfNull()
8281
.Count(x => x.Priority == DialogGuiActionPriority.Values.Secondary) <= 1)
8382
.WithMessage("Only one secondary GUI action is allowed.")
8483
.Must(x => x
84+
.EmptyIfNull()
8585
.Count(x => x.Priority == DialogGuiActionPriority.Values.Tertiary) <= 5)
8686
.WithMessage("Only five tertiary GUI actions are allowed.")
8787
.UniqueBy(x => x.Id)

0 commit comments

Comments
 (0)