2009-11-05 17 views
9

Używam wtyczki JQuery Form do przesyłania plików w aplikacji ASP.NET MVC. Dowiedziałem się, że ponieważ do przesyłania plików wykorzystywany jest element iframe (a nie XMLHttpRequest, co nie jest możliwe), sprawdzanie po stronie serwera dla IsAjaxRequest kończy się niepowodzeniem.Wykrywanie IsAjaxRequest() przy użyciu ASP.NET MVC i JQuery Form Plugin/File Upload

Widziałem kilka postów związanych z tym pytaniem, ale nie znalazłem żadnych dobrych rozwiązań do obejścia tego problemu. Podobnie jak w przypadku pozostałych aplikacji, chciałbym mieć możliwość obsługi zarówno scenariuszy z włączoną obsługą JavaScript, jak i wyłączonych skryptów JavaScript, dlatego chciałbym wykryć, czy zapytanie dotyczy ajaxu, czy nie.

Zdaję sobie sprawę, że stosowane podejście iframe nie jest technicznie ajax, ale próbuję naśladować efekt ajax.

Wszelkie sugestie byłyby mile widziane.

Odpowiedz

9

Właśnie uświadomiłem sobie, że całkowicie nie odpowiedział na pytanie, więc dodaję do góry tutaj, pozostawiając moją starą odpowiedź poniżej:

problem jest podczas wysyłania pliku na iFrame, Nagłówek "X-Requested-With" nie jest ustawiony i nie możesz ustawić konkretnych nagłówków żądań dla zwykłego formularza POST w JavaScript. Będziesz musiał uciekać się do innych sztuczek, takich jak wysyłanie ukrytego pola z POST, który zawiera wartość, a następnie zmienić lub przesłonić metodę rozszerzenia "IsAjaxRequest", aby również sprawdzić ten warunek. How to override an existing extension method?

Prawdopodobnie najlepszym rozwiązaniem byłoby prawdopodobnie zawierać własną metodę rozszerzenia z inną nazwą, w oparciu off domyślnego MVC kodu metodę rozszerzenia ze zmianami wykryć iFrame przesłać POST, a następnie użyć metody rozszerzenie wszędzie tam, gdzie oczekujesz tego.


jQuery ustawia domyślnie nagłówek "X-Requested-With" na "XMLHttpRequest". Jest to bardzo przydatne, o ile jesteś ostrożny przy wykonywaniu wszystkich wywołań AJAX przez jQuery.

W zależności od potrzeb, można łatwo skonfigurować wykrywanie w filtrze działania z niego korzystać w razie potrzeby, a nawet zbudować go w klasie kontrolera tak:

[jQueryPartial] 
public abstract class MyController : Controller 
{ 
    public bool IsAjaxRequest { get; set; } 
} 

ActionFilterAttribute:

public class jQueryPartial : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     // Verify if a XMLHttpRequest is fired. 
     // This can be done by checking the X-Requested-With 
     // HTTP header. 
     MyController myController = filterContext.Controller as MyController; 
     if (myController != null) 
     { 
      if (filterContext.HttpContext.Request.Headers["X-Requested-With"] != null 
       && filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest") 
      { 
       myController.IsAjaxRequest = true; 
      } 
      else 
      { 
       myController.IsAjaxRequest = false; 
      } 
     } 
    } 
} 

i korzystania realizację:

public class SomeController : MyController 
{ 
    public ActionResult Index() 
    { 
      if (IsAjaxRequest) 
       DoThis(); 
      else 
       DoThat(); 

      return View(); 
    } 
} 
+0

W twoim kodzie , IsAjaxRequest jest zawsze prawdziwy, pokonując cel kodu .... plus to ta sama funkcjonalność, która istnieje w metodzie rozszerzenia ... tak więc to naprawdę nie pomaga. – zowens

+1

Dzięki za informacje. Podążając za twoim przykładem, zakończyłem dynamicznie dodając ukrytą wartość formularza ("isFileUploadAjaxPost") przez JQuery. W kontrolerze sprawdzam tę zmienną formularza. Jeśli jest obecny, używam TempData do przechowywania tej wartości przed wywołaniem RedirectToAction, aby wyświetlić widok "edycji" dla nowo przesłanego pliku. W metodzie działania receive sprawdzam zarówno Request.IsAjaxRequest() (tak jak robiłem cały czas), jak i moją wartość TempData, aby określić, czy żądanie jest "ajax" czy nie. Działa świetnie. Dzięki! – goombaloon

+0

@zowens: Naprawiłem kod teraz, ale tak, zdałem sobie sprawę po jego wykonaniu, a następnie patrząc na metodę rozszerzenia IsAjaxRequest, która jest dokładnie taka sama. Zaadaptowałem kod z ActionFilter, który dynamicznie ustawia stronę wzorcową na podstawie typu żądania, co oczywiście jest nieco mniej redundantne niż powyższy kod. – Jay

11

Należy ustawić nagłówek "X-Requested-With" dla metody IsAjaxRequest, aby zwrócić wartość true. Oto jak to zrobić w jquery.

$(document).ready(function() { 
    jQuery.ajaxSetup({ 
      beforeSend: function (xhr) { 
       xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 
       return xhr; 
      } 
    }); 
}); 
+0

Wtyczka JQuery Form nie używa XMLHttpRequest do przesyłania plików. Używa elementu iframe. – goombaloon

+0

To byłaby doskonała odpowiedź, gdyby zadziałało ... –

+1

pracował dla mnie w kanciastym '$ httpProvider.defaults.headers.common = {'X-Requested-With': 'XMLHttpRequest'};' – parliament

2

właśnie natknąłem acr więc to pytanie i później znalazł lepsze rozwiązanie, więc oto jest (dla każdego, kto dostaje tutaj z google):

Wtyczka jQuery form ma dwie opcje, które mogą pomóc w tym przypadku.

  1. jeśli używasz żądania POST, wydaje się, że jest on zawsze przy użyciu iframe, więc jeśli nie ma potrzeby wysyłania plików, ustawienie iframe = false w opcjach Forma pomógł w moim przypadku.

  2. Jeśli potrzebujesz iframe dla fileuploads, można użyć właściwości data opcji oszukać

    IsAjaxRequest() setting : data: { "X-Requested-With": "XMLHttpRequest" }

Pełny skrypt z obu opcji wygląda tak:

$('#someform').ajaxForm(
{ 
     dataType: 'json', 
     success: onSuccess, 
     error: onError, 
       iframe: false 
     data: { "X-Requested-With": "XMLHttpRequest" } 
    } 
); 
11

Od wersji ASP.NET MVC 2 (i późniejszej) istnieje metoda rozszerzenia na Request.

if (Request.IsAjaxRequest()) 
{ 
    // was an ajax request 
} 

Stosując metodę jQuery takich jak .load() na metodzie kontrolera spowoduje Request.IsAjaxRequest() powrocie prawda.

Powiązane problemy