我发现了使用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不再包含任何导致“多提交按钮”解决方案失败的提交按钮。 p>
还有其他人遇到过这种情况吗?
答案 0 :(得分:1)
我知道这不是您问题的直接答案,但我会建议使用客户端JQuery和标记来替代多个提交按钮:
<强>的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" />
}
它可能不如代码解决方案那么优雅,但它提供了一些麻烦,因为实际更改的唯一内容是单击提交按钮时窗体的action-attribute。
基本上它的作用是,只要点击具有属性数据操作集的提交按钮,它就会将其父表单action-attribute替换为属性data-controller
和data-action
的组合。单击按钮,然后触发表单的提交事件。
当然,这个特殊的例子非常通用,它总是会创建/ Controller / Action url,但是这可以通过点击操作中的更多逻辑轻松扩展。
只是一个提示:)
答案 1 :(得分:0)
我不确定它是mvc 3中的一个错误,因为它不是你期待的东西。 RemoteAttribute
导致javascript拦截并使用ajax帖子验证表单。要做到这一点,表单帖子可能会被取消,并且当验证完成时,表单的提交事件可能是直接调用,而不是使用单击的实际按钮。我可以看到你的场景中会出现问题的地方,但这是有道理的。我的建议是,要么不使用RemoteAttribute
并自行验证,要么没有多个表单操作。
答案 2 :(得分:0)
当在使用多个提交按钮的视图中的模型上使用RemoteAttribute时,问题就会出现。无论您使用什么“多按钮”解决方案,POST都不再包含任何提交输入。
我设法通过一些Tweek来解决问题 ActionMethodSelectorAttribute ,并添加了一个隐藏的视图字段和一些javascript来帮助连接各个部分。
<强>视图模型强>
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; }
}
<强> ActionMethodSelectorAttribute 强>
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);
}
答案 3 :(得分:0)
我遇到了同样的问题。
我还附上了一个提交事件,以便在提交之前准备好表格。有趣的是,当我在on submit函数中插入一个断点,然后继续时,问题就消失了。
我通过删除Remote属性并使用ModelState验证字段来结束Ajax表单。