Bidding Beyond Limits: Enhancing Customer Experience with SignalR

Image for Bidding Beyond Limits: Enhancing Customer Experience with SignalR

Introduction

In the bustling domain of e-commerce, online auction platforms stand out as exciting arenas where buyers and sellers converge for real-time interactions. The essence of real-time communication in such platforms is pivotal, and herein lies the brilliance of Web Sockets. They forge a real-time communication bridge between the server and the client, a catalyst for the thriving real-time interactions in various web applications like live chat, online gaming, and live streaming. For online auction platforms, the merits of Web Sockets are multi-fold: instantaneous bid updates, diminished latency, and bolstered scalability. This post unfolds the mechanics of Web Sockets, spotlighting how they can redefine the real-time bidding dynamics on auction platforms.

The Mechanics of Web Sockets

WebSocket Connection Illustration by Ably WebSocket Connection Illustration by Ably

Web Sockets herald a unique protocol that orchestrates a full-duplex communication channel over a single, enduring connection, a notable departure from the conventional HTTP where new connections are spawned for each request. This unbroken connection is the linchpin for real-time data transfer, a cornerstone for real-time applications like online auctions. Diagrams showcasing the Web Sockets protocol against traditional HTTP connections illuminate the efficacy and continuous data flow propelled by Web Sockets, marking them as a superior choice for real-time interactions.

SignalR in the Real World

SignalR, a distinguished library within the ASP.NET ecosystem, emerges as a robust conduit for nurturing real-time interactions between server and client. Be it instant data change reflections, enabling live chat functionalities, or updating live scores in a game, SignalR simplifies the orchestration of real-time communication. By masking the complexities entailed in managing persistent connections and handling real-time data synchronization, SignalR allows developers to concentrate on the messages seamlessly.

Hubs

Embarking on a SignalR journey necessitates the creation of a Hub for clients to utilize. For simplicity, we’ll demonstrate how you can obtain live information about a single auction lot instead of all visible lots on a page.

public class LotHub : Hub
{
    /// <summary>
    /// Join a lot.
    /// </summary>
    /// <param name="lotId">The id of the lot.</param>
    public async Task JoinLot(string lotId)
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, lotId);
    }

    /// <summary>
    /// Leave a lot.
    /// </summary>
    /// <param name="lotId">The id of the lot.</param>
    public async Task LeaveLot(string lotId)
    {
        await Groups.RemoveFromGroupAsync(Context.ConnectionId, lotId);
    }
}

The above snippet exemplifies how SignalR can be effortlessly leveraged to manage the grouping of multiple users based on a particular key, taking advantage of the grouping feature to send updates only for the lot in focus.

constructor() {
this.hubConnection = new HubConnectionBuilder()
      .withUrl('/LotHub')
      .configureLogging(LogLevel.Critical)
      .withAutomaticReconnect()
      .build();

    this.setupSignalRConnection();
}

setupSignalRConnection() {
    if (this.signalRSetup) return;
    this.signalRSetup = true;

    this.hubConnection
      .start()
      .then(() => {
        this.hubConnection.invoke('JoinLot', this.id);

        this.hubConnection.on('BidUpdate', (e: string) => {
          const obj: UpdatedBid = JSON.parse(e);
          this.store.dispatch(updateBid({ bidInfo: obj }));
        });
      })
      .catch((err) => {
        // code to display error omitted for brevity...
      });
  }

We have a strong affinity for Angular, and hence, opted to use the SignalR client on NPM. The code illustrates post page construction, connecting to the LotHub, and ensuring automatic reconnection to counter any network instability. If no parameters are specified for WithAutomaticReconnect, the client attempts to reconnect four times with a 0, 2, 10, and 30 seconds delay. If the final reconnection attempts fails, the client will stop trying to reconnect.

Sending Messages

public class LotHubService : ILotHubService
{
    private readonly IHubContext<LotHub> _hubContext;

    public LotHubService(IHubContext<LotHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public async Task OnBid(UpdatedBid bid)
    {
        var json = JsonSerializer.Serialize(bid, new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        });

        await _hubContext.Clients.Group(bid.Id).SendAsync("BidUpdate", json);
    }
}

A dedicated service is crafted to utilize the HubContext, ensuring that once a bid is verified as valid, the bid change is broadcasted to everyone eyeing the lot, including the bidder, to reflect the change instantaneously.

Putting it all together

Bid Process

Now that you've gotten a glimpse of the different pieces of the puzzle, let's dive into how they all mesh together. The diagram above walks you through the bid process from the moment a user hits the bid button to when the bid is shared with all the folks watching the lot. Here's a step-by-step breakdown of what goes down:

  • First off, a user clicks the bid button.
  • The server then gets into action, validating the bid using etags to make sure that the user was looking at the latest version of the lot when they pressed that button.
  • Once the green light is given, the bid is saved to the database.
  • Everyone keeping tabs on the lot gets a heads up about the bid via email, text, or push notification, based on their preferences.
  • The bid is then broadcasted live to all users who are tuned into the lot.

With this intel, let’s chat about some choices we made along the way. We decided to use etags to ensure that the user is looking at the latest version of the lot. This is key because if a user is looking at an outdated version, they might bid on a lot that already has a higher bid. Next, we chose to use a service to send the bid update to all the users glued to the lot. This makes it a breeze to share the bid update with everyone, including the bidder, without diving deep into the technicalities of accessing the HubContext within our CQRS command handlers. Lastly, we decided to process bid commands via HTTP instead of Web Socket. This choice allows us to reuse some of the existing code paths we have for processing HTTP responses, like logging, error handling, and automatic retries, making our lives a tad easier.

Conclusion

The inception of Web Sockets has undeniably ushered a paradigm shift in real-time online interactions, with online auction platforms reaping substantial benefits. Embracing Web Sockets and SignalR, auction platforms can markedly enhance the real-time bidding experience, elevating user engagement, and potentially, garnering higher bid values. Though the transition necessitates a structured approach and vigilant attention to security, it heralds a stride towards more dynamic and user-centric auction platforms.

Ready to elevate your project to the next level? Contact us.