You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET MVC中如何从Azure Service Bus队列取消息并展示到View.cshtml

问题描述

我有一个能从Azure Service Bus队列获取消息的控制台应用,代码如下:

using System;
using System.Text;
using System.Text.Json;
using Microsoft.Azure.ServiceBus;
using SampleShared.Models;

namespace SampleAppReceiver
{
    class Program
    {
        const string connString = "<my_connection_string>";
        static IQueueClient qClient;

        static async Task Main(string[] args)
        {
            qClient = new QueueClient(connString, "<my_queue_name>");

            var msgOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                // 同时处理的消息数量
                MaxConcurrentCalls = 1,

                // 等待消息完全处理后再自动完成
                AutoComplete = false,
            };

            qClient.RegisterMessageHandler(ProcessMessageAsync, msgOptions);

            Console.ReadLine();
            await qClient.CloseAsync();
        }

        private static async Task ProcessMessageAsync(Message msg, CancellationToken token)
        {
            // 反序列化消息体
            var jsonBody = Encoding.UTF8.GetString(msg.Body);
            var personObj = JsonSerializer.Deserialize<Person>(jsonBody);

            Console.WriteLine($"Login: {personObj.Login}");
            Console.WriteLine($"Message: {personObj.Message}");

            // 通知队列消息已处理完成
            await qClient.CompleteAsync(msg.SystemProperties.LockToken);
        }

        private static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs args)
        {
            Console.WriteLine($"出现错误: {args.Exception}");
            return Task.CompletedTask;
        }
    }
}

目前我的ASP.NET MVC项目已经通过IAzureBusService接口实现了从View向Azure Service Bus队列发送消息的功能,相关代码如下:

// ...
public interface IAzureBusService
{
    Task SendMessageAsync(Person personMessage, string queueName);
}
// ...

对应的控制器方法:

[HttpPost]
public async Task<IActionResult> Index(Person person)
{
    await _busService.SendMessageAsync(person, "personqueue");
    return RedirectToAction("Index");
}

请问如何在控制器中正确将从队列接收的所有消息添加到View.cshtml中?


解决方案

1. 扩展Azure Bus服务接口

首先给IAzureBusService添加接收消息的方法,支持一次性拉取多条消息:

public interface IAzureBusService
{
    Task SendMessageAsync(Person personMessage, string queueName);
    // 添加拉取消息的方法,参数为队列名和拉取数量
    Task<List<Person>> ReceiveMessagesAsync(string queueName, int messageCount = 10);
}

2. 实现消息接收逻辑

在IAzureBusService的实现类中,添加消息接收的具体代码。这里使用ReceiveAsync方法拉取指定数量的消息,处理完成后标记为已完成(从队列移除):

public class AzureBusService : IAzureBusService
{
    private readonly string _connectionString;

    public AzureBusService(IConfiguration configuration)
    {
        _connectionString = configuration.GetValue<string>("AzureServiceBus:ConnectionString");
    }

    // 原有发送消息的实现...

    public async Task<List<Person>> ReceiveMessagesAsync(string queueName, int messageCount = 10)
    {
        var receivedPersons = new List<Person>();
        using var queueClient = new QueueClient(_connectionString, queueName);

        try
        {
            // 拉取指定数量的消息,超时时间设置为5秒
            var messages = await queueClient.ReceiveAsync(messageCount, TimeSpan.FromSeconds(5));
            foreach (var message in messages)
            {
                // 反序列化消息体
                var jsonBody = Encoding.UTF8.GetString(message.Body);
                var person = JsonSerializer.Deserialize<Person>(jsonBody);
                receivedPersons.Add(person);

                // 标记消息为已处理,从队列移除
                await queueClient.CompleteAsync(message.SystemProperties.LockToken);
            }
        }
        catch (Exception ex)
        {
            // 这里可以添加日志记录逻辑
            Console.WriteLine($"接收消息出错: {ex.Message}");
        }
        finally
        {
            await queueClient.CloseAsync();
        }

        return receivedPersons;
    }
}

如果你只想查看消息而不将其从队列移除,可以使用PeekAsync方法替代ReceiveAsync,这样消息会保留在队列中供后续处理。

3. 在控制器中调用接收方法并传递给View

修改控制器的Index方法,在GET请求时拉取队列消息,将消息列表传给View:

public class HomeController : Controller
{
    private readonly IAzureBusService _busService;

    public HomeController(IAzureBusService busService)
    {
        _busService = busService;
    }

    public async Task<IActionResult> Index()
    {
        // 拉取队列中的消息,最多10条
        var receivedMessages = await _busService.ReceiveMessagesAsync("personqueue");
        // 将消息列表传给View
        return View(receivedMessages);
    }

    [HttpPost]
    public async Task<IActionResult> Index(Person person)
    {
        await _busService.SendMessageAsync(person, "personqueue");
        return RedirectToAction("Index");
    }
}

4. 在View中展示消息

修改Index.cshtml,使用模型绑定展示接收到的消息列表:

@model List<SampleShared.Models.Person>

<h1>消息列表</h1>

@if (Model != null && Model.Count > 0)
{
    <table class="table">
        <thead>
            <tr>
                <th>Login</th>
                <th>消息内容</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var person in Model)
            {
                <tr>
                    <td>@person.Login</td>
                    <td>@person.Message</td>
                </tr>
            }
        </tbody>
    </table>
}
else
{
    <p>暂无消息</p>
}

<h2>发送新消息</h2>
<form asp-action="Index" method="post">
    <div class="form-group">
        <label>Login</label>
        <input type="text" name="Login" class="form-control" />
    </div>
    <div class="form-group">
        <label>消息内容</label>
        <textarea name="Message" class="form-control"></textarea>
    </div>
    <button type="submit" class="btn btn-primary">发送</button>
</form>

补充说明

如果需要实时接收并展示消息(无需刷新页面),可以结合SignalR实现:

  • 后台启动一个服务持续监听队列,当有新消息时通过SignalR推送给前端
  • 前端页面通过SignalR连接接收消息并动态更新UI

这种方式更适合需要实时展示的场景,但实现复杂度更高。


内容的提问来源于stack exchange,提问作者np.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 20:05:39