sync full source from private myoffice

This commit is contained in:
myoffice-sync
2026-08-05 10:55:09 +00:00
parent 874796c860
commit 405abdfe69
714 changed files with 70352 additions and 234 deletions
@@ -0,0 +1,35 @@
namespace MyOffice.Web.Infrastructure.Attributes
{
using System.ComponentModel.DataAnnotations;
using Core.Extensions;
public class AsGuidAttribute: ValidationAttribute
{
private readonly bool _nullable;
public AsGuidAttribute(bool nullable = false)
{
_nullable = nullable;
}
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
if (value == null && _nullable)
{
return ValidationResult.Success;
}
if (value == null || value.ToString().IsMissing())
{
return new ValidationResult("Id parameter is not valid");
}
if (!Guid.TryParse(value.ToString(), out _))
{
return new ValidationResult("Id parameter is not valid");
}
return ValidationResult.Success;
}
}
}
@@ -0,0 +1,71 @@
namespace MyOffice.Web.Infrastructure.Attributes;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.ModelBinding;
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class DefaultFromBodyAttribute : Attribute
{
}
public class DefaultFromBodyBindingConvention : IActionModelConvention
{
public void Apply(ActionModel action)
{
if (action == null)
{
throw new ArgumentNullException(nameof(action));
}
if (action.Controller.Attributes.Any(x => x is DefaultFromBodyAttribute))
{
foreach (var parameter in action.Parameters)
{
if (parameter.Attributes.Any(x =>
x is FromQueryAttribute
or FromRouteAttribute
or FromHeaderAttribute
or FromFormAttribute
or FromServicesAttribute))
{
continue;
}
// Already bound (e.g. CancellationToken → Special) — do not force Body.
if (parameter.BindingInfo?.BindingSource is { } existing
&& existing != BindingSource.ModelBinding
&& existing != BindingSource.Custom)
{
continue;
}
var paramType = parameter.ParameterInfo.ParameterType;
if (paramType == typeof(CancellationToken)
|| Nullable.GetUnderlyingType(paramType) == typeof(CancellationToken))
{
continue;
}
var isSimpleType = paramType.IsPrimitive
|| paramType.IsEnum
|| paramType == typeof(string)
|| paramType == typeof(decimal)
|| paramType == typeof(Guid)
|| paramType == typeof(Guid?)
|| paramType == typeof(DateTime)
|| paramType == typeof(DateTime?)
|| paramType == typeof(DateOnly)
|| paramType == typeof(DateOnly?)
|| paramType == typeof(TimeOnly)
|| paramType == typeof(TimeOnly?);
if (!isSimpleType)
{
parameter.BindingInfo ??= new BindingInfo();
parameter.BindingInfo.BindingSource = BindingSource.Body;
}
}
}
}
}
@@ -0,0 +1,28 @@
namespace MyOffice.Web.Infrastructure.Attributes;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Infrastructure;
public class GlobalModelStateValidatorAttribute : ActionFilterAttribute
{
private readonly ProblemDetailsFactory _problemDetailsFactory;
public GlobalModelStateValidatorAttribute(ProblemDetailsFactory problemDetailsFactory)
{
_problemDetailsFactory = problemDetailsFactory;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
context.Result = new ObjectResult(_problemDetailsFactory.CreateValidationProblemDetails(context.HttpContext, context.ModelState))
{
StatusCode = StatusCodes.Status400BadRequest
};
}
base.OnActionExecuting(context);
}
}