如何实现网页的实时数据 [英] How to implement real time data for a web page

查看:48
本文介绍了如何实现网页的实时数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(这是一个 Q/A 风格的问题,旨在成为提出类似问题的人们的首选资源.很多人似乎偶然发现了这样做的最佳方法,因为他们不知道所有选项.许多答案将特定于 ASP.NET,但 AJAX 和其他技术在其他框架中确实有等价物,例如 socket.io 和 SignalR.)

(This is intended as a Q/A style question, intended to be a go-to resource for people that ask similar questions. A lot of people seem to stumble on the best way of doing this because they don't know all the options. Many of the answers will be ASP.NET specific, but AJAX and other techniques do have equivalents in other frameworks, such as socket.io and SignalR.)

我有一个在 ASP.NET 中实现的数据表.我想实时或接近实时地在页面上显示对此基础数据的更改.我该怎么做?

I have a table of data that I have implemented in ASP.NET. I want to display changes to this underlying data on the page in real time or near real time. How do I go about it?

我的模型:

public class BoardGame
    {
    public int Id { get; set;}
    public string Name { get; set;}
    public string Description { get; set;}
    public int Quantity { get; set;}
    public double Price { get; set;}

    public BoardGame() { }
    public BoardGame(int id, string name, string description, int quantity, double price)
        {
        Id=id;
        Name=name;
        Description=description;
        Quantity=quantity;
        Price=price;
        }
    }

在此示例中,我将不使用实际数据库,而是将数据存储在 Application 变量中.我将在 Global.asax.cs 的 Application_Start 函数中植入它.

In lieu of an actual database for this example, I'm just going to store the data in the Application variable. I'm going to seed it in my Application_Start function of my Global.asax.cs.

var SeedData = new List<BoardGame>(){
    new BoardGame(1, "Monopoly","Make your opponents go bankrupt!", 76, 15),
    new BoardGame(2, "Life", "Win at the game of life.", 55, 13),
    new BoardGame(3, "Candyland", "Make it through gumdrop forrest.", 97, 11)
    };
Application["BoardGameDatabase"] = SeedData;

如果我使用 Web 表单,我会用中继器显示数据.

If I were using Web Forms, I'd display the data with a repeater.

<h1>Board Games</h1>
        <asp:Repeater runat="server" ID="BoardGameRepeater" ItemType="RealTimeDemo.Models.BoardGame">
            <HeaderTemplate>
                <table border="1">
                    <tr>
                        <th>Id</th>
                        <th>Name</th>
                        <th>Description</th>
                        <th>Quantity</th>
                        <th>Price</th>
                    </tr>
            </HeaderTemplate>
            <ItemTemplate>
                <tr>
                    <td><%#: Item.Id %></td>
                    <td><%#: Item.Name %></td>
                    <td><%#: Item.Description %></td>
                    <td><%#: Item.Quantity %></td>
                    <td><%#: Item.Price %></td>
                </tr>
            </ItemTemplate>
            <FooterTemplate></table></FooterTemplate>
        </asp:Repeater>

并在后面的代码中加载该数据:

And load that data in the code behind:

protected void Page_Load(object sender, EventArgs e)
    {
    BoardGameRepeater.DataSource = Application["BoardGameDatabase"];
    BoardGameRepeater.DataBind();
    }

如果这是使用 Razor 的 MVC,那么它只是模型上的一个简单的 foreach:

If this were MVC using Razor, it's just a simple foreach over the model:

@model IEnumerable<RealTimeDemo.Models.BoardGame>
<h1>Board Games</h1>
<table border="1">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Id)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Description)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Quantity)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Price)
        </th>
    </tr> 
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Id)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Description)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Quantity)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Price)
        </td>
    </tr>
} 
</table>

让我们使用 Web 表单创建一个用于添加数据的小页面,以便我们可以实时查看数据更新.我建议您创建两个浏览器窗口,以便您可以同时查看表单和表格.

Let's use Web Forms to have a little page for adding data so we can then watch the data update in real time. I recommend you create two browser windows so you can see the form and table at the same time.

<h1>Create</h1>
<asp:Label runat="server" ID="Status_Lbl" /><br />
Id: <asp:TextBox runat="server" ID="Id_Tb" /><br />
Name: <asp:TextBox runat="server" ID="Name_Tb" /><br />
Description: <asp:TextBox runat="server" ID="Description_Tb" /><br />
Quantity: <asp:TextBox runat="server" ID="Quantity_Tb" /><br />
Price: <asp:TextBox runat="server" ID="Price_Tb" /><br />
<asp:Button runat="server" ID="SubmitBtn" OnClick="SubmitBtn_Click" Text="Submit" />

以及背后的代码:

protected void SubmitBtn_Click(object sender, EventArgs e)
    {
    var game = new BoardGame();
    game.Id = Int32.Parse(Id_Tb.Text);
    game.Name = Name_Tb.Text;
    game.Description = Description_Tb.Text;
    game.Quantity = Int32.Parse(Quantity_Tb.Text);
    game.Price = Int32.Parse(Price_Tb.Text);
    var db = (List<BoardGame>)Application["BoardGameDatabase"];
    db.Add(game);
    Application["BoardGameDatabase"] = db;
    //only for SignalR
    /*var context = GlobalHost.ConnectionManager.GetHubContext<GameHub>();
    context.Clients.All.addGame(game); */           
    }

