0

这是正在发生的事情。我有一个 ASP.NET MVC 4 Web API Web 应用程序。我可以通过 URL 调用 API 资源。其中一个函数获取指定时间内的性能监控数据,并在完成后以 JSON 形式返回。但是,我想做的是返回

重要的是要注意我正在使用模型中的浏览器和 API 资源,而不是使用视图。请不要随便告诉我在视图中使用 Javascript,因为没有视图,或者告诉我查看 SignalR wiki,因为“.NET”部分的信息适用于桌面应用程序,而不是 Web 应用程序。例如,您不能向浏览器“Console.WriteLine()”。

重申一下,我正在使用 ASP.NET MVC 4 Web API 来开发 API,并通过浏览器中的 URL 调用 API 并返回 JSON。我正在尝试使用 SignalR 让应用程序将 JSON 发送到浏览器,但它根本没有做任何事情。相反,一旦过程完成,应用程序只需从控制器操作返回完整的 JSON 以及所有性能数据值。换句话说,SignalR 不工作。

所以我想做的是在 API 资源收集所有信息的同时,SignalR 每秒向浏览器发送 JSON,以便客户端可以实时查看正在发生的事情。我需要找出的是为什么 SignalR 不发送它,以及我如何发送信息以在没有 Javascript 的情况下在浏览器中显示,因为我是从模型类而不是视图中工作的。

如您所见,我使用 On 订阅事件,然后使用 Invoke 调用服务器端集线器方法 SendToClient。

请让我知道如果我试图做是不可能的。我从未听说过通过 URL 进行的“实时”动态 API 调用。

这是我的中心课程。它位于 ~/signalr/hubs 并位于名为 LiveHub.cs 的文件中。Send 方法是我试图在下一个代码块中看到的方法中调用的方法。

namespace PerfMon2.signalr.hubs
{
    public class LiveHub : Hub
    {

        public void SendToClient(List<DataValueInfo> json)
        {
            Clients.showValue(json);
        }
    }
}

这是 LogDBRepository.cs 中包含 SignalR 调用的方法。

