2013-07-19 19 views
6

Chcę zatrzymać akcje, które są wywoływane przez metodę jQuery.ajax po stronie serwera. Mogę zatrzymać żądanie Ajax, używając metody $.ajax.abort() po stronie klienta, ale nie po stronie serwera.Jak przerwać działanie w ASP.NET MVC

Aktualizacja:

użyłem działania asynchronicznej zamiast działania synchronizacji, ale nie to, czego chcę! Jak wiadomo serwer nie może przetworzyć więcej niż jednego żądania w tym samym czasie, ponieważ powoduje, że każde żądanie musi czekać do zakończenia poprzedniego, nawet jeśli poprzednie żądanie zostało anulowane przez metodę $ .Ajax.Abort(). Wiem, jeśli używam [SessionState (System.Web.SessionState.SessionStateBehavior.ReadOnly)] przypisuję to prawie, co chcę, ale to mnie nie satysfakcjonuje.

Przede wszystkim chcę przerwać metodę przetwarzania po stronie serwera przez użytkownika. To wszystko :)

+0

Jeśli rozumiem poprawnie, nie chcesz, aby XHR uderzył w twój serwer? –

+0

:) ... może coś na tych liniach może pomóc http: // stackoverflow.com/questions/216173/differentiating-between-ajax-call-browser-request-request lub http://stackoverflow.com/questions/216173/differentiating-between-an-ajax-call-browser-request –

+2

Dzięki, ale to nie jest czymś, czego chcę! Wzywam akcję, która zajmuje na przykład 1 minutę. Chcę umożliwić użytkownikom anulowanie żądania, jeśli chcą, używam $ .ajax.abort() i działa poprawnie i anuluje żądanie, ale wiem, że serwer działa na poprzednie żądanie. Jeśli wyślę kolejne żądanie z tą sesją na serwerze, musi poczekać do końca ostatniej akcji. –

Odpowiedz

4

Możesz zajrzeć do stosując następujący typ kontrolera Using an Asynchronous Controller in ASP.NET MVC

a także sprawdzić, czy ten artykuł pomoże Ci się także Cancel async web service calls, przepraszam, że nie może dać żadnych przykładów kodu i tym razem.

Stworzyłem przykład jako dowód koncepcji, aby pokazać, że można anulować żądania po stronie serwera. My github async cancel example

Jeśli wywołujesz inne witryny za pomocą kodu, masz dwie opcje, w zależności od docelowego środowiska i metody, której chcesz użyć. I tu jestem w tym odniesienia do opinii:

WebRequest.BeginGetResponse do użytku w .NET 4.0 HttpClient do użytku w .NET 4.5, ta klasa ma metodę, aby anulować wszystkie oczekujące żądania.

Mam nadzieję, że dzięki temu uzyskasz wystarczającą ilość informacji, aby osiągnąć swój cel.

+0

Dzięki, jestem pewien, że zrozumiałeś mnie poprawnie. Czy możesz pokazać mi przykładowy kod? –

+2

Trochę więcej badań może zależeć od używanej wersji mvc. Aby wyjaśnić, rozumiem, że chciałbyś rozpocząć asynchroniczne żądanie, ponieważ jest to długotrwały proces, który użytkownicy mogą anulować. Gdy użytkownik anuluje żądanie, serwer pobiera ten asynchroniczny wątek i zasadniczo przerywa operację. Czy to jest poprawne? – ermagana

+0

Tak, dokładnie! Używam ASP.NET MVC 4, nie pracowałem z async w języku C#, jeśli masz przykładowy kod to mi pomoże! Dziękuję :) –

-1

Prostym rozwiązaniem jest użycie czegoś takiego jak poniżej. Używam go do anulowania długo działających zadań (w szczególności generowania tysięcy powiadomień). Używam również tego samego podejścia do sondowania postępu i aktualizacji paska postępu za pośrednictwem AJAX. Również ten pracuje praktycznie na każdej wersji MVC i nie zależy od nowych funkcji .NET

public class MyController : Controller 
{ 

private static m_CancelAction = false; 

public string CancelAction() 
{ 
    m_CancelAction = true; 
    return "ok"; 
} 

public string LongRunningAction() 
{ 
    while(...) 
    { 
     Dosomething (i.e. Send email, notification, write to file, etc) 

     if(m_CancelAction) 
     { 
      m_CancelAction = false; 
      break; 
      return "aborted"; 
     } 
    } 

    return "ok"; 
} 
} 
+0

Czy nie ma zagrożenia bezpieczeństwa, że ​​inny klient może anulować działanie długo działającej prośby od powiedzmy pierwszego klienta. –

0

widzieliśmy problem w IE, gdy przerwany został przekazany wniosek jeszcze do działania kontrolera - jednak z usunięto argumenty, które prowadzą do różnych błędów, zgłaszane w naszych dziennikach i wpisach aktywności użytkownika.

Mam rozwiązać to za pomocą filtra jak na poniższym

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 
using TWV.Infrastructure; 
using TWV.Models; 

namespace TWV.Controllers 
{ 
    public class TerminateOnAbortAttribute : FilterAttribute, IActionFilter 
    { 
     public void OnActionExecuting(ActionExecutingContext filterContext) 
     { 
      // IE does not always terminate when ajax request has been aborted - however, the input stream gets wiped 
      // The content length - stays the same, and thus we can determine if the request has been aborted 
      long contentLength = filterContext.HttpContext.Request.ContentLength; 
      long inputLength = filterContext.HttpContext.Request.InputStream.Length; 
      bool isAborted = contentLength > 0 && inputLength == 0; 
      if (isAborted) 
      { 
       filterContext.Result = new EmptyResult(); 
      } 
     } 

     public void OnActionExecuted(ActionExecutedContext filterContext) 
     { 
      // Do nothing 
     } 
    } 
} 
3

Oto przykład Backend:

[HttpGet] 
public List<SomeEntity> Get(){ 
     var gotResult = false; 
     var result = new List<SomeEntity>(); 
     var tokenSource2 = new CancellationTokenSource(); 
     CancellationToken ct = tokenSource2.Token; 
     Task.Factory.StartNew(() => 
     { 
      // Do something with cancelation token to break current operation 
      result = SomeWhere.GetSomethingReallySlow(); 
      gotResult = true; 
     }, ct); 
     while (!gotResult) 
     { 
      // When you call abort Response.IsClientConnected will = false 
      if (!Response.IsClientConnected) 
      { 
       tokenSource2.Cancel(); 
       return result; 
      } 
      Thread.Sleep(100); 
     } 
     return result; 
} 

Javascript:

var promise = $.post("/Somewhere") 
setTimeout(function(){promise.abort()}, 1000) 

nadzieję, że nie jestem późno.

+0

Czy można używać "Task.IsCompleted" zamiast flagi "gotResult"? – Simon

Powiązane problemy