Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Ahammdan committed May 25, 2024
2 parents f5f6817 + dce276b commit 4c4f23d
Show file tree
Hide file tree
Showing 15 changed files with 309 additions and 69 deletions.
4 changes: 3 additions & 1 deletion docs/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ GEM
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.6)
rexml (3.2.8)
strscan (>= 3.0.9)
rouge (4.1.3)
safe_yaml (1.0.5)
sass-embedded (1.67.0-x86_64-linux-gnu)
google-protobuf (~> 3.23)
strscan (3.1.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
unicode-display_width (2.4.2)
Expand Down
11 changes: 11 additions & 0 deletions sample/Ardalis.Result.Sample.Core/Services/BadResultService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Ardalis.Result.Sample.Core.Services;

public class BadResultService
{
public Result ReturnErrorWithMessage(string message)
{
var result = Result.Error(message);
return result;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,69 +7,67 @@
using System.Linq;
using System.Threading.Tasks;

namespace Ardalis.Result.Sample.Core.Services
namespace Ardalis.Result.Sample.Core.Services;
public class WeatherServiceWithExceptions
{
public class WeatherServiceWithExceptions
public WeatherServiceWithExceptions(IStringLocalizer<WeatherService> stringLocalizer)
{
public WeatherServiceWithExceptions(IStringLocalizer<WeatherService> stringLocalizer)
{
_stringLocalizer = stringLocalizer;
}
_stringLocalizer = stringLocalizer;
}

private static readonly string[] Summaries = new[]
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

private IStringLocalizer<WeatherService> _stringLocalizer;
private IStringLocalizer<WeatherService> _stringLocalizer;

public Task<IEnumerable<WeatherForecast>> GetForecastAsync(ForecastRequestDto model)
public Task<IEnumerable<WeatherForecast>> GetForecastAsync(ForecastRequestDto model)
{
return Task.FromResult(GetForecast(model));
}

public IEnumerable<WeatherForecast> GetForecast(ForecastRequestDto model)
{
switch (model.PostalCode)
{
return Task.FromResult(GetForecast(model));
case "NotFound":
throw new ForecastNotFoundException();
case "Conflict":
throw new ForecastConflictException();
}

public IEnumerable<WeatherForecast> GetForecast(ForecastRequestDto model)
// validate model
if (model.PostalCode.Length > 10)
{
switch (model.PostalCode)
throw new ForecastRequestInvalidException(new Dictionary<string, string>()
{
case "NotFound":
throw new ForecastNotFoundException();
case "Conflict":
throw new ForecastConflictException();
}
{ nameof(model.PostalCode), _stringLocalizer["PostalCode cannot exceed 10 characters."].Value }
});
}

// validate model
if (model.PostalCode.Length > 10)
// test single result value
if (model.PostalCode == "55555")
{
return new List<WeatherForecast>
{
throw new ForecastRequestInvalidException(new Dictionary<string, string>()
new WeatherForecast
{
{ nameof(model.PostalCode), _stringLocalizer["PostalCode cannot exceed 10 characters."].Value }
});
}
Date = DateTime.Now,
TemperatureC = 0,
Summary = Summaries[0]
}
};
}

// test single result value
if (model.PostalCode == "55555")
var rng = new Random();
return new List<WeatherForecast>(Enumerable.Range(1, 5)
.Select(index => new WeatherForecast
{
return new List<WeatherForecast>
{
new WeatherForecast
{
Date = DateTime.Now,
TemperatureC = 0,
Summary = Summaries[0]
}
};
}

var rng = new Random();
return new List<WeatherForecast>(Enumerable.Range(1, 5)
.Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray());
}
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Linq;
using Ardalis.Result.Sample.Core.Services;
using FluentAssertions;
using Xunit;

namespace Ardalis.Result.Sample.UnitTests.ServiceTests;

public class BadResultService_ReturnResultWithError
{
[Fact]
public void ReturnsErrorResultGivenMessage()
{
var service = new BadResultService();

var result = service.ReturnErrorWithMessage("Some error message");

result.Status.Should().Be(ResultStatus.Error);
result.Errors.Single().Should().Be("Some error message");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public void ReturnsInvalidResultWith2ErrorsGivenSomeLongNameSurname()
}

[Fact]
public void ReturnsConflictResultGivenExistPerson()
public void ReturnsConflictResultGivenExistingPerson()
{
var service = new PersonService();
string firstName = "John";
Expand All @@ -39,6 +39,6 @@ public void ReturnsConflictResultGivenExistPerson()
var result = service.Create(firstName, lastName);

result.Status.Should().Be(ResultStatus.Conflict);
result.Errors.Single().Should().Be($"Person ({firstName} {lastName}) is exist");
result.Errors.Single().Should().Be($"Person ({firstName} {lastName}) already exists in the system");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public async Task ReturnsConflictGivenExistPerson(string route)
var problemDetails = JsonConvert.DeserializeObject<ProblemDetails>(stringResponse);

Assert.Contains("There was a conflict.", problemDetails.Title);
Assert.Contains("Next error(s) occurred:* Person (John Smith) is exist", problemDetails.Detail);
Assert.Contains("Next error(s) occurred:* Person (John Smith) already exists in the system", problemDetails.Detail);
Assert.Equal(409, problemDetails.Status);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public async Task ReturnsNotFoundGivenUnknownId(string route)
var problemDetails = JsonConvert.DeserializeObject<ProblemDetails>(stringResponse);

Assert.Contains("Resource not found.", problemDetails.Title);
Assert.Contains("Person Not Found", problemDetails.Detail);
Assert.Contains("Person with id 2 Not Found", problemDetails.Detail);
Assert.Equal(404, problemDetails.Status);
}

Expand Down
11 changes: 5 additions & 6 deletions src/Ardalis.Result.AspNetCore/Ardalis.Result.AspNetCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@
<Summary>Adds ASP.NET Core filters that translate from Result to ActionResult.</Summary>
<PackageTags>result pattern web api aspnetcore mvc</PackageTags>
<PackageReleaseNotes>
* BREAKING Expose ValidationErrors as IEnumerable to Prevent Side Effects by @KyleMcMaster in https://github.com/ardalis/Result/pull/169
* Add Created.Result by @hectorrhg in https://github.com/ardalis/Result/pull/177
* Add Result.NoContent support (HTTP 204) by @dadyarri in https://github.com/ardalis/Result/pull/178
* Fix 179 by @ardalis in https://github.com/ardalis/Result/pull/180
* Update Error usage to utilize ErrorList record with ErrorMessages and CorrelationId by @KyleMcMaster in https://github.com/ardalis/Result/pull/173
* fixes ardalis/Result#187; add created option in ToMinimalApiResult by @Dalmazox in #188
* ✨ 176 result status helpers by @danielmackay in #184
* Bump rexml from 3.2.6 to 3.2.8 in /docs by @dependabot in #183
* Fix Null Ref when returning Result.Error(string) non-generically. by @ardalis in #189
</PackageReleaseNotes>
<AssemblyName>Ardalis.Result.AspNetCore</AssemblyName>
<Version>9.0.0</Version>
<Version>9.1.0</Version>
<TargetFrameworks>$(NetCoreFrameworks)</TargetFrameworks>
</PropertyGroup>

Expand Down
5 changes: 2 additions & 3 deletions src/Ardalis.Result.AspNetCore/MinimalApiResultExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ public static Microsoft.AspNetCore.Http.IResult ToMinimalApiResult(this Result r
internal static Microsoft.AspNetCore.Http.IResult ToMinimalApiResult(this IResult result) =>
result.Status switch
{
ResultStatus.Ok => typeof(Result).IsInstanceOfType(result)
? Results.Ok()
: Results.Ok(result.GetValue()),
ResultStatus.Ok => result is Result ? Results.Ok() : Results.Ok(result.GetValue()),
ResultStatus.Created => Results.Created("", result.GetValue()),
ResultStatus.NotFound => NotFoundEntity(result),
ResultStatus.Unauthorized => UnAuthorized(result),
ResultStatus.Forbidden => Forbidden(result),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
<PropertyGroup>
<PackageId>Ardalis.Result.FluentValidation</PackageId>
<Title>Ardalis.Result.FluentValidation</Title>
<Description>A simple package to implement the FluentValidation in Result package.</Description>
<Summary>A simple package to implement the FluentValidation in Result package.</Summary>
<Description>A simple package to implement FluentValidation with the Ardalis.Result package.</Description>
<Summary>A simple package to implement FluentValidation with the Ardalis.Result package.</Summary>
<PackageTags>result;pattern;web;api;aspnetcore;mvc;FluentValidation;Validation</PackageTags>
<PackageReleaseNotes>Updating to sync with Ardalis.Result 9.0.0</PackageReleaseNotes>
<AssemblyName>Ardalis.Result.FluentValidation</AssemblyName>
<Version>9.0.0</Version>
<PackageReleaseNotes>
* fixes ardalis/Result#187; add created option in ToMinimalApiResult by @Dalmazox in #188
* ✨ 176 result status helpers by @danielmackay in #184
* Bump rexml from 3.2.6 to 3.2.8 in /docs by @dependabot in #183
* Fix Null Ref when returning Result.Error(string) non-generically. by @ardalis in #189
</PackageReleaseNotes>
<AssemblyName>Ardalis.Result.FluentValidation</AssemblyName>
<Version>9.1.0</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
7 changes: 5 additions & 2 deletions src/Ardalis.Result/Ardalis.Result.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
<Summary>A simple package to implement the Result pattern for returning from services.</Summary>
<PackageTags>result pattern web api aspnetcore mvc</PackageTags>
<PackageReleaseNotes>
* #182 - Add overload for single Error message and make correlationId optional
* fixes ardalis/Result#187; add created option in ToMinimalApiResult by @Dalmazox in #188
* ✨ 176 result status helpers by @danielmackay in #184
* Bump rexml from 3.2.6 to 3.2.8 in /docs by @dependabot in #183
* Fix Null Ref when returning Result.Error(string) non-generically. by @ardalis in #189
</PackageReleaseNotes>
<AssemblyName>Ardalis.Result</AssemblyName>
<Version>9.0.1</Version>
<Version>9.1.0</Version>
</PropertyGroup>
<ItemGroup>
<None Include="icon.png" Pack="true" Visible="false" PackagePath="" />
Expand Down
59 changes: 59 additions & 0 deletions src/Ardalis.Result/IResultExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
namespace Ardalis.Result;

public static class IResultExtensions
{
/// <summary>
/// Returns true if the result is successful (status is Ok).
/// </summary>
public static bool IsOk(this IResult result) => result.Status == ResultStatus.Ok;

/// <summary>
/// Returns true if the result is created (status is Created).
/// </summary>
public static bool IsCreated(this IResult result) => result.Status == ResultStatus.Created;

/// <summary>
/// Returns true if the result is an error (status is Error).
/// </summary>
public static bool IsError(this IResult result) => result.Status == ResultStatus.Error;

/// <summary>
/// Returns true if the result is forbidden (status is Forbidden).
/// </summary>
public static bool IsForbidden(this IResult result) => result.Status == ResultStatus.Forbidden;

/// <summary>
/// Returns true if the result is unauthorized (status is Unauthorized).
/// </summary>
public static bool IsUnauthorized(this IResult result) => result.Status == ResultStatus.Unauthorized;

/// <summary>
/// Returns true if the result is invalid (status is Invalid).
/// </summary>
public static bool IsInvalid(this IResult result) => result.Status == ResultStatus.Invalid;

/// <summary>
/// Returns true if the result is not found (status is NotFound).
/// </summary>
public static bool IsNotFound(this IResult result) => result.Status == ResultStatus.NotFound;

/// <summary>
/// Returns true if the result is no content (status is NoContent).
/// </summary>
public static bool IsNoContent(this IResult result) => result.Status == ResultStatus.NoContent;

/// <summary>
/// Returns true if the result is a conflict (status is Conflict).
/// </summary>
public static bool IsConflict(this IResult result) => result.Status == ResultStatus.Conflict;

/// <summary>
/// Returns true if the result is a critical error (status is CriticalError).
/// </summary>
public static bool IsCriticalError(this IResult result) => result.Status == ResultStatus.CriticalError;

/// <summary>
/// Returns true if the result is unavailable (status is Unavailable).
/// </summary>
public static bool IsUnavailable(this IResult result) => result.Status == ResultStatus.Unavailable;
}
12 changes: 12 additions & 0 deletions src/Ardalis.Result/Result.Void.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ public static Result<T> Success<T>(T value, string successMessage)
};
}

/// <summary>
/// Represents an error that occurred during the execution of the service.
/// A single error message may be provided and will be exposed via the Errors property.
/// </summary>
/// <param name="errorMessage"></param>
/// <returns></returns>
public static Result Error(string errorMessage)

Check warning on line 73 in src/Ardalis.Result/Result.Void.cs

View workflow job for this annotation

GitHub Actions / build

'Result.Error(string)' hides inherited member 'Result<Result>.Error(string)'. Use the new keyword if hiding was intended.

Check warning on line 73 in src/Ardalis.Result/Result.Void.cs

View workflow job for this annotation

GitHub Actions / build

'Result.Error(string)' hides inherited member 'Result<Result>.Error(string)'. Use the new keyword if hiding was intended.

Check warning on line 73 in src/Ardalis.Result/Result.Void.cs

View workflow job for this annotation

GitHub Actions / build

'Result.Error(string)' hides inherited member 'Result<Result>.Error(string)'. Use the new keyword if hiding was intended.

Check warning on line 73 in src/Ardalis.Result/Result.Void.cs

View workflow job for this annotation

GitHub Actions / build

'Result.Error(string)' hides inherited member 'Result<Result>.Error(string)'. Use the new keyword if hiding was intended.
{
return new Result(ResultStatus.Error) { Errors = new[] { errorMessage } };
}


/// <summary>
/// Represents the validation error that prevents the underlying service from completing.
/// </summary>
Expand Down
Loading

0 comments on commit 4c4f23d

Please sign in to comment.