jbogard / MediatR

Simple, unambitious mediator implementation in .NET
Apache License 2.0
11.19k stars 1.18k forks source link

.NET8 upgrade from .NET Core 2.1 : Command cannot be used as type parameter 'TRequest' for 'IRequestHandler<TRequest>' #1033

Closed eb-datatel closed 5 months ago

eb-datatel commented 6 months ago

I cannot see what about this definition is not conforming to MediatR.IRequest.

The type 'EmployeeSignInCommand' cannot be used as type parameter 'TRequest' in the generic type or method 'IRequestHandler<TRequest>'.
There is no implicit reference conversion from 'EmployeeSignInCommand' to 'MediatR.IRequest'.
public class EmployeeSignInCommand : IRequest<SignInViewModel<EmployeeViewModel>>

public class EmployeeSignInCommandHandler : IRequestHandler<EmployeeSignInCommand, SignInViewModel<EmployeeViewModel>>
{
  public async Task<SignInViewModel<EmployeeViewModel>> Handle(EmployeeSignInCommand request, CancellationToken cancellationToken)
}
Danielovich commented 5 months ago

Not sure if you are posting the correct code here, because your EmployeeSignInCommand type is not ending correct, and will result in a compile time error (missing { } ).

Anyways, I can get your code to compile with .NET 8 and MediatR 12.2.0. Please check your MediatR version.

public class EmployeeSignInCommand : IRequest<SignInViewModel<EmployeeViewModel>> { }

    public class EmployeeSignInCommandHandler : IRequestHandler<EmployeeSignInCommand, SignInViewModel<EmployeeViewModel>>
    {
        public async Task<SignInViewModel<EmployeeViewModel>> Handle(EmployeeSignInCommand request, CancellationToken cancellationToken)
        {
            return await Task.FromResult(new SignInViewModel<EmployeeViewModel>());
        }
    }

    public class EmployeeViewModel
    {
    }

    public class SignInViewModel<T>
    {
    }

You didn't provide any of the subclasses for reference so I made my own.

eb-datatel commented 5 months ago

It's no longer a compile error, but a runtime error. I also replaced my implementation of EmployeeSignInCommandHandler.Handle() with your minimalist version, and that also give the same error

An unhandled exception has occurred while executing the request.
      Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: The type '....EmployeeSignInCommand' cannot be used as type parameter 'TRequest' in the generic type or method 'MediatR.ISender.Send<TRequest>(TRequest, System.Threading.CancellationToken)'. There is no implicit reference conversion from '...EmployeeSignInCommand' to 'MediatR.IRequest'.
eb-datatel commented 5 months ago

It was not a MediatR issue. It was a change to .NET 8 where JSON serialization broke in two ways.

  1. Newtonsoft.Json.JsonConvert.SerializeObject... started returning "{\"ValueKind\":1}" so I needed to switch to System.Text.Json

  2. In .NET 8, dynamic is no longer supported.

It compiles, but at runtime, the object created this way looks fine in the debugger, but generates the type mismatch error I reported above. dynamic payload = JsonConvert.DeserializeObject(payloadJson, requestType); fortunately in this case it was only necessary to change dynamic to var

var payload = JsonConvert.DeserializeObject(payloadJson, requestType);
var result = Ok(await mediator.Send(payload));