推荐答案

SignalR

这是我最高兴与大家分享的答案,因为它代表了一种更简洁的实现,而且轻量级并且在当今的移动(数据受限)环境中运行良好.

SignalR

This is the answer I'm most excited to share, because it represents a much cleaner implementation that is lightweight and works well in today's mobile (data constricted) environment.

多年来,有几种方法可以实时"将数据从服务器推送到客户端(或推送数据的外观).快速短轮询(类似于我基于 AJAX 的答案),长轮询Forever Frame服务器发送事件,以及 WebSockets 是用于实现此目的的不同传输机制.SignalR 是一个抽象层,能够根据客户端和服务器的能力选择合适的传输机制.使用 SignalR 的最大好处是它很简单.无需担心传输机制,编程模型简单易懂.

There have been several methods over the years to provide "realtime" pushing of data from the server to the client (or the appearance of pushing data). Rapid Short Polling (similar to my AJAX based answers), Long Polling, Forever Frame, Server Sent Events, and WebSockets are different transport mechanisms used to achieve this. SignalR is an abstraction layer capable of selecting an appropriate transport mechanism based on the client and server's capabilities. The best part of using SignalR is that it's simple. You don't have to worry about the transport mechanism, and the programming model is easy to understand.

我将定义一个 SignalR 集线器,但将其留空.

I'm going to define a SignalR hub, but just leave it empty.

public class GameHub : Hub
    {
    }

当我将数据添加到数据库"时,我将运行以下代码.如果您阅读了该问题,您会看到我在创建"表单中对其进行了注释.您需要取消注释.

When I add data to the "database", I'm going to run the below bit of code. If you read the question, you'll see I commented it out in the "create" form. You'll want to uncomment that.

var context = GlobalHost.ConnectionManager.GetHubContext<GameHub>();
context.Clients.All.addGame(game);

这是我的页面代码:

<h1>SignalR</h1>
        <asp:Repeater runat="server" ID="BoardGameRepeater" ItemType="RealTimeDemo.Models.BoardGame">
            <HeaderTemplate>
                <table border="1">
                    <thead>
                        <tr>
                            <th>Id</th>
                            <th>Name</th>
                            <th>Description</th>
                            <th>Quantity</th>
                            <th>Price</th>
                        </tr>
                    </thead>
                    <tbody id="BoardGameTblBody">
            </HeaderTemplate>
            <ItemTemplate>
                <tr>
                    <td><%#: Item.Id %></td>
                    <td><%#: Item.Name %></td>
                    <td><%#: Item.Description %></td>
                    <td><%#: Item.Quantity %></td>
                    <td><%#: Item.Price %></td>
                </tr>
            </ItemTemplate>
            <FooterTemplate></tbody></table></FooterTemplate>
        </asp:Repeater>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <script src="Scripts/jQuery-1.6.4.min.js"></script>
        <script src="Scripts/jquery.signalR-2.1.1.min.js"></script>
        <script src="signalr/hubs"></script>
        <script type="text/javascript">
            var hub = $.connection.gameHub;
            hub.client.addGame = function (game) {
                $("#BoardGameTblBody").append("<tr><td>" + game.Id + "</td><td>" + game.Name + "</td><td>" + game.Description + "</td><td>" + game.Quantity + "</td><td>" + game.Price + "</td></tr>");
            };
            $.connection.hub.start();
        </script>

以及背后的代码:

protected void Page_Load(object sender, EventArgs e)
        {
        BoardGameRepeater.DataSource = Application["BoardGameDatabase"];
        BoardGameRepeater.DataBind();
        }

注意这里发生了什么.当服务器调用 context.Clients.All.addGame(game); 时,它会为连接到服务器的每个客户端执行分配给 hub.client.addGame 的函数游戏中心.SignalR 负责为我连接事件,并自动将服务器上的 game 对象转换为客户端上的 game 对象.最重要的是,没有每隔几秒钟来回的网络流量,因此它非常轻巧.

Notice what's happening here. When the server calls context.Clients.All.addGame(game); it's executing the function that's been assigned to hub.client.addGame for every client that is connected to the GameHub. SignalR is taking care of wiring up the events for me, and automatically converting my game object on the server to the game object on the client. And best of all, there's no network traffic back and forth every few seconds, so it's incredibly lightweight.

优点:

  • 网络流量非常小
  • 易于开发,但仍然灵活
  • 不随请求发送视图状态
  • 不会持续轮询服务器.

注意,您可以在客户端上为 editedGame 添加一个函数,以便轻松地将更改的数据推送到客户端(删除相同).

Note, you could add a function on the client for editedGame for pushing changed data out to the client easily (same for delete).

这篇关于如何实现网页的实时数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