ardalis / Result

A result abstraction that can be mapped to HTTP response codes if needed.
MIT License
866 stars 107 forks source link

Invalid() returns 404 rather than 400 #75

Closed fspataro-zz closed 2 years ago

fspataro-zz commented 3 years ago

This is an odd one... pretty simple manual FluentValidation then using the ToActionResult extension method with .Invalid()...

When I use the nuget package, the result is 404, if i copy the extension class from this repo into my project I get the expected 400 with the validation errors json...

DTOValidator validator = new();
ValidationResult valResult = validator.Validate(dto);
if (!valResult.IsValid)
{
    return this.ToActionResult(Result<bool>.Invalid(valResult.AsErrors()));
}

possibly related to #74 but the old code looks like it should return a 400 as well... could be something in my middleware but I'd expect the 'source code in my project' to generate the same result.

ardalis commented 3 years ago

I'll take a look. Which NuGet package version are you on?

fspataro-zz commented 3 years ago

I was loading the package via Visual Studio Package Manager GUI (old school)...

<PackageReference Include="Ardalis.Result.AspNetCore" Version="3.0.1" />
<PackageReference Include="Ardalis.Result.FluentValidation" Version="3.0.2" />
betocastillo86 commented 2 years ago

Same error here with .net 6

The versions that I'm using are:

<PackageReference Include="Ardalis.Result" Version="3.1.2" />
<PackageReference Include="Ardalis.Result.AspNetCore" Version="3.0.1" />

This error is not only happening for 404 -> 400. When I want to return a NotFound it returns 200 and with this body

{
    "value": null,
    "valueType": null,
    "status": 5,
    "isSuccess": false,
    "successMessage": "",
    "errors": [],
    "validationErrors": []
}

When I want to return a Forbidden it returns 200 and with this body

{
    "value": null,
    "valueType": null,
    "status": 2,
    "isSuccess": false,
    "successMessage": "",
    "errors": [],
    "validationErrors": []
}

When I want to return a Error it returns 200 and with this body

{
    "value": null,
    "valueType": null,
    "status": 1,
    "isSuccess": false,
    "successMessage": "",
    "errors": [
        "error detail"
    ],
    "validationErrors": []
}

It seems like ResultStatus is moved. It is very strange.

RichardBr commented 2 years ago

In visual studio when I navigate from [TranslateResultToActionResult] attribute on my controller it shows the following code...

#region Assembly Ardalis.Result.AspNetCore, Version=3.0.1.0, Culture=neutral, PublicKeyToken=null
// C:\Users\dad\.nuget\packages\ardalis.result.aspnetcore\3.0.1\lib\netstandard2.0\Ardalis.Result.AspNetCore.dll
// Decompiled with ICSharpCode.Decompiler 6.1.0.5902
#endregion

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Ardalis.Result.AspNetCore
{
    public class TranslateResultToActionResultAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            IResult result = (context.Result as ObjectResult)?.Value as IResult;
            if (result == null)
            {
                return;
            }

            ControllerBase controllerBase = context.Controller as ControllerBase;
            if (controllerBase == null)
            {
                return;
            }

            if (result.Status == ResultStatus.Invalid)
            {
                context.Result = controllerBase.NotFound();
            }

            if (result.Status == ResultStatus.Unauthorized)
            {
                foreach (ValidationError validationError in result.ValidationErrors)
                {
                    (context.Controller as ControllerBase)?.ModelState.AddModelError(validationError.Identifier, validationError.ErrorMessage);
                }

                context.Result = controllerBase.BadRequest(controllerBase.ModelState);
            }

            if (result.Status == ResultStatus.Ok)
            {
                context.Result = new OkObjectResult(result.GetValue());
            }
        }
    }
}

This code I think is the problem

ardalis commented 2 years ago

Yeah, not too sure about this:

if (result.Status == ResultStatus.Invalid)
            {
                context.Result = controllerBase.NotFound();
            }
ardalis commented 2 years ago

Looks like you're on 3.0.1; latest is 3.1.2 in which I believe this should be fixed. Can you upgrade and confirm?

https://github.com/ardalis/Result/blob/main/src/Ardalis.Result.AspNetCore/ResultExtensions.cs#L42

RichardBr commented 2 years ago

The nuget package "Ardalis.Result.AspNetCore" needs updating. Current its v3.0.1. Please publish latest version. Thanks.

ardalis commented 2 years ago

Fixed, finally.