CreateMap<ExportRetail, ExportRetailDto>()
.ForMember(dest => dest.ExportRetailNomenklatura, opt => opt.MapFrom((src, dest, _, ctx) =>
ExpandHelper.MapWithDepthControl(src, ctx, (source, depth) =>
src.ExportRetailNomenklaturaId == null ? null : ExpandHelper.HasExpand(ctx, "nomenklatura", depth)
? ctx.Mapper.Map<NomenklaturaDto>(src.ExportRetailNomenklatura)
: new NomenklaturaDto { InternalId = src.ExportRetailNomenklaturaId.Value })))
public enum ExpandMatchMode
{
Exact,
StartsWith,
EndsWith,
Contains
}
public static class ExpandHelper
{
public static bool HasExpand(ResolutionContext ctx, string pattern, int depth = 0)
{
return ctx.Items.TryGetValue("expand", out var obj) &&
obj is string[] expandArray &&
expandArray.Any(expandItem =>
{
var segments = expandItem.Split('.');
return depth >= 0 &&
depth < segments.Length &&
segments[depth].Equals(pattern, StringComparison.OrdinalIgnoreCase);
});
}
public static TResult MapWithDepthControl<TSource, TResult>(
TSource source,
ResolutionContext ctx,
Func<TSource, int, TResult> mappingFunc)
{
int currentDepth = GetOrInitializeDepth(ctx);
// Увеличиваем глубину для вложенных вызовов
ctx.Items["TypeDepth"] = currentDepth + 1;
try
{
return mappingFunc(source, currentDepth);
}
finally
{
// Восстанавливаем оригинальную глубину
ctx.Items["TypeDepth"] = currentDepth;
}
}
private static int GetOrInitializeDepth(ResolutionContext ctx)
{
if (!ctx.Items.TryGetValue("TypeDepth", out var depthObj))
{
depthObj = 0;
ctx.Items["TypeDepth"] = depthObj;
}
return (int)depthObj;
}
}
}
public class ResponseResult<T> : IResponseResult<T>
{
public bool IsSuccess { get; private set; }
public ProblemDetails? Error { get; private set; }
public T? Data { get; private set; }
public static ResponseResult<T> Success(T data) => new ResponseResult<T> { IsSuccess = true, Data = data };
public static ResponseResult<T> Success() => new ResponseResult<T> { IsSuccess = true};
public static ResponseResult<T> Failure(Exception exception) => new ResponseResult<T>
{
IsSuccess = false,
Error = new ProblemDetails
{
Title = GetTitleByException(exception),
Detail = exception.Message,
Status = exception switch
{
ArgumentException => StatusCodes.Status400BadRequest,
KeyNotFoundException => StatusCodes.Status404NotFound,
UnauthorizedAccessException => StatusCodes.Status401Unauthorized,
_ => StatusCodes.Status500InternalServerError
},
Instance = Guid.NewGuid().ToString()
}
};
private static string GetTitleByException(Exception exception) =>
exception switch
{
ArgumentException => "Invalid argument",
KeyNotFoundException => "Resource not found",
UnauthorizedAccessException => "Unauthorized",
_ => "Internal server error"
};
}
return ResponseResult<bool>.Failure(
new KeyNotFoundException(
string.Format("User with login '{0}' not found", request.Login))
);
[HttpGet("verify")]
public async Task<ActionResult> VerifyUser(
[FromQuery] string login,
[FromQuery] string password,
CancellationToken cancellationToken)
{
var result = await mediator.Send(new VerifyQuery() { Login = login, Password = password }, cancellationToken);
if (result.IsSuccess)
{
return Ok(new { verify = result.Data });
}
return StatusCode(result.Error?.Status ?? 400, result.Error);
}