2012-03-21 15 views
5

Mam 3 aplikacji ASP.NET MVC, który ma działanie postu zwanego Create:zapobiec przesyłaniu podwójna forma

[HttpPost] 
public virtual ActionResult Create(Issues issues) 
{ 
    if (ModelState.IsValid) 
    { 
     context.Issues.Add(issues); 
     context.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
    return View(issues); 
} 

Gdybym dwukrotnie kliknąć na przycisk złożenia przez pomyłkę, będziemy go utworzyć 2x problemów. Czy istnieje sposób, aby temu zapobiec, bez użycia javascript i wyłączając przycisk, myślałem, że całe użycie korzystania z RedirectToAction było temu zapobiec, używając wzorca Post/Redirect/Get?

+1

czy możesz po prostu dodać coś takiego, jak (! Context.Issues.Exists (logic))? –

+1

Wystarczy wyłączyć przycisk przesyłania po kliknięciu! – gdoron

+0

Nie ma takiej metody o nazwie Exists? – CallumVass

Odpowiedz

4

Wzór wspomniałeś (post/Redirect/Get wzorzec projektowy) zapobiega strona odświeża się od podwójnego delegowania ponieważ ostatnia akcja jest GET, POST nie.

Jeśli chcesz, aby zapobiec podwójne kliknięcia z podwójnego księgowania, można:

1. Disable the button after click 
2. Maintain a unique index on 'Issues' and look for duplicates 
3. Maintain something in session that gives you an indication of a double post 

A może kilka więcej sposobów ... Myślę wyłączenie przycisku jest chyba najprostszy bo ciebie przekierowanie na inną stronę i tak.

+0

Jest to w porządku dla powyższego przykładu, ale punktem, do którego dążyłem, jest bardziej zaawansowany przykład, na przykład Ajax.BeginForm, który aktualizuje tylko część strony – CallumVass

+0

@BiffBaffBoff - Aby zapobiec dwukrotnemu kliknięciu strony klienta (AJAX POST), można po prostu zablokować interfejs użytkownika do czasu, aż odpowiedź wróci (synchroniczna) lub wyłączyć przycisk (asynchroniczny) lub implementuj coś po stronie serwera, aby go wykryć. –

+0

Cześć Chris, to jest dokładnie to, co zrobiłem teraz. Wyłączyłem przycisk, dopóki odpowiedź nie wróciła. Dzięki jeszcze raz – CallumVass

1

Można wygenerować identyfikator IssueId po wyświetleniu formularza użytkownikowi, a następnie sprawdzić, czy nie ma problemu z takim identyfikatorem w metodzie Create, a na przykład pomijać takie żądania.

+0

Cóż, po prostu utworzę ciąg dalszy dołączania Id, ponieważ IssueId to moje pole PK, więc przy każdym nowym wydaniu będzie on miał nowy identyfikator (2, 3, 4, 5 itd.) – CallumVass

2

najprostszy sposób mogę myśleć, to użyć obrad:

if (ModelState.IsValid) 
{ 
    DateTime now = DateTime.Now; 
    if (Session["LastAdd"] == null || (now - (DateTime)Session["LastAdd"]).TotalMilliseconds > 1000) 
    { 
     //first time, or more than a second passed since last addition 
     context.Issues.Add(issues); 
     context.SaveChanges(); 
     Session["LastAdd"] = now; 
    } 
    return RedirectToAction("Index"); 
} 
+0

Niestety nie używam sesji jako jego aplikacja uwierzytelniająca Windows – CallumVass

+0

@BiffBaffBoff - Rozpocznij używanie zmiennych 'Session'. –

+0

@ Zmienne sesji Biff nie mają nic wspólnego z uwierzytelnianiem. co sprawia, że ​​myślisz w ten sposób? –

5

proste rozwiązanie!

Wyłącz przycisk przesyłania po kliknięciu. Koniec.

$('submitButtonId').click(function(){ 
    $(this).prop('disabled', true); 
    $(this).attr('disabled', 'disabled'); // for jQuery versions < 1.6. 
}); 
+1

Dzięki temu rozwiązaniu, jeśli użytkownik ma problem z siecią pomiędzy kliknięciem i przesłaniem informacji do serwera, nie ma możliwości odzyskania informacji w formularzu. Jeśli użytkownik poświęci 5 minut na wypełnienie formularza, będą zdenerwowani. Lepszym rozwiązaniem jest prawdopodobnie wyłączenie go tylko do momentu, gdy sieć zakończy się sukcesem lub zakończy się niepowodzeniem. –

+0

Nie będzie działać z wyłączoną obsługą JavaScript? –

+0

@AlexAngas, nic nie zadziała, gdy javascript jest wyłączony. Nie sądzę, istnieje dobry sposób robienia tego bez js. (Odpowiedź od "Wizard" poniżej jest trudnym kodowaniem 1000 ms, co jest dalekie od ideału, a co jeśli użytkownik ma wolne połączenie sieciowe?) – gdoron

0

Wzorzec PRG tego nie zapobiegnie, ponieważ działanie P trwa w tym czasie (co zwykle ma miejsce), a użytkownik może ponownie wysłać formularz (poprzez odświeżenie lub odświeżenie przeglądarki), co spowoduje, że wzorzec PRG "zawieść".

Należy zauważyć, że złośliwi użytkownicy mogą również ominąć wszystkie pomiary po stronie klienta, uruchamiając wiele postów http w krótkich odstępach czasu.

Rozwiązaniem wszystkich powyższych problemów jest sprawdzenie duplikatów przesyłanych po stronie serwera przy użyciu następującej metody, opisanej przeze mnie, here.

Dla Państwa wygody, cytuję:

„Jeśli skorzystać z ukrytym przed fałszerstwem token w swojej formie (jak powinno), można buforować zapobiegające fałszerstwom żeton na pierwszy przedstawić i usunąć żeton z pamięci podręcznej, jeśli jest to wymagane, lub wygasają z pamięci podręcznej wpis po określonym czasie.

będziesz wtedy w stanie sprawdzić z każdego żądania wobec cache czy specyficzna forma została złożona i odrzucić jeśli tak. "