通知不实现 $INotification C#

notification does not implement $INotification C#

我有一个使用调解器和 CQRS 的多租户项目,出于某种原因,我的订单请求中的 CRUD 是 returning 这个错误,我已经尝试重构我的处理程序,有时包括通过从请求处理程序 class,但不起作用。

所有 http 方法 return 完全相同的错误,但在不同的处理程序中,我们正在为队列使用 Azure 服务总线。

有什么建议吗?谢谢!

错误:

System.Exception
 ---> System.ArgumentException: notification does not implement $INotification
   at MediatR.Mediator.Publish(Object notification, CancellationToken cancellationToken)
   at Project.RequestHandler.MarketPlace.Order.OrderGetRequestHandler.Handle(OrderGetRequest request, CancellationToken cancellationToken) in C:\git\Project\project-apis.Services\Project.RequestHandler\MarketPlace\Order\OrderGetRequestHandler.cs:line 27
   at MediatR.Internal.RequestHandlerWrapperImpl`2.<>c__DisplayClass1_0.<Handle>g__Handler|0()
   at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestPostProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
   at Project.MarketPlaceAPI.Controllers.OrderController.Get() in C:\git\Project\project-apis.Application\Project.MarketPlaceAPI\Controllers\OrderController.cs:line 28
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Project.Infra.CrossCutting.Middlewares.IPFilterMiddleWare.Invoke(HttpContext context, IOptions`1 applicationOptionsAccessor, ILogger`1 logger) in C:\git\Project\project-apis.Infra.02.CrossCutting\Project.Infra.CrossCutting\Middlewares\IPFilterMiddleware.cs:line 37
   --- End of inner exception stack trace ---
   at Project.Infra.CrossCutting.Middlewares.IPFilterMiddleWare.Invoke(HttpContext context, IOptions`1 applicationOptionsAccessor, ILogger`1 logger) in C:\git\Project\project-apis.Infra.02.CrossCutting\Project.Infra.CrossCutting\Middlewares\IPFilterMiddleware.cs:line 82
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS
=======
Cache-Control: no-cache
Connection: keep-alive
Accept: */*
Accept-Encoding: gzip, deflate, br
Authorization: Bearer <REMOVED SECURITY TOKEN>
Host: localhost:<PORT>
User-Agent: PostmanRuntime/7.29.0
Postman-Token: <TOKEN>

实体:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable

namespace Project.Domain.Entities
{
    public class Order : UpdatedEntity
    {
        public Order() { }
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int OrderId { get; init; }
        [ForeignKey("Tenant")]
        public int TenantId {get;set;}
        [ForeignKey("TargetTenant")]
        public int TargetTenantId {get;set;}
        public virtual Tenant Tenant { get; set; }
        public virtual Tenant TargetTenant { get; set; }
    }
}

OrderGetDTO:

using System;
using Project.Domain.Entities;

namespace Project.Domain.DTO.MarketPlace.Order
{
    public class OrderGetDTO
    {
        public int OrderId { get; set; }
        public int TenantId { get; set; }
        public int TargetTenantId { get; set; }
        public DateTime CreatedAt { get; set;  }
        public DateTime UpdatedAt { get; set;  }
    }
}

订单获取响应:

using System.Collections.Generic;
using Project.Domain.DTO.MarketPlace.Order;
using Project.Domain.Responses.Generics;
using MediatR;

namespace Project.Domain.Responses.MarketPlace.Order
{
    public class OrderGetResponse : RowsResponse<OrderGetDTO>
                                  , INotification
    {
        public OrderGetResponse (bool success, string message) : base(success, message) { }
        public OrderGetResponse (IEnumerable<OrderGetDTO> rows) : base(rows) { }
    }
}

订单获取请求:

using Project.Domain.Interfaces.Requests;
using Project.Domain.Responses.MarketPlace.Order;
using MediatR;

namespace Project.Domain.Requests.MarketPlace.Order
{
    public class OrderGetRequest : BaseListTenantUserRequest
                                 , IRequest<OrderGetResponse>
                                 , ITargetTenantRequest  
    {
        public int OrderId { get; set; }
        public int TargetTenantId {get;set;}
    }
}

IOrderGetRepository:

using System.Threading.Tasks;
using Project.Domain.Requests.MarketPlace.Order;
using Project.Domain.Responses.MarketPlace.Order;

namespace Project.Domain.Interfaces.Repository.MarketPlace.Order
{
    public interface IOrderGetRepository
    {
        Task<OrderGetResponse> Handle(OrderGetRequest request);
    }
}

OrderGetRequestHandler:

using MediatR;
using System.Threading;
using System.Threading.Tasks;
using Project.Domain.Interfaces.Repository.MarketPlace.Order;
using Project.Domain.Requests.MarketPlace.Order;
using Project.Domain.Responses.MarketPlace.Order;

namespace Project.RequestHandler.MarketPlace.Order
{
    public class OrderGetRequestHandler : IRequestHandler< OrderGetRequest
                                                         , OrderGetResponse>
    {
        private readonly IOrderGetRepository _repository;
        private readonly IMediator _mediator;
        
        public OrderGetRequestHandler( IOrderGetRepository repository,
                                       IMediator mediator)
        {
            _repository = repository;
            _mediator = mediator;
        }
        
        public Task<OrderGetResponse> Handle( OrderGetRequest request
                                            , CancellationToken cancellationToken)
        {
            var returnValue = _repository.Handle(request);
            _mediator.Publish(returnValue, cancellationToken);
            return returnValue;
        }
    }
}

OrderGetRepository:

using System.Linq;
using Project.Infra.Data.Context;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
using Project.Domain.DTO.MarketPlace.Order;
using Project.Domain.Interfaces.Repository.Tenants;
using Project.Domain.Interfaces.Repository.MarketPlace.Order;
using Project.Domain.Requests.MarketPlace.Order;
using Project.Domain.Responses.MarketPlace.Order;

namespace Project.Infra.Data.Repository.MarketPlace.Order
{
    public class OrderGetRepository : IOrderGetRepository
    {
        private readonly ProjectContext _context;
        private readonly ITenantRepository _tenantRepository;
        
        public OrderGetRepository( ProjectContext context
                                 , ITenantRepository tenantRepository)
        {
            _context = context;
            _tenantRepository = tenantRepository;
        }

        public async Task<OrderGetResponse> Handle(OrderGetRequest request)
        {
            var tenantRecord = await _tenantRepository.Handle(request);
            if (tenantRecord == null)
            {
                return new OrderGetResponse(false, "Tenant not found") {
                    IsNotFound = true
                };
            }
            
            request.Query = string.IsNullOrEmpty(request.Query) ||
            request.Query.ToLower().Equals("[null]") ? string.Empty : 
            request.Query.ToLower();
            
            return new OrderGetResponse ((
                    await _context.Orders
                                .Where(r=> r.TenantId.Equals(tenantRecord.TenantId) &&
                                           r.OrderId.Equals(request.OrderId))
                                .Select(r => new OrderGetDTO() {
                                        OrderId = r.OrderId,
                                        TenantId = r.TenantId,
                                        TargetTenantId = r.TargetTenantId,
                                        CreatedAt = r.CreatedAt,
                                        UpdatedAt = r.UpdatedAt ?? r.CreatedAt
                                })
                                .ToListAsync()));
        }
    }
}

订单管理员:

using MediatR;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Project.Infra.Shared.Controllers;
using Microsoft.AspNetCore.Authorization;
using Project.Domain.Requests.MarketPlace.Order;
using Project.Domain.Responses.MarketPlace.Order;

namespace Project.MarketPlaceAPI.Controllers
{
    [ApiController]
    [Authorize]
    [Route("api/v2/[controller]")]
    public class OrderController : BaseApiController
    {
        private readonly IMediator _mediator;
        public OrderController(IMediator mediator)
        {
            _mediator = mediator;
        }

        [HttpGet]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(OrderGetResponse))]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        public async Task<IActionResult> Get()
        {
            return ProcessResponse(await _mediator.Send(new OrderGetRequest()
            {
                TenantId = TenantId,
                UserId = UserId
            }));
        }
        
        [HttpGet]
        [Route("{id}")]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(OrderGetResponse))]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        public async Task<IActionResult> Get(int id)
        {
            return ProcessResponse(await _mediator.Send(new OrderGetRequest()
            {
                TenantId = TenantId,
                UserId = UserId,
                OrderId = id
            }));
        }

        [HttpPost]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(OrderGetResponse))]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]        
        public async Task<IActionResult> Post([FromBody] OrderGetRequest request)
        {
             request.TenantId = TenantId;
             request.UserId = UserId;
             return ProcessResponse(await _mediator.Send(request));
        }

        [HttpPut]
        [Route("{id}")]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(OrderGetResponse))]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        public async Task<IActionResult> Put([FromBody] OrderGetRequest request
                                                      , int id)
        {
             request.TenantId = TenantId;
             request.UserId = UserId;
             request.OrderId = id;
             return ProcessResponse(await _mediator.Send(request));
        }
        
        [HttpPatch]
        [Route("{id}")]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(OrderGetResponse))]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        public async Task<IActionResult> Patch([FromBody] OrderGetRequest request
                                                        , int id)
        {
             request.TenantId = TenantId;
             request.UserId = UserId;
             request.OrderId = id;
             return ProcessResponse(await _mediator.Send(request));
        }

        [HttpDelete]
        [Route("{id}")]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(OrderDeleteResponse))]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        public async Task<IActionResult> Delete([FromBody] OrderDeleteRequest request
                                                          , int id)
        {
            request.TenantId = TenantId;
            request.UserId = UserId;
            request.OrderId = id;
            return ProcessResponse(await _mediator.Send(request));
        }
    }
}

我在谷歌上搜索相同错误的解决方案:notification does not implement $INotification

找不到任何东西,但在我的代码中找出了问题,所以也许你正在处理同样的问题。我在打电话:

_mediator.Publish(MyRequest...)

其实我应该打电话给

_mediator.Send(MyRequest...)

你只能PublishNotifications。你只能 Send Requests。错误是抱怨试图 Publish 不是 Notification 的对象。尝试将以下行从 Publish 更改为 Send 并查看它是否有效,或者验证您尝试 Publish 的对象实际上是一个通知(它需要实现 INotification 接口:

_mediator.Publish(returnValue, cancellationToken);

编辑: 我再次查看了您的代码,我认为问题在于您不是 awaiting 下面第一行中的 returnValue:

var returnValue = _repository.Handle(request);
_mediator.Publish(returnValue, cancellationToken);

这导致返回值为 Task<INotification>,这不是下面的 Publish 函数所期望的。您应该改为执行以下操作:

var returnValue = await _repository.Handle(request);
await _mediator.Publish(returnValue, cancellationToken);

您还需要制作函数签名 async 才能编译: public async Task<OrderGetResponse> Handle( OrderGetRequest request...