#asp.net-mvc-3
#asp.net-mvc-3
Вопрос:
Я обнаружил то, что кажется ошибкой при использовании MVC 3 с RemoteAttibute и ActionNameSelectorAttribute.
Я внедрил решение для поддержки нескольких кнопок отправки в одном представлении, аналогичное этому сообщению:http://blog.ashmind.com/2010/03/15/multiple-submit-buttons-with-asp-net-mvc-final-solution
Решение работает, однако, когда я ввожу RemoteAttribute в свою модель, ControllerContext.RequestContext.HttpContext.Request больше не содержит ни одной из моих кнопок отправки, что приводит к сбою решения «multi-submit-button».
Кто-нибудь еще сталкивался с подобным сценарием?
Ответ №1:
Я знаю, что это не прямой ответ на ваш вопрос, но я бы предложил альтернативное решение для нескольких кнопок отправки, используя вместо этого клиентский jQuery и markup:
Javascript
<script type="text/javascript">
$(document).ready(function () {
$("input[type=submit][data-action]").click(function (e) {
var $this = $(this);
var form = $this.parents("form");
var action = $this.attr('data-action');
var controller = $this.attr('data-controller');
form.attr('action', "/" controller "/" action);
form.submit();
e.preventDefault();
});
});
</script>
HTML
@using (Html.BeginForm())
{
<input type="text" name="name" id="name" />
<input type="submit" value="Save draft" data-action="SaveDraft" data-controller="Home" />
<input type="submit" value="Publish" data-action="Publish" data-controller="Home" />
}
Это может быть не так элегантно, как кодовое решение, но оно предлагает несколько меньше хлопот, поскольку единственное, что на самом деле меняется, — это атрибут действия формы при нажатии кнопки отправки.
По сути, что это делает, так это то, что всякий раз, когда нажимается кнопка отправки с набором атрибутов data-action, она заменяет атрибут действия родительской формы комбинацией атрибутов data-controller
и data-action
на нажатой кнопке, а затем запускает событие отправки формы.
Конечно, этот конкретный пример не является универсальным, и он всегда будет создавать URL-адрес / Controller / Action, но это можно легко расширить с помощью дополнительной логики в click-action.
Просто совет 🙂
Комментарии:
1. Спасибо за предложение, но мне нужно поддерживать отключенные браузеры javascript. Я разработал решение, которое вскоре опубликую.
Ответ №2:
я не уверен, что это ошибка в mvc 3, поскольку это не то, что вы ожидали. RemoteAttribute
заставляет javascript перехватывать и проверять форму с помощью ajax post. для этого публикация формы, вероятно, отменяется, и когда проверка завершена, событие отправки формы, вероятно, вызывается напрямую, а не с использованием фактически нажатой кнопки. я вижу, где это было бы проблематично в вашем сценарии, но это имеет смысл. мое предложение: либо не используйте RemoteAttribute
и не проверяйте вещи самостоятельно, либо не выполняйте несколько действий с формой.
Комментарии:
1. Спасибо за сообщение, Натан. Я слышу, что ты говоришь. Я думаю, мне придется самому «имитировать» RemoteAttribute с помощью ajax. К сожалению, в форме есть несколько кнопок — чего я не могу избежать.
Ответ №3:
Проблема проявляется, когда атрибут RemoteAttribute используется в модели в представлении, где используются кнопки множественной отправки. Независимо от того, какое «многокнопочное» решение вы используете, сообщение больше не содержит никаких входных данных для отправки.
Мне удалось решить проблему с помощью нескольких настроек атрибута ActionMethod selectorattribute и добавления скрытого поля просмотра и некоторого javascript, чтобы помочь соединить элементы.
ViewModel
public class NomineeViewModel
{
[Remote("UserAlreadyRegistered", "Nominee", AdditionalFields="Version", ErrorMessage="This Username is already registered with the agency.")]
public string UserName { get; set; }
public int Version {get; set;}
public string SubmitButtonName{ get; set; }
}
ActionMethod selectorattribute
public class OnlyIfPostedFromButtonAttribute : ActionMethodSelectorAttribute
{
public String SubmitButton { get; set; }
public String ViewModelSubmitButton { get; set; }
public override Boolean IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
{
var buttonName = controllerContext.HttpContext.Request[SubmitButton];
if (buttonName == null)
{
//This is neccessary to support the RemoteAttribute that appears to intercepted the form post
//and removes the submit button from the Request (normally detected in the code above)
var viewModelSubmitButton = controllerContext.HttpContext.Request[ViewModelSubmitButton];
if ((viewModelSubmitButton == null) || (viewModelSubmitButton != SubmitButton))
return false;
}
// Modify the requested action to the name of the method the attribute is attached to
controllerContext.RouteData.Values["action"] = methodInfo.Name;
return true;
}
}
Вид
<script type="text/javascript" language="javascript">
$(function () {
$("input[type=submit][data-action]").click(function (e) {
var action = $(this).attr('data-action');
$("#SubmitButtonName").val(action);
});
});
</script>
<% using (Html.BeginForm())
{%>
<p>
<%= Html.LabelFor(m => m.UserName)%>
<%= Html.DisplayFor(m => m.UserName)%>
</p>
<input type="submit" name="editNominee" value="Edit" data-action="editNominee" />
<input type="submit" name="sendActivationEmail" value="SendActivationEmail" data-action="sendActivationEmail" />
<%=Html.HiddenFor(m=>m.SubmitButtonName) %>
<% } %>
Контроллер
[AcceptVerbs(HttpVerbs.Post)]
[ActionName("Details")]
[OnlyIfPostedFromButton(SubmitButton = "editNominee", ViewModelSubmitButton = "SubmitButtonName")]
public ActionResult DetailsEditNominee(NomineeViewModel nom)
{
return RedirectToAction("Edit", "Nominee", new { id = nom.UserName });
}
[AcceptVerbs(HttpVerbs.Post)]
[ActionName("Details")]
[OnlyIfPostedFromButton(SubmitButton = "sendActivationEmail", ViewModelSubmitButton = "SubmitButtonName")]
public ActionResult DetailsSendActivationEmail(NomineeViewModel nom)
{
return RedirectToAction("SendActivationEmail", "Nominee", new { id = nom.UserName });
}
[OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
public ActionResult UserAlreadyRegistered(string UserName, int Version)
{
//Only validate this property for new records (i.e. Version != zero)
return Version != 0 ? Json(true, JsonRequestBehavior.AllowGet)
: Json(! nomineeService.UserNameAlreadyRegistered(CurrentLogonDetails.TaxAgentId, UserName), JsonRequestBehavior.AllowGet);
}
Ответ №4:
Я столкнулся с той же проблемой.
Я также прикрепил событие отправки для подготовки формы перед отправкой. Интересно, что когда я вставляю точку останова в функцию on submit, а затем продолжаю, проблема исчезает.
В итоге я получил Ajax-форму, удалив удаленный атрибут и подтвердив поле с помощью ModelState.