0

これが何が起こっているかです。ASP.NET MVC 4 Web API Web アプリケーションがあります。URL 経由で API リソースを呼び出すことができます。これらの関数の 1 つは、指定された時間のパフォーマンス監視データを取得し、完了すると JSON で返します。しかし、私がやりたいのは戻ることです

ビューではなく、モデル内のブラウザーと API リソースで作業していることに注意することが重要です。ビューがないため、ビューで Javascript を使用するように気軽に言わないでください。また、「.NET」セクションの情報は Web アプリではなくデスクトップ アプリケーションを対象としているため、SignalR wiki を参照するように言わないでください。たとえば、ブラウザに対して「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);
        }
    }
}

SignalR 呼び出しを含む LogDBRepository.cs のメソッドを次に示します。

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 に答える