プロトタイプ メソッド (この場合は Array.prototype メソッド) が IE でのみ消失し、配列が SignalR を通過する場合にのみ問題が発生しました。
私は、この問題を示す小さい/愚かだが単純な概念実証 Web アプリを作成しました (コードはすべて以下にあります)。[すべてのクライアントを更新] をクリックしてから [文字 'r' を含む果物] をクリックすると、_list のプロトタイプ メソッドが見つからず、例外が発生することに注意してください。その場合、配列は SignalR から取得されました。「リセット」をクリックして配列をハードコードされた値にリセットすると、「文字 'r' を含む果物」ボタンが突然機能します - プロトタイプ メソッドが戻ってきました。この問題は IE でのみ発生することに注意してください。
ヒント: 最初に概念実証を書いたとき、問題を再現できませんでした。配列がSignalRを介して取得されたとき、IEにはまだプロトタイプメソッドがありましたが、ページが読み込まれたときに別のエラーが発生しました。誤ってjQueryを2回含めていました。冗長なスクリプトを取り出して 2 番目の jQuery を含めると、(明らかに) そのエラーは修正されましたが、問題を再現できるようになりました。IE には、私が作成した Array プロトタイプ メソッドがありませんでしたが、配列が SignalR 経由で提供された場合のみでした。
myExtensions.js:
Array.prototype.where = function (del)
{
var ret = new Array();
for (var i = 0; i < this.length; i++)
{
if (del(this[i])) ret.push(this[i]);
}
return ret;
}
Array.prototype.select = function (del)
{
var ret = new Array();
for (var i = 0; i < this.length; i++)
{
ret.push(del(this[i]));
}
return ret;
}
_Layout.cshtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>@ViewBag.Title - My ASP.NET MVC Application</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
@Styles.Render("~/Content/css")
@Scripts.Render("~/Scripts/myExtensions.js")
@Scripts.Render("~/bundles/modernizr")
@Scripts.Render("~/Scripts/jquery-1.7.1.js")
@Scripts.Render("~/Scripts/jquery.signalR-1.0.0-rc1.js")
<script src="~/signalr/hubs"></script>
</head>
<body>
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">@Html.ActionLink("IE/SignalR error POC", "Index", "Home")</p>
</div>
</div>
</header>
<div id="body">
@RenderSection("featured", required: false)
<section class="content-wrapper main-content clear-fix">
@RenderBody()
</section>
</div>
<footer>
<div class="content-wrapper">
<div class="float-left">
<p>© @DateTime.Now.Year - My ASP.NET MVC Application</p>
</div>
</div>
</footer>
@*@Scripts.Render("~/Scripts/myExtensions.js")*@
</body>
</html>
ListHub.cs
using System.Linq;
using Microsoft.AspNet.SignalR.Hubs;
namespace SignalR_Bug_POC.Hubs
{
public class ListHub : Hub
{
public void RunTest()
{
Clients.All.updateList(new string[]
{
"apple", "pear", "grape", "strawberry", "rasberry", "orange", "watermelon"
}.Select(f => new { Name = f }).ToList());
}
}
}
インデックス.cshtml
@{
ViewBag.Title = "Home Page";
}
@if(false)
{
@Scripts.Render("~/Scripts/jquery.signalR-1.0.0-rc1.js")
@Scripts.Render("~/Scripts/myExtensions.js")
<script src="~/signalr/hubs"></script>
}
<script type="text/javascript">
var _fruits = ["blueberry", "grape", "orange", "strawberry"].select(function (f) { return { "Name": f } });
var _list;
var conn = $.connection.listHub;
$.connection.hub.start();
conn.client.updateList = function (data)
{
_list = data;
$("#theList").html("");
for (var i = 0; i < _list.length; i++)
{
$("#theList").append("<li>" + _list[i].Name + "</li>");
}
}
$(document).ready(function ()
{
$("#cmdUpdateClients").click(function ()
{
conn.server.runTest();
});
$("#cmdReset").click(function ()
{
conn.client.updateList(_fruits);
});
$("#cmdRunTest").click(function ()
{
var message = "";
var fruitsContaining = _list
.where(function (f) { return f.Name.indexOf('r') >= 0 })
.select(function (f) { return f.Name });
for (var i = 0; i < fruitsContaining.length; i++)
{
message += " - " + fruitsContaining[i] + "\n";
}
alert(message);
});
conn.client.updateList(_fruits);
});
</script>
<input type="button" id="cmdUpdateClients" value="Update All Clients" />
<input type="button" id="cmdReset" value="Reset" />
<input type="button" id="cmdRunTest" value="Fruits containing the letter r." />
<ul id="theList"></ul>
それがコードで間違っているのか (つまり、間違った順序で実行しているのか)、それとも IE のバグなのか SignalR のバグなのかはわかりません。たとえば、conn.client.updateList JS メソッドの最初の行にブレークポイントを設定し、コール スタックを一番上まで追跡すると、(SignalR receive メソッド内に) 'data' オブジェクトの配列が存在しないことがわかります。私のプロトタイプメソッドがありません。