.net core 在ASP.net核心IHostedService中使用RabbitMQ

.net core 在ASP.net核心IHostedService中使用RabbitMQ,.net-core,rabbitmq,.net Core,Rabbitmq,我面临一个需要帮助的问题。 我正在开发一个后台进程,该进程将侦听rabbitmq服务器中的队列。 如果我在.net核心控制台应用程序中运行它就可以了。然而,我想用一种更优雅的方式来实现它,比如web服务(这给我带来了很多麻烦,因为它在安装时无法工作)或IIS托管的web应用程序。 当我试图在.net核心web应用程序中托管服务(IHostedService)时,我面临一个作用域服务的问题 下面的代码在控制台应用程序中运行良好。如何使其在.net核心web应用程序中作为IHostedService

我面临一个需要帮助的问题。 我正在开发一个后台进程,该进程将侦听rabbitmq服务器中的队列。 如果我在.net核心控制台应用程序中运行它就可以了。然而,我想用一种更优雅的方式来实现它,比如web服务(这给我带来了很多麻烦,因为它在安装时无法工作)或IIS托管的web应用程序。 当我试图在.net核心web应用程序中托管服务(IHostedService)时,我面临一个作用域服务的问题

下面的代码在控制台应用程序中运行良好。如何使其在.net核心web应用程序中作为IHostedService运行。 我应该改变什么。 谢谢你的帮助。 代码:

