ご協力ありがとうございます@ xavier-j。 これを回った後、私はこれを書きました。同じことを必要とする誰かのために役立つことを願って:あなたは、私がキートークンとして、ここでAntiForgeryTokenを使用しています。このActionFilterは
public class KeepLastRequestAttribute : ActionFilterAttribute
{
public string HashCode { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
Dictionary<string, CancellationTokenSource> clt;
if (filterContext.HttpContext.Application["CancellationTokensDictionary"] != null)
{
clt = (Dictionary<string, CancellationTokenSource>)filterContext.HttpContext.Application["CancellationTokensDictionary"];
}
else
{
clt = new Dictionary<string, CancellationTokenSource>();
}
if (filterContext.HttpContext.Request.Form["__RequestVerificationToken"] != null)
{
HashCode = filterContext.HttpContext.Request.Form["__RequestVerificationToken"];
}
CancellationTokenSource oldCt = null;
clt.TryGetValue(HashCode, out oldCt);
CancellationTokenSource ct = new CancellationTokenSource();
if (oldCt != null)
{
oldCt.Cancel();
clt[HashCode] = ct;
}
else
{
clt.Add(HashCode, ct);
}
filterContext.HttpContext.Application["CancellationTokensDictionary"] = clt;
filterContext.Controller.ViewBag.CancellationToken = ct;
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
base.OnResultExecuted(filterContext);
if (filterContext.Controller.ViewBag.ThreadHasBeenCanceld == null && filterContext.HttpContext.Application["CancellationTokensDictionary"] != null) {
lock (filterContext.HttpContext.Application["CancellationTokensDictionary"])
{
Dictionary<string, CancellationTokenSource> clt = (Dictionary<string, CancellationTokenSource>)filterContext.HttpContext.Application["CancellationTokensDictionary"];
clt.Remove(HashCode);
filterContext.HttpContext.Application["CancellationTokensDictionary"] = clt;
}
}
}
}
を追加必要
まず、あなたはより多くのコントロールを持っている独自のカスタムハッシュコードを追加することができます。
は、コントローラでは、あなたが現在進行中の要求を中止する必要があなたのJavaScriptでこのような何か
[HttpPost]
[KeepLastRequest]
public async Task<ActionResult> DoSlowJob(CancellationToken ct)
{
CancellationTokenSource ctv = ViewBag.CancellationToken;
CancellationTokenSource nct = CancellationTokenSource.CreateLinkedTokenSource(ct, ctv.Token, Response.ClientDisconnectedToken);
var mt = Task.Run(() =>
{
SlowJob(nct.Token);
}, nct.Token);
await mt;
return null;
}
private void SlowJob(CancellationToken ct)
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(200);
if (ct.IsCancellationRequested)
{
this.ViewBag.ThreadHasBeenCanceld = true;
System.Diagnostics.Debug.WriteLine("cancelled!!!");
break;
}
System.Diagnostics.Debug.WriteLine("doing job " + (i + 1));
}
System.Diagnostics.Debug.WriteLine("job done");
return;
}
そして最後に、そうでない場合は、ブラウザのブロック新しい要求を持つことになります。
var onSomethingChanged = function() {
if (currentRequest != null) {
currentRequest.abort();
}
var fullData = $('#my-heavy-form :input').serializeArray();
currentRequest = $.post('/MyController/DoSlowJob', fullData).done(function (data) {
// Do whatever you want with returned data
}).fail(function (f) {
console.log(f);
});
currentRequest.always(function() {
currentRequest = null;
})
}
クライアント側のソリューションを実装すると、コントローラにポストバックする必要がなくなります。 SPAは、ユーザーが保存したときや他のトリガーが発生したときにオブジェクト状態全体をポストバックできます。 – tawman
C#からJavascriptに2400行以上のコードを移動することはできません。 C#では検証とデータ結合を含むすべてのロジックがあります。 また、このソリューションはSPAではなく、この場合はSPAのように見えます。 – Keivan
私は素敵なアプローチは、バウンスシステムを構築することです、あなたはコマンドの配列を持っているので、チェックボックスが変更されるたびにこの操作を保存し、毎秒実行するタイムアウト機能を持っていると想像してください、この関数は、要求を実行してクリアします。このようにして、最後の操作で1分間に1つの要求が発生します –