#javascript #c# #html #asp.net-mvc
#javascript #c# #HTML #asp.net-mvc
Вопрос:
Я отключаю кнопку при первом нажатии, чтобы предотвратить повторную отправку транзакции. Если на экране появляется ошибка, и я отправляю их обратно в форму, кнопка по-прежнему отключена, поэтому они не могут повторно отправить форму.
Это моя форма с моим javascript:
@using SuburbanCustPortal.sessions
@model SuburbanCustPortal.Models.PaymentModel.WebPayment
@{
ViewBag.Title = "Make a payment!";
}
@if (CurrentCustomerSession.Current.TokenShowHideSettings.ShowPaymentScreenMessage)
{
<div class="CompanyMessage">
@Html.Raw(@CurrentCustomerSession.Current.TokenSettings.PaymentScreenMessage)
</div>
}
@using (Html.BeginForm("WebPaymentSubmit", "Payment", FormMethod.Post))
{
<div>
<fieldset>
<legend>Please enter the amount of the payment below.</legend>
<div class="paymentPageMargin">
<div class="paymentBlock">
<div class="block_container">
<div class="serviceBox1 paymentBlockTextLeft payment-label-nomargin">
Account Number:
</div>
<div class="serviceBox2 paymentBlockText payment-label-nomargin">
@CurrentCustomerSession.Current.Branch-@CurrentCustomerSession.Current.AccountNumber
</div>
</div>
@if (CurrentCustomerSession.Current.CurrentCustomer.BudgetRate > 0)
{
<div class="block_container">
<div class="serviceBox1 paymentBlockTextLeft payment-label-nomargin">
Budget Rate:
</div>
<div class="serviceBox2 paymentBlockText payment-label-nomargin">
$@string.Format("{0:F2}", CurrentCustomerSession.Current.CurrentCustomer.BudgetRate)
</div>
</div>
<div class="block_container">
<div class="serviceBox1 paymentBlockTextLeft payment-label-nomargin">
Budget Balance:
</div>
<div class="serviceBox2 paymentBlockText payment-label-nomargin">
$@string.Format("{0:F2}", CurrentCustomerSession.Current.CurrentCustomer.BudgetBalance)
</div>
</div>
}
else
{
<div class="block_container">
<div class="serviceBox1 paymentBlockTextLeft payment-label-nomargin">
Account Balance:
</div>
<div class="serviceBox2 paymentBlockText payment-label-nomargin">
@string.Format("{0:F2}", CurrentCustomerSession.Current.CurrentCustomer.TotalBalance)
</div>
</div>
}
</div>
@Html.ValidationSummary(true, "Submit was unsuccessful. Please correct the following errors.")
<div class="paymentCardTypesMargin">
@if ((bool)CurrentCustomerSession.Current.TokenSettings.CreditCardAcceptsVisa)
{
<img src="../Content/images/visa.jpg" alt="Visa Card" height="27" width="42" />
}
@if ((bool)CurrentCustomerSession.Current.TokenSettings.CreditCardAcceptsAmex)
{
<img src="../Content/images/amex.png" alt="Mastercard" height="27" width="42" />
}
@if ((bool)CurrentCustomerSession.Current.TokenSettings.CreditCardAcceptsMasterCard)
{
<img src="../Content/images/mastercard.jpg" alt="Mastercard" height="27" width="42" />
}
@if ((bool)CurrentCustomerSession.Current.TokenSettings.CreditCardAcceptsDiscover)
{
<img src="../Content/images/discover.gif" alt="Mastercard" height="27" width="42" />
}
</div>
<div class="payment-label width300">
Card Holder's Name
</div>
<div class="editor-field width200">
@Html.TextBoxFor(m => m.NameOnCard, new { @class = "makePaymentTextLeft width200" })
</div>
<div class="block_container">
<div class="payment-label-nomargin serviceBox1 width205">
<p>Billing Street Address</p>
</div>
<div class="payment-label-nomargin serviceBox2 width75">
<p>Billing Zip Code</p>
</div>
</div>
<div class="block_container">
<div class="serviceBox1 width200">
@Html.TextBoxFor(m => m.StreetAddress, new { @class = "makePaymentTextLeft width200" })
</div>
<div class="serviceBox2">
@Html.TextBoxFor(m => m.Zip, new { @class = "makePaymentTextLeft width75" })
</div>
</div>
<div class="payment-label">
Credit Card Number
</div>
<div class="editor-field">
@Html.TextBoxFor(m => m.CreditCardNumber, new { @class = "makePaymentTextLeft width200", autocomplete = "off" })
</div>
<div class="block_container">
<div class="serviceBox1 width120">
<p>Expiration Date</p>
</div>
<div class="serviceBox2 width150">
<p>Security Code</p>
</div>
</div>
<div class="block_container">
<div class="serviceBox1 width30">
@Html.TextBoxFor(m => m.CreditCardExpMonth, new { @class = "makePaymentTextLeft width30", @placeholder = "MM", autocomplete = "off" })
</div>
<div class="serviceBox3 width30">
@Html.TextBoxFor(m => m.CreditCardExpYear, new { @class = "makePaymentTextLeft width30", @placeholder = "YY", autocomplete = "off" })
</div>
<div class="serviceBox4 padLeftCvv">
@Html.TextBoxFor(m => m.CreditCardCcv, new { @class = "makePaymentTextLeft width40", autocomplete = "off" })
</div>
</div>
<div class="payment-label">
Payment Amount
</div>
<div class="payment-label-nomargin focus">
@Html.TextBoxFor(m => m.Amount, "{0:F2}", new {@class = "makePaymentTextRight width90", autocomplete = "off"})
</div>
<div class="paymentButton">
<p>
<input id="saveButton" class="typicalbutton" type="submit" value="Pay Now" />
</p>
<script>
// Find ALL <form> tags on your page
$('form').submit(function () {
// On submit disable its submit button
$('input[type=submit]', this).attr('disabled', 'disabled');
});
</script>
</div>
</div>
</fieldset>
</div>
}
Как мне повторно включить кнопку, когда форма не может быть отправлена из-за ошибок в форме?
ПРАВКА1
Это мой метод в моем контроллере, который вызывается при отправке:
[Authorize]
[SessionExpireFilter]
public ActionResult WebPaymentSubmit(PaymentModel.WebPayment model)
{
Console.WriteLine("WebPaymentSubmit Clicked!!");
var control = Logging.StartLog();
control.ClassName = System.Reflection.MethodBase.GetCurrentMethod().Name;
try
{
Logging.WriteLog(control, "Start WebPaymentSubmit");
var hasErrors = false;
if( model.Amount <= 0)
{
hasErrors = true;
ModelState.AddModelError("Amount", "Invalid amount.");
}
if (string.IsNullOrEmpty(model.CreditCardNumber) || LuhnsTest.IsValidCreditCardNumber(model.CreditCardNumber))
{
hasErrors = true;
ModelState.AddModelError("CreditCardNumber", "Invalid credit card number.");
}
if (hasErrors)
{
return View("WebPayment");
}
Представление возврата («WebPayment»); это то, как он отправляется обратно после проверки значения.
ПРАВКА2
Хорошо, я понял, почему он не публикуется. PaymentModel [Требуется] останавливает продолжение формы, поэтому форма не перезагружается.
Если это так, как включить кнопку, если требуемая ошибка в моей PaymentModel?
public class WebPayment
{
[Required]
[DataType(DataType.Text)]
public string StreetAddress { get; set; }
[Required]
[DataType(DataType.Text)]
public string Zip { get; set; }
[Required]
[DataType(DataType.Text)]
public string NameOnCard { get; set; }
[Required]
[DataType(DataType.Text)]
public string CreditCardNumber { get; set; }
[Required]
[DataType(DataType.Text)]
public string CreditCardExpMonth { get; set; }
[Required]
[DataType(DataType.Text)]
public string CreditCardExpYear { get; set; }
[Required]
[DataType(DataType.Text)]
public string CreditCardCcv { get; set; }
[Required]
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:F2}", ApplyFormatInEditMode = true)]
public decimal Amount { get; set; }
}
Комментарии:
1. я бы использовал ajax для отправки формы, поиска ошибки или успеха и включения кнопки обратно
2. Для включения кнопки используется тайм-аут, но вам потребуется какой-то обратный вызов, чтобы изменить кнопку. смотрите: jsbin.com/cecibibuco/edit?html , js, консоль, вывод
3. @JonathanNewton Я использую jquery-1.5.1.min.js , это будет конфликтовать, если я добавлю новую строку jquery в свой заголовок?
4. Я уверен, что подход js будет работать, потому что страница перезагружается после отправки. Этот подход будет работать, если вы будете публиковать сообщения с помощью Ajax
5. Смотрите Мой EDIT2, я узнал больше информации.
Ответ №1:
Вам нужно будет обработать ответ в JavaScript с помощью вызова Ajax, если вы не хотите, чтобы страница обновлялась.
http://jsbin.com/caguzejopu/1/edit?html , js, консоль, вывод
Это означает обновление вашего контроллера для возврата ответа, если использование делает неверный запрос
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Payment declinded");
Ответ №2:
Возможно, это не лучший способ, но не могли бы вы просто включить кнопку при загрузке страницы? При начальной загрузке это не имело бы значения, но при каждой последующей загрузке оно будет сброшено на включено. Таким образом, каждый раз, когда вы загружаете страницу, она явно включается, а затем вы можете управлять ею, как вам нравится. Хотя это сработает, только если страница будет перезагружена после того, как форма не будет отправлена.
Ответ №3:
Если вы используете обратную передачу, этот код повторно включает кнопку при каждой перезагрузке:
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(FormCollection collection)
{
return View();
}
Если вы публикуете с помощью какого-либо javascript, вам придется повторно включить обработчик ошибок.
Второе, что я заметил, это то, что вы используете jQuery во встроенном блоке кода. Вы должны быть уверены, что библиотека уже загружена туда. Обходной путь может заключаться в том, чтобы поместить этот код в scripts
раздел и отобразить его после jQuery
загрузки.
Комментарии:
1. Я обновил свой вопрос в ответ на ваш ответ.
2. На самом деле у меня тоже нет кнопки, отключенной в обновленной настройке. Вы указываете
View
имя для отображения, и в моем случае оно найденоAction
. Таким образом, страница должна перезагрузиться в любом случае.3. Я в замешательстве. Если бы это было так, разве кнопка не была бы включена?
4. На самом деле она не будет включена: страница снова будет отображаться в исходном состоянии. Вы включили кнопку при отображении страницы, а затем добавили атрибут с помощью javascript на стороне клиента (внутри браузера). Когда вы нажимаете кнопку, запрос отправляется на сервер, а затем сервер отображает новую страницу и загружает ее в браузер. В этом случае состояние не сохраняется.
5. Смотрите мою ПРАВКУ2. Я обнаружил, что он не достигает метода, о котором я упоминал выше, потому что PaymentModel не работает на требуемом.
Ответ №4:
Вы могли бы включить кнопки в функциях ‘done’ и ‘fail’ вызова ajax.
$('form').submit(function (e) {
e.preventDefault(); // Prevent default submit action
$('input[type=submit]', this).prop('disabled', true);
// If you're using client side validation as well
if ($(this).valid() === false) {
$('input[type=submit]', this).prop('disabled', false);
return;
}
// Submit manually with Ajax
$.ajax({
url: $('form').attr("action"),
type: $('form').attr("method"),
data: $('form').serialize(),
}).done(function (data) {
// If returning partial view
//$("#your-form-container").html(data);
// Else returning whole view
$(document.body).html(data); // Haven't tested
// I don't think you need this since the form is refreshed anyway
$('input[type=submit]', this).prop('disabled', false);
}).fail(function() {
$('input[type=submit]', this).prop('disabled', false);
});
});