使用系统;
使用System.Collections.Generic;
使用系统数据;
使用System.Data.SqlClient;
使用System.Linq;
使用系统文本;
使用系统线程;
使用System.Threading.Tasks;
使用PaymentProcessor.Models;
使用Microsoft.Extensions.Configuration;
使用Newtonsoft.Json;
使用Newtonsoft.Json.Linq;
使用RabbitMQ.Client;
使用RabbitMQ.Client.Events;
使用Microsoft.EntityFrameworkCore;
命名空间支付处理器
{
公共类付费处理服务:HostedService
{
i配置配置;
私有实体上下文请求上下文;
私有字符串连接字符串;
私有字符串HostName=“”;
私有字符串用户名=”;
私有字符串密码=”;
私有静态int-MaxRetries;
私营IConnectionFactory;
专用i连接;
私人IModel频道;
公共支付处理服务(IConfiguration配置)
{
this.configuration=配置;
this.connectionString=configuration.GetConnectionString(“StagingContext”);
claimsContext=新实体上下文(connectionString);
HostName=this.configuration.GetValue(“设置:主机名”);
UserName=this.configuration.GetValue(“设置:UserName”);
Password=this.configuration.GetValue(“设置:密码”);
MaxRetries=this.configuration.GetValue(“设置:MaxRetries”).ConvertTo();
}
受保护的覆盖异步任务ExecuteAsync(CancellationToken CancellationToken)
{
连接:
工厂=新连接工厂{HostName=HostName,UserName=UserName,Password=Password};
尝试
{
connection=factory.CreateConnection();
channel=connection.CreateModel();
渠道交换声明(“支付处理交换”、“主题”);
channel.QueueDeclare(“付款处理队列”,真、假、假、空);
channel.QueueBind(“支付处理队列”、“支付处理交换”、“处理”);
var queueArgs=新字典
{
{“x-dead-letter-exchange”,“付款处理交换”},
{“x-dead-letter-routing-key”,“处理\u重试”},
{“x-message-ttl”,10000}
};
渠道交换声明(“支付处理交换”、“主题”);
channel.QueueDeclare(“付款\处理\重试\队列”,true、false、false、queueArgs);
channel.QueueBind(“支付\处理\重试\队列”、“支付\处理\交换”、“处理\重试”,null);
渠道交换声明(“支付、处理、交换”、“主题”);
channel.QueueDeclare(“付款\处理\错误\队列”,真、假、假、空);
channel.QueueBind(“支付\处理\错误\队列”、“支付\处理\交换”、“处理\错误”,null);
渠道交换声明(“支付、处理、交换”、“主题”);
channel.QueueDeclare(“支付\集成\队列”,真、假、假、空);
channel.QueueBind(“支付\集成\队列”、“支付\处理\交换”、“集成”,null);
通道.BasicQos(0,1,false);
var消费者=新事件基本消费者(渠道);
消费者.已接收+=(型号,ea)=>
{
var message=ea.Body.DeSerializeText();
尝试
{
var saveBundle=JObject.Parse(消息);
var msg=(动态)((动态)saveBundle).Message;
字符串referenceNo=(字符串)msg.referenceNo;
var参数=新[]
{
新的SqlParameter
{
DbType=DbType.String,
ParameterName=“ReferenceNo”,
Value=referenceNo
}
};
var result=claimsContext.Database.ExecuteSqlCommand(“dbo.paymentreferencessprocesssingle@ReferenceNo”,参数);
IBasicProperties=channel.CreateBasicProperties();
props.Persistent=true;
props.ContentType=“text/plain”;
props.DeliveryMode=2;
channel.BasicPublish(“支付、处理、交换”、“集成”、道具,(新的MessageEnvelope{RetryCounts=0,Message=JObject.FromObject(新的{ReferenceNo=ReferenceNo}))).Serialize();
}
捕获(例外情况除外)
{
MessageEnvelope信封=JsonConvert.DeserializeObject(消息);
if(envelope.RetryCountsusing System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using PaymentProcessor.Models;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using Microsoft.EntityFrameworkCore;

namespace PaymentProcessor
{
    public class PaymentProcessingService : HostedService
    {
        IConfiguration configuration;

        private EntitiesContext claimsContext;
        private string connectionString;

        private string HostName = "";
        private string UserName = "";
        private string Password = "";

        private static int MaxRetries;

        private IConnectionFactory factory;
        private IConnection connection;
        private IModel channel;

        public PaymentProcessingService(IConfiguration configuration)
        {
            this.configuration = configuration;

            this.connectionString = configuration.GetConnectionString ("StagingContext");
            claimsContext = new EntitiesContext(connectionString);

            HostName = this.configuration.GetValue<string>("Settings:HostName");
            UserName = this.configuration.GetValue<string>("Settings:UserName");
            Password = this.configuration.GetValue<string>("Settings:Password");
            MaxRetries = this.configuration.GetValue<string>("Settings:MaxRetries").ConvertTo<int>(); 
        }

        protected override async Task ExecuteAsync(CancellationToken cancellationToken)
        {

            connect:
            factory = new ConnectionFactory { HostName = HostName, UserName = UserName, Password = Password };

            try
            {
                connection = factory.CreateConnection();
                channel = connection.CreateModel();

                channel.ExchangeDeclare("payment_rocessing_exchange", "topic");
                channel.QueueDeclare("payment_processing_queue", true, false, false, null);
                channel.QueueBind("payment_processing_queue", "payment_processing_exchange", "processing");


                var queueArgs = new Dictionary<string, object>
                    {
                        { "x-dead-letter-exchange", "payment_processing_exchange" },
                        {"x-dead-letter-routing-key", "processing_retry"},
                        { "x-message-ttl", 10000 }
                    };

                channel.ExchangeDeclare("payment_rocessing_exchange", "topic");
                channel.QueueDeclare("payment_processing_retry_queue", true, false, false, queueArgs);
                channel.QueueBind("payment_processing_retry_queue", "payment_processing_exchange", "processing_retry", null);

                channel.ExchangeDeclare("payment_processing_exchange", "topic");
                channel.QueueDeclare("payment_processing_error_queue", true, false, false, null);
                channel.QueueBind("payment_processing_error_queue", "payment_processing_exchange", "processing_error", null);

                channel.ExchangeDeclare("payment_processing_exchange", "topic");
                channel.QueueDeclare("payment_integration_queue", true, false, false, null);
                channel.QueueBind("payment_integration_queue", "payment_processing_exchange", "integration", null);

                channel.BasicQos(0, 1, false);

                var consumer = new EventingBasicConsumer(channel);
                consumer.Received += (model, ea) =>
                {


                    var message = ea.Body.DeSerializeText();
                    try
                    {
                        var saveBundle = JObject.Parse(message);
                        var msg = (dynamic)((dynamic)saveBundle).Message;
                        string referenceNo = (string)msg.ReferenceNo;

                        var parameters = new[]
                        {
                           new SqlParameter
                            {
                                DbType =  DbType.String,
                                ParameterName = "ReferenceNo",
                                Value =referenceNo
                            }
                        };

                        var result = claimsContext.Database.ExecuteSqlCommand("dbo.PaymentReferencesProcessSingle @ReferenceNo", parameters);

                        IBasicProperties props = channel.CreateBasicProperties();
                        props.Persistent = true;
                        props.ContentType = "text/plain";
                        props.DeliveryMode = 2;

                        channel.BasicPublish("payment_processing_exchange", "integration", props, (new MessageEnvelope { RetryCounts = 0, Message = JObject.FromObject(new { ReferenceNo = referenceNo }) }).Serialize()); 



                    }
                    catch (Exception ex)
                    {

                        MessageEnvelope envelope = JsonConvert.DeserializeObject<MessageEnvelope>(message);

                        if (envelope.RetryCounts < MaxRetries)
                        {
                            int RetryCounts = envelope.RetryCounts + 1;
                            MessageEnvelope messageEnvelope = new MessageEnvelope { RetryCounts = RetryCounts, Message = envelope.Message };
                            var data = messageEnvelope.Serialize();
                            channel.BasicPublish("payment_processing_exchange", "processing_retry", null, data);

                        }
                        else
                        {
                            var data = envelope.Serialize();
                            channel.BasicPublish("payment_processing_exchange", "processing_error", null, data);
                        }

                    }
                    finally
                    {
                        channel.BasicAck(ea.DeliveryTag, false);
                    }

                };

                channel.BasicConsume(queue: "payment_processing_queue", autoAck: false, consumer: consumer);

            }
            catch (Exception ex)
            {

                Thread.Sleep(10000);
                goto connect;
            }

        }
    }
}
services.AddScoped<IHostedService, PaymentProcessingService>();
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Threading.Tasks;

namespace Core
{
    internal class Program
    {
        static async Task Main(string[] args)
        {

            await new HostBuilder()
                 .ConfigureServices((hostContext, services) =>
                 {
                     services.AddHostedService<ServiceRabbitMQ>(); // register our service here            
                 })
                .RunConsoleAsync();
        }
    }
}