public List<LogInfo> LogTimedPerfData(string macName, string categoryName, string counterName,
                                          string instanceName, string logName, string live, long? seconds)
    {
        iModsDBRepository modsDB = new iModsDBRepository();
        List<MachineInfo> theMac = modsDB.GetMachineByName(macName);

        if (theMac.Count == 0)
            return new List<LogInfo>();

        else if (instanceName == null)
        {
            if (!PerformanceCounterCategory.Exists(categoryName, macName) ||
                !PerformanceCounterCategory.CounterExists(counterName, categoryName, macName) )
            {
                return new List<LogInfo>();
            }
        }
        else if (instanceName != null)
        {
            if (!PerformanceCounterCategory.Exists(categoryName, macName) ||
                !PerformanceCounterCategory.CounterExists(counterName, categoryName, macName) ||
                !PerformanceCounterCategory.InstanceExists(instanceName, categoryName, macName))
            {
                return new List<LogInfo>();
            }
        }
        else if (logName == null)
        {
            return new List<LogInfo>();
        }

        // Check if entered log name is a duplicate for the authenticated user
        List<LogInfo> checkDuplicateLog = this.GetSingleLog(logName);
        if (checkDuplicateLog.Count > 0)
        {
            return new List<LogInfo>();
        }

        PerformanceCounterCategory category = new PerformanceCounterCategory(categoryName, theMac[0].MachineName);
        if (category.CategoryName == null || category.MachineName == null)
        {
            return new List<LogInfo>();
        }

        List<LogInfo> logIt = new List<LogInfo>();
        if (category.CategoryType != PerformanceCounterCategoryType.SingleInstance)
        {
            List<InstanceInfo> instances = modsDB.GetInstancesFromCatMacName(theMac[0].MachineName, category.CategoryName);

            foreach (InstanceInfo inst in instances)
            {
                if (!category.InstanceExists(inst.InstanceName))
                {
                    continue;
                }
                else if (inst.InstanceName.Equals(instanceName, StringComparison.OrdinalIgnoreCase))
                {
                    PerformanceCounter perfCounter = new PerformanceCounter(categoryName, counterName,
                                                                        inst.InstanceName, theMac[0].MachineName);

                    //CounterSample data = perfCounter.NextSample();
                    //double value = CounterSample.Calculate(data, perfCounter.NextSample());
                    string data = "";
                    List<UserInfo> currUser = this.GetUserByName(WindowsIdentity.GetCurrent().Name);

                    string timeStarted = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt");

                    //string[] dataValues = new string[(int)seconds];
                    List<string> dataValues = new List<string>();

                    var hubConnection = new HubConnection("http://localhost/PerfMon2/");
                    hubConnection.Credentials = CredentialCache.DefaultNetworkCredentials;
                    var perfMon = hubConnection.CreateProxy("LiveHub");
                    // perfMon.On("sendValue", message => Console.WriteLine(message));
                    perfMon.On("showValue", json => Console.WriteLine(json));
                    hubConnection.Start().Wait();

                    List<DataValueInfo> lol = new List<DataValueInfo>();
                    for (int i = 0; i < seconds; i++)
                    {
                        data = "Value " + i + ": " + perfCounter.NextValue().ToString();
                        //dataValues[i] = data;
                        dataValues.Add(data);
                        lol.Add(new DataValueInfo
                        {
                            Value = perfCounter.NextValue().ToString()
                        });
                        //           perfMon.Invoke<List<DataValueInfo>>("Send", lol);
                        perfMon.Invoke("SendToClient", lol);
                        Thread.Sleep(1000);
                    }
                    string timeFinished = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt");

                    Log log = new Log
                    {
                        LogName = logName,
                        CounterName = perfCounter.CounterName,
                        InstanceName = perfCounter.InstanceName,
                        CategoryName = perfCounter.CategoryName,
                        MachineName = perfCounter.MachineName,
                        TimeStarted = timeStarted,
                        TimeFinished = timeFinished,
                        PerformanceData = string.Join(",", dataValues),
                        UserID = currUser[0].UserID
                    };
                    this.CreateLog(log);
                    logIt.Add(new LogInfo
                    {
                        LogName = logName,
                        CounterName = perfCounter.CounterName,
                        InstanceName = perfCounter.InstanceName,
                        CategoryName = perfCounter.CategoryName,
                        MachineName = perfCounter.MachineName,
                        TimeStarted = timeStarted,
                        TimeFinished = timeFinished,
                        PerformanceData = dataValues.ToList<string>()
                    });
                    break;
                }
            }
        }
        else
        {
            PerformanceCounter perfCounter = new PerformanceCounter(categoryName, counterName,
                                                                        "", theMac[0].MachineName);


            string data = "";
            List<UserInfo> currUser = this.GetUserByName(WindowsIdentity.GetCurrent().Name);

            string timeStarted = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt");

            //string[] dataValues = new string[(int)seconds];
            List<string> dataValues = new List<string>();

            var hubConnection = new HubConnection("http://localhost/PerfMon2/");
            hubConnection.Credentials = CredentialCache.DefaultNetworkCredentials;
            var perfMon = hubConnection.CreateProxy("LiveHub");
            // perfMon.On("sendValue", message => Console.WriteLine(message));
            perfMon.On("showValue", json => Console.WriteLine(json));
            hubConnection.Start().Wait();

            List<DataValueInfo> lol = new List<DataValueInfo>();
            for (int i = 0; i < seconds; i++)
            {
                data = "Value " + i + ": " + perfCounter.NextValue().ToString();
                //dataValues[i] = data;
                dataValues.Add(data);
                lol.Add(new DataValueInfo
                {
                    Value = perfCounter.NextValue().ToString()
                });
     //           perfMon.Invoke<List<DataValueInfo>>("Send", lol);
                perfMon.Invoke("SendToClient", lol);
                Thread.Sleep(1000);
            }
            string timeFinished = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt");

            Log log = new Log
            {
                LogName = logName,
                CounterName = perfCounter.CounterName,
                InstanceName = perfCounter.InstanceName,
                CategoryName = perfCounter.CategoryName,
                MachineName = perfCounter.MachineName,
                TimeStarted = timeStarted,
                TimeFinished = timeFinished,
                PerformanceData = string.Join(",", dataValues),
                UserID = currUser[0].UserID
            };              
            this.CreateLog(log);
            logIt.Add(new LogInfo
            {
                LogName = logName,
                CounterName = perfCounter.CounterName,
                InstanceName = perfCounter.InstanceName,
                CategoryName = perfCounter.CategoryName,
                MachineName = perfCounter.MachineName,
                TimeStarted = timeStarted,
                TimeFinished = timeFinished,
                PerformanceData = dataValues.ToList<string>()
            });
        }
        return logIt;
    }

这是 LogController.cs 中方法的控制器:

 [AcceptVerbs("GET", "POST")]
    public List<LogInfo> Log_Perf_Data(string machine_name, string category_name, string counter_name, string instance_name,
                                   string log_name, long? seconds, string live, string enforceQuery)
    {
        LogController.CheckUser();

        // POST api/log/post_data?machine_name=&category_name=&counter_name=&instance_name=&log_name=&seconds=
        if (machine_name != null && category_name != null && counter_name != null && log_name != null && seconds.HasValue && enforceQuery == null)
        {
            List<LogInfo> dataVal = logDB.LogTimedPerfData(machine_name, category_name, counter_name, instance_name,
                                   log_name, live, seconds);
            logDB.SaveChanges();
            return dataVal;

        }

        return new List<LogInfo>();
    }
4

1 回答 1

1

也许你可以用推送技术来实现它。我是这样做的: 带消息的类

 public class Message
    {
        /// <summary>
        /// The name who will receive this message.
        /// </summary>
        public string RecipientName { get; set; }

        /// <summary>
        /// The message content.
        /// </summary>
        public string MessageContent { get; set; }
    }

代表客户的类:

public class Client
    {
        private ManualResetEvent messageEvent = new ManualResetEvent(false);
        private Queue<Message> messageQueue = new Queue<Message>();

        /// <summary>
        /// This method is called by a sender to send a message to this client.
        /// </summary>
        /// <param name="message">the new message</param>
        public void EnqueueMessage(Message message)
        {
            lock (messageQueue)
            {
                messageQueue.Enqueue(message);

                // Set a new message event.
                messageEvent.Set();
            }
        }

        /// <summary>
        /// This method is called by the client to receive messages from the message queue.
        /// If no message, it will wait until a new message is inserted.
        /// </summary>
        /// <returns>the unread message</returns>
        public Message DequeueMessage()
        {
            // Wait until a new message.
            messageEvent.WaitOne();

            lock (messageQueue)
            {
                if (messageQueue.Count == 1)
                {
                    messageEvent.Reset();
                }
                return messageQueue.Dequeue();
            }
        }
    }

向客户端发送消息的类:

public class ClientAdapter
    {
        /// <summary>
        /// The recipient list.
        /// </summary>
        private Dictionary<string, Client> recipients = new Dictionary<string,Client>();

        /// <summary>
        /// Send a message to a particular recipient.
        /// </summary>
        public void SendMessage(Message message)
        {
            if (recipients.ContainsKey(message.RecipientName))
            {
                Client client = recipients[message.RecipientName];

                client.EnqueueMessage(message);
            }
        }

        /// <summary>
        /// Called by a individual recipient to wait and receive a message.
        /// </summary>
        /// <returns>The message content</returns>
        public string GetMessage(string userName)
        {
            string messageContent = string.Empty;

            if (recipients.ContainsKey(userName))
            {
                Client client = recipients[userName];

                messageContent = client.DequeueMessage().MessageContent;
            }

            return messageContent;
        }

        /// <summary>
        /// Join a user to the recipient list.
        /// </summary>
        public void Join(string userName)
        {
            recipients[userName] = new Client();
        }

        /// <summary>
        /// Singleton pattern.
        /// This pattern will ensure there is only one instance of this class in the system.
        /// </summary>
        public static ClientAdapter Instance = new ClientAdapter();
        private ClientAdapter() { }
    }

发送消息:

    Message message = new Message
                                      {
                                          RecipientName = tbRecipientName.Text.Trim(),
                                          MessageContent = tbMessageContent.Text.Trim()
                                      };

                if (!string.IsNullOrWhiteSpace(message.RecipientName) && !string.IsNullOrEmpty(message.MessageContent))
                {
                    // Call the client adapter to send the message to the particular recipient instantly.
                    ClientAdapter.Instance.SendMessage(message);
}

接收消息(这是在测试页面中编写的 JavaScript 函数。它们在 ASPX 页面上呈现消息的内容。在这里你应该实现你的逻辑):

 // This method will persist a http request and wait for messages.
        function waitEvent() {

            CSASPNETReverseAJAX.Dispatcher.WaitMessage("<%= Session["userName"] %>", 
            function (result) {

                displayMessage(result);

                // Keep looping.
                setTimeout(waitEvent, 0);
            }, function () {

                // Keep looping.
                setTimeout(waitEvent, 0);
            });
        }

        // Append a message content to the result panel.
        function displayMessage(message) {
            var panel = document.getElementById("<%= lbMessages.ClientID %>");

            panel.innerHTML += currentTime() + ": " + message + "<br />";
        }

        // Return a current time string.
        function currentTime() {
            var currentDate = new Date();
            return currentDate.getHours() + ":" + currentDate.getMinutes() + ":" + currentDate.getSeconds();
        }
于 2012-09-03T08:35:20.987 回答