Skip to content

Commit

Permalink
Merge pull request #817 from neozhu/refaactor/o3
Browse files Browse the repository at this point in the history
Refactor Codebase with ChatGPT o3-mini-hight
  • Loading branch information
neozhu authored Feb 19, 2025
2 parents b2809dd + 3da977f commit 79b50c7
Show file tree
Hide file tree
Showing 62 changed files with 2,305 additions and 1,893 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This repository hosts a Blazor Server application designed using Clean Architect
## Explore the Live Demo

Experience the application in action in Blazor Server mode by visiting:

- Home Server: [cleanserver.blazors.app:8443](https://cleanserver.blazors.app:8443/)
- MS SQL Database: [architecture.blazorserver.com](https://architecture.blazorserver.com/)

- PostgreSQL Database: [architecture.blazors.app](https://architecture.blazors.app/)
Expand Down
16 changes: 8 additions & 8 deletions src/Application/Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<LangVersion>default</LangVersion>
</PropertyGroup>
<ItemGroup>

<PackageReference Include="SixLabors.ImageSharp" Version="3.1.6" />
<PackageReference Include="Ardalis.Specification" Version="8.0.0" />
<PackageReference Include="Ardalis.Specification.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="ClosedXML" Version="0.105.0-rc" />
Expand All @@ -17,15 +17,15 @@
<PackageReference Include="jcamp.FluentEmail.Razor" Version="3.8.0" />
<PackageReference Include="FluentValidation" Version="12.0.0-preview1" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="12.0.0-preview1" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="9.0.1" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="9.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="9.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Riok.Mapperly" Version="4.2.0-next.0" />
<PackageReference Include="Hangfire.Core" Version="1.8.17" />
<PackageReference Include="ZiggyCreatures.FusionCache" Version="2.0.0" />
<PackageReference Include="ActualLab.Fusion" Version="9.8.17" />
<PackageReference Include="ActualLab.Fusion.Blazor" Version="9.8.17" />
<PackageReference Include="ActualLab.Generators" Version="9.8.17">
<PackageReference Include="Hangfire.Core" Version="1.8.18" />
<PackageReference Include="ZiggyCreatures.FusionCache" Version="2.1.0" />
<PackageReference Include="ActualLab.Fusion" Version="9.8.37" />
<PackageReference Include="ActualLab.Fusion.Blazor" Version="9.8.37" />
<PackageReference Include="ActualLab.Generators" Version="9.8.37">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
11 changes: 0 additions & 11 deletions src/Application/Common/ExceptionHandlers/ConflictException.cs

This file was deleted.

This file was deleted.

This file was deleted.

11 changes: 0 additions & 11 deletions src/Application/Common/ExceptionHandlers/UnauthorizedException.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@ public class
where TResponse : Result<int>
where TException : ValidationException
{
private readonly ILogger<ValidationExceptionHandler<TRequest, TResponse, TException>> _logger;

public ValidationExceptionHandler(ILogger<ValidationExceptionHandler<TRequest, TResponse, TException>> logger)
{
_logger = logger;
}

public Task Handle(TRequest request, TException exception, RequestExceptionHandlerState<TResponse> state,
CancellationToken cancellationToken)
Expand Down
4 changes: 4 additions & 0 deletions src/Application/Common/Interfaces/IUploadService.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using SixLabors.ImageSharp.Processing;

namespace CleanArchitecture.Blazor.Application.Common.Interfaces;

public interface IUploadService
{
Task<string> UploadAsync(UploadRequest request);
void Remove(string filename);

Task<string> UploadImageAsync(Stream imageStream, UploadType uploadType, ResizeOptions? resizeOptions = null, string? fileName=null);
}

This file was deleted.

192 changes: 149 additions & 43 deletions src/Application/Common/Models/Result.cs
Original file line number Diff line number Diff line change
@@ -1,65 +1,171 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace CleanArchitecture.Blazor.Application.Common.Models;
namespace CleanArchitecture.Blazor.Application.Common.Models;

/// <summary>
/// Represents the result of an operation.
/// </summary>
public class Result : IResult
{
internal Result()
{
Errors = new string[] { };
}

internal Result(bool succeeded, IEnumerable<string> errors)
/// <summary>
/// Protected constructor to initialize the result.
/// </summary>
/// <param name="succeeded">Indicates whether the operation succeeded.</param>
/// <param name="errors">A collection of error messages.</param>
protected Result(bool succeeded, IEnumerable<string>? errors)
{
Succeeded = succeeded;
Errors = errors.ToArray();
Errors = errors?.ToArray() ?? Array.Empty<string>();
}

public string ErrorMessage => string.Join(", ", Errors ?? new string[] { });

/// <summary>
/// Indicates whether the operation succeeded.
/// </summary>
public bool Succeeded { get; init; }

/// <summary>
/// An array of error messages.
/// </summary>
public string[] Errors { get; init; }

/// <summary>
/// Gets a concatenated string of error messages, separated by commas.
/// </summary>
public string ErrorMessage => string.Join(", ", Errors);

/// <summary>
/// Creates a successful <see cref="Result"/> instance.
/// </summary>
public static Result Success() => new Result(true, Array.Empty<string>());

/// <summary>
/// Asynchronously creates a successful <see cref="Result"/> instance.
/// </summary>
public static Task<Result> SuccessAsync() => Task.FromResult(Success());
public static Result Failure(params string[] errors) => new Result(false, errors);
public static Task<Result> FailureAsync(params string[] errors) => Task.FromResult(Failure(errors));

// Functional extensions
public TResult Match<TResult>(Func<TResult> onSuccess, Func<string, TResult> onFailure) =>
Succeeded ? onSuccess() : onFailure(ErrorMessage);
/// <summary>
/// Creates a failed <see cref="Result"/> instance.
/// </summary>
/// <param name="errors">Error messages.</param>
public static Result Failure(params string[] errors) => new Result(false, errors);

/// <summary>
/// Asynchronously creates a failed <see cref="Result"/> instance.
/// </summary>
/// <param name="errors">Error messages.</param>
public static Task<Result> FailureAsync(params string[] errors) => Task.FromResult(Failure(errors));

public async Task<TResult> MatchAsync<TResult>(Func<Task<TResult>> onSuccess, Func<string, Task<TResult>> onFailure) =>
Succeeded ? await onSuccess() : await onFailure(ErrorMessage);
/// <summary>
/// Executes the appropriate function based on whether the operation succeeded.
/// </summary>
/// <typeparam name="TResult">The return type.</typeparam>
/// <param name="onSuccess">Function to execute if the operation succeeded.</param>
/// <param name="onFailure">Function to execute if the operation failed, with an error message.</param>
public TResult Match<TResult>(Func<TResult> onSuccess, Func<string, TResult> onFailure)
=> Succeeded ? onSuccess() : onFailure(ErrorMessage);

/// <summary>
/// Asynchronously executes the appropriate function based on whether the operation succeeded.
/// </summary>
/// <typeparam name="TResult">The return type.</typeparam>
/// <param name="onSuccess">Asynchronous function to execute if the operation succeeded.</param>
/// <param name="onFailure">Asynchronous function to execute if the operation failed, with an error message.</param>
public Task<TResult> MatchAsync<TResult>(Func<Task<TResult>> onSuccess, Func<string, Task<TResult>> onFailure)
=> Succeeded ? onSuccess() : onFailure(ErrorMessage);
}

/// <summary>
/// Represents the result of an operation that includes data.
/// </summary>
/// <typeparam name="T">The type of the data.</typeparam>
public class Result<T> : Result, IResult<T>
{
public T? Data { get; set; }
public static Result<T> Success(T data) => new Result<T> { Succeeded= true, Data= data };
public static Task<Result<T>> SuccessAsync(T data) => Task.FromResult(Success(data));
public static new Result<T> Failure(params string[] errors) => new Result<T> { Succeeded = false, Errors = errors.ToArray() };
public static new Task<Result<T>> FailureAsync(params string[] errors) => Task.FromResult(new Result<T> { Succeeded = false, Errors = errors.ToArray() });

// Functional extensions
public TResult Match<TResult>(Func<T, TResult> onSuccess, Func<string, TResult> onFailure) =>
Succeeded ? onSuccess(Data!) : onFailure(ErrorMessage);

public async Task<TResult> MatchAsync<TResult>(Func<T, Task<TResult>> onSuccess, Func<string, Task<TResult>> onFailure) =>
Succeeded ? await onSuccess(Data!) : await onFailure(ErrorMessage);

public Result<TResult> Map<TResult>(Func<T, TResult> map) =>
Succeeded ? Result<TResult>.Success(map(Data!)) : Result<TResult>.Failure(Errors);

public async Task<Result<TResult>> MapAsync<TResult>(Func<T, Task<TResult>> map) =>
Succeeded ? Result<TResult>.Success(await map(Data!)) : await Result<TResult>.FailureAsync(Errors);
/// <summary>
/// The data contained in the result.
/// </summary>
public T? Data { get; init; }

/// <summary>
/// Protected constructor to initialize a result with data.
/// </summary>
/// <param name="succeeded">Indicates whether the operation succeeded.</param>
/// <param name="errors">A collection of error messages.</param>
/// <param name="data">The data returned from the operation.</param>
protected Result(bool succeeded, IEnumerable<string>? errors, T? data)
: base(succeeded, errors)
{
Data = data;
}

public Result<TResult> Bind<TResult>(Func<T, Result<TResult>> bind) =>
Succeeded ? bind(Data!) : Result<TResult>.Failure(Errors);
/// <summary>
/// Creates a successful <see cref="Result{T}"/> instance with the specified data.
/// </summary>
/// <param name="data">The data to include in the result.</param>
public static Result<T> Success(T data) => new Result<T>(true, Array.Empty<string>(), data);

public async Task<Result<TResult>> BindAsync<TResult>(Func<T, Task<Result<TResult>>> bind) =>
Succeeded ? await bind(Data!) : await Result<TResult>.FailureAsync(Errors);
/// <summary>
/// Asynchronously creates a successful <see cref="Result{T}"/> instance with the specified data.
/// </summary>
/// <param name="data">The data to include in the result.</param>
public static Task<Result<T>> SuccessAsync(T data) => Task.FromResult(Success(data));

}
/// <summary>
/// Creates a failed <see cref="Result{T}"/> instance.
/// </summary>
/// <param name="errors">Error messages.</param>
public static new Result<T> Failure(params string[] errors) => new Result<T>(false, errors, default);

/// <summary>
/// Asynchronously creates a failed <see cref="Result{T}"/> instance.
/// </summary>
/// <param name="errors">Error messages.</param>
public static new Task<Result<T>> FailureAsync(params string[] errors) => Task.FromResult(Failure(errors));

/// <summary>
/// Executes the appropriate function based on whether the operation succeeded.
/// </summary>
/// <typeparam name="TResult">The return type.</typeparam>
/// <param name="onSuccess">Function to execute if the operation succeeded, with the data.</param>
/// <param name="onFailure">Function to execute if the operation failed, with an error message.</param>
public TResult Match<TResult>(Func<T, TResult> onSuccess, Func<string, TResult> onFailure)
=> Succeeded ? onSuccess(Data!) : onFailure(ErrorMessage);

/// <summary>
/// Asynchronously executes the appropriate function based on whether the operation succeeded.
/// </summary>
/// <typeparam name="TResult">The return type.</typeparam>
/// <param name="onSuccess">Asynchronous function to execute if the operation succeeded, with the data.</param>
/// <param name="onFailure">Asynchronous function to execute if the operation failed, with an error message.</param>
public Task<TResult> MatchAsync<TResult>(Func<T, Task<TResult>> onSuccess, Func<string, Task<TResult>> onFailure)
=> Succeeded ? onSuccess(Data!) : onFailure(ErrorMessage);

/// <summary>
/// Maps the data contained in the result to a new type.
/// </summary>
/// <typeparam name="TResult">The type of the mapped data.</typeparam>
/// <param name="map">The mapping function.</param>
public Result<TResult> Map<TResult>(Func<T, TResult> map)
=> Succeeded ? Result<TResult>.Success(map(Data!)) : Result<TResult>.Failure(Errors);

/// <summary>
/// Asynchronously maps the data contained in the result to a new type.
/// </summary>
/// <typeparam name="TResult">The type of the mapped data.</typeparam>
/// <param name="map">The asynchronous mapping function.</param>
public async Task<Result<TResult>> MapAsync<TResult>(Func<T, Task<TResult>> map)
=> Succeeded ? Result<TResult>.Success(await map(Data!)) : await Result<TResult>.FailureAsync(Errors);

/// <summary>
/// Binds the result to another result, allowing for chaining operations.
/// </summary>
/// <typeparam name="TResult">The type of the data in the resulting result.</typeparam>
/// <param name="bind">The binding function that returns a new result.</param>
public Result<TResult> Bind<TResult>(Func<T, Result<TResult>> bind)
=> Succeeded ? bind(Data!) : Result<TResult>.Failure(Errors);

/// <summary>
/// Asynchronously binds the result to another result, allowing for chaining operations.
/// </summary>
/// <typeparam name="TResult">The type of the data in the resulting result.</typeparam>
/// <param name="bind">The asynchronous binding function that returns a new result.</param>
public async Task<Result<TResult>> BindAsync<TResult>(Func<T, Task<Result<TResult>>> bind)
=> Succeeded ? await bind(Data!) : await Result<TResult>.FailureAsync(Errors);
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,16 @@ public class ImportProductsCommandHandler :
private readonly IApplicationDbContext _context;
private readonly IExcelService _excelService;
private readonly IStringLocalizer<ImportProductsCommandHandler> _localizer;
private readonly ISerializer _serializer;

public ImportProductsCommandHandler(
IApplicationDbContext context,
IExcelService excelService,
ISerializer serializer,
IStringLocalizer<ImportProductsCommandHandler> localizer
)
{
_context = context;
_localizer = localizer;
_excelService = excelService;
_serializer = serializer;
}

public async Task<Result<byte[]>> Handle(CreateProductsTemplateCommand request, CancellationToken cancellationToken)
Expand Down Expand Up @@ -84,7 +81,7 @@ public async Task<Result<int>> Handle(ImportProductsCommand request, Cancellatio
_localizer["Pictures"],
(row, item) => item.Pictures = string.IsNullOrEmpty(row[_localizer["Pictures"]].ToString())
? new List<ProductImage>()
: _serializer.Deserialize<List<ProductImage>>(row[_localizer["Pictures"]].ToString())
: JsonSerializer.Deserialize<List<ProductImage>>(row[_localizer["Pictures"]].ToString())
}
}, _localizer["Products"]);
if (!result.Succeeded) return await Result<int>.FailureAsync(result.Errors);
Expand Down
Loading

0 comments on commit 79b50c7

Please sign in to comment.