(feature): simplify patch request fields management for frontend validation like zod

This commit is contained in:
Maksym Sadovnychyy 2024-12-14 17:54:06 +01:00
parent 2e2036c90d
commit eaa610a853
5 changed files with 29 additions and 39 deletions

View File

@ -1945,22 +1945,7 @@ var response = new PagedResponse<User>(users, totalCount: 100, pageNumber: 1, pa
--- ---
#### **3. `PatchField<T>`** #### **3. `PatchOperation`**
##### Summary
Represents a patch operation on a specific field or value, used for partial updates in Web APIs.
##### Usage
```csharp
var patchField = new PatchField<string> {
Operation = PatchOperation.Replace,
Value = "New Value"
};
```
---
#### **4. `PatchOperation`**
##### Summary ##### Summary
Enumerates the types of patch operations that can be performed on a field or collection. Enumerates the types of patch operations that can be performed on a field or collection.
@ -2008,13 +1993,18 @@ Console.WriteLine($"Total Pages: {pagedResponse.TotalPages}");
### Partial Updates Using PatchField ### Partial Updates Using PatchField
```csharp ```csharp
var patch = new PatchField<string> { var patch = new SomePatchRequestModel {
Operation = PatchOperation.Replace, Username = "Updated Name"
Value = "Updated Name"
Operations = new Dictionary<string, PatchOperation> {
{ "Username", PartchOperation.Replace }
}
}; };
// Deconstruct the patch field // Deconstruct the patch field
var (operation, value) = patch; var usernmae = patch.Username;
var operation = GetOperation(nameOf(patch.Username);
Console.WriteLine($"Operation: {operation}, Value: {value}"); Console.WriteLine($"Operation: {operation}, Value: {value}");
``` ```

View File

@ -1,17 +1,25 @@
using System.ComponentModel.DataAnnotations; using System.Reflection;
using System.Reflection; using System.ComponentModel.DataAnnotations;
using MaksIT.Core.Webapi.Models; using MaksIT.Core.Webapi.Models;
namespace MaksIT.Core.Abstractions.Webapi; namespace MaksIT.Core.Abstractions.Webapi;
public abstract class PatchRequestModelBase : RequestModelBase, IValidatableObject { public abstract class PatchRequestModelBase : RequestModelBase {
public Dictionary<string, PatchOperation> Operations = new Dictionary<string, PatchOperation>();
private bool HasNonNullPatchField => GetType() private bool HasNonNullPatchField => GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance) .GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(prop => prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(PatchField<>)) .Where(prop => prop.Name != nameof(Operations))
.Any(prop => prop.GetValue(this) != null); .Any(prop => prop.GetValue(this) != null);
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { public PatchOperation GetOperation(string propertyName) {
return Operations[propertyName];
}
public override IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (!HasNonNullPatchField) { if (!HasNonNullPatchField) {
yield return new ValidationResult("At least one patch field must be provided", new string[] { "PatchField" }); yield return new ValidationResult("At least one patch field must be provided", new string[] { "PatchField" });
} }

View File

@ -1,9 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace MaksIT.Core.Abstractions.Webapi; namespace MaksIT.Core.Abstractions.Webapi;
public abstract class RequestModelBase { public abstract class RequestModelBase : IValidatableObject {
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
return Enumerable.Empty<ValidationResult>();
}
} }

View File

@ -8,7 +8,7 @@
<!-- NuGet package metadata --> <!-- NuGet package metadata -->
<PackageId>MaksIT.Core</PackageId> <PackageId>MaksIT.Core</PackageId>
<Version>1.2.2</Version> <Version>1.2.3</Version>
<Authors>Maksym Sadovnychyy</Authors> <Authors>Maksym Sadovnychyy</Authors>
<Company>MAKS-IT</Company> <Company>MAKS-IT</Company>
<Product>MaksIT.Core</Product> <Product>MaksIT.Core</Product>

View File

@ -1,12 +0,0 @@

namespace MaksIT.Core.Webapi.Models;
public class PatchField<T> {
public PatchOperation Operation { get; set; }
public T? Value { get; set; }
public void Deconstruct(out PatchOperation operation, out T? value) {
operation = Operation;
value = Value;
}
}