FluentResults icon indicating copy to clipboard operation
FluentResults copied to clipboard

ToActionResult() not working with version 4.0.0

Open chunty opened this issue 4 months ago • 3 comments

The following code:

using FluentResults;
using FluentResults.Extensions.AspNetCore;
using Microsoft.AspNetCore.Mvc;

public class Program
{
	public static void Main()
	{
		var err = Result.Fail(new MyError());
		var controller = new MyController();
		var result = err.ToActionResult();

		Console.WriteLine(result);
	}

	public class MyController : ControllerBase;

	public class MyError() : Error("Error");

}

Gives the error:

System.MissingMethodException
  HResult=0x80131513
  Message=Method not found: 'System.Collections.Generic.List`1<FluentResults.IError> FluentResults.ResultBase.get_Errors()'.
  Source=FluentResults.Extensions.AspNetCore
  StackTrace:
   at FluentResults.Extensions.AspNetCore.DefaultAspNetCoreResultEndpointProfile.TransformFailedResultToActionResult(FailedResultToActionResultTransformationContext context)
   at FluentResults.Extensions.AspNetCore.ResultToActionResultTransformer.Transform(Result result, IAspNetCoreResultEndpointProfile profile)
   at FluentResults.Extensions.AspNetCore.ResultExtensions.ToActionResult(Result result, IAspNetCoreResultEndpointProfile profile)
   at FluentResults.Extensions.AspNetCore.ResultExtensions.ToActionResult(Result result)
   at Program.Main() in C:\Users\chrishunt.QES-OFFICE\source\repos\Countrywide\TestFluentResults\ConsoleApp1\Program.cs:line 11

I believe the problem has been introduced as part of this change: https://github.com/altmann/FluentResults/pull/164

chunty avatar Sep 03 '25 15:09 chunty

weirdly just overriding with a copy of the default profile works:

using FluentResults;
using FluentResults.Extensions.AspNetCore;
using Microsoft.AspNetCore.Mvc;

public class Program
{
	public static void Main()
	{
		AspNetCoreResult.Setup(config => config.DefaultProfile = new CustomAspNetCoreResultEndpointProfile());

		var err = Result.Fail(new MyError());
		var controller = new MyController();
		var result = err.ToActionResult();

		Console.WriteLine(result);
	}

	public class MyController : ControllerBase;

	public class MyError() : Error("Error");


	public class CustomAspNetCoreResultEndpointProfile : IAspNetCoreResultEndpointProfile
	{
		public virtual ActionResult TransformFailedResultToActionResult(FailedResultToActionResultTransformationContext context)
		{
			var result = context.Result;

			var errorDtos = result.Errors.Select(e => new ErrorDto
			{
				Message = e.Message
			});

			return new BadRequestObjectResult(errorDtos);
		}

		public virtual ActionResult TransformOkNoValueResultToActionResult(OkResultToActionResultTransformationContext<Result> context)
		{
			return new OkResult();
		}

		public virtual ActionResult TransformOkValueResultToActionResult<T>(OkResultToActionResultTransformationContext<Result<T>> context)
		{
			return new OkObjectResult(context.Result.ValueOrDefault);
		}
	}
}

chunty avatar Sep 03 '25 16:09 chunty

This could be a red herring but the wonders of ChatGPT tells me the following:

That exception is a classic binary mismatch between your two packages:

  • Your app is loading FluentResults 4.0.0 at runtime, whose ResultBase exposes Errors with a different binary signature than what your ASP.NET extension package was compiled against.
  • FluentResults.Extensions.AspNetCore you reference was compiled against an older FluentResults where ResultBase.get_Errors() had the signature the extension expects. At runtime it can’t find that exact method, so you get: MissingMethodException: ... ResultBase.get_Errors().

Why this happens

  • ToActionResult() calls into the transformer/profile code inside the ASP.NET package. That code reads result.Errors via the compiled signature. If your app loads a newer FluentResults where the property’s signature changed (or its assembly identity/version doesn’t match), the CLR can’t bind the call and throws. ([GitHub][1])
  • You’re on FluentResults 4.0.0 (a recent major with breaking changes), so anything built against 3.x can break at runtime if not rebuilt against 4.x. ([NuGet][2])

How the fix solves it

  1. Make the packages compatible (pick one path):

    • Upgrade the ASP.NET extension to a version built for FR 4.x (current NuGet shows 0.2.0 is the latest; use that or newer), so both packages agree on the Errors member at the IL level. ([NuGet][3], [nuget.info][4])
    • OR downgrade FluentResults to the latest 3.16.x that your current extension was built against. (The project’s releases and issues note 4.0.0 as a recent major; older extensions may still target 3.x.) ([GitHub][5])
  2. After aligning versions, clean NuGet caches and rebuild to avoid stale binaries:

    • Delete bin/, obj/
    • dotnet nuget locals all --clear

chunty avatar Sep 04 '25 07:09 chunty

https://github.com/altmann/FluentResults/issues/241

PUDGE133 avatar Sep 11 '25 20:09 PUDGE133