Asp.net mvc 3 MVC3 RemoteAttribute和多提交按钮

Asp.net mvc 3 MVC3 RemoteAttribute和多提交按钮,asp.net-mvc-3,Asp.net Mvc 3,我发现了使用MVC 3和RemoteAttibute以及ActionNameSelectorAttribute时出现的一个bug 我已经实现了一个解决方案,支持同一视图上的多个提交按钮,类似于本文: 但是,解决方案是有效的,当我在模型中引入RemoteAttribute时,controllerContext.RequestContext.HttpContext.Request不再包含任何导致“多提交按钮”解决方案失败的提交按钮 还有其他人经历过这种情况吗?我不确定这是否是mvc 3中的错误,因为

我发现了使用MVC 3和RemoteAttibute以及ActionNameSelectorAttribute时出现的一个bug

我已经实现了一个解决方案,支持同一视图上的多个提交按钮,类似于本文:

但是,解决方案是有效的,当我在模型中引入RemoteAttribute时,controllerContext.RequestContext.HttpContext.Request不再包含任何导致“多提交按钮”解决方案失败的提交按钮


还有其他人经历过这种情况吗?

我不确定这是否是mvc 3中的错误,因为这不是您所期望的。
RemoteAttribute
使javascript截取并使用ajax post验证表单。为此,可能会取消表单post,当验证完成时,可能会直接调用表单的提交事件,而不是使用实际单击的按钮。我可以看出在您的场景中这会有什么问题,但这是有道理的。我的建议是,要么不要使用
RemoteAttribute
自己验证东西,要么不要有多个表单操作。

我知道这不是对您问题的直接回答,但我建议使用客户端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>

$(文档).ready(函数(){
$(“输入[type=submit][data action]”)。单击(函数(e){
var$this=$(this);
var form=$this.parents(“form”);
var action=$this.attr('data-action');
var controller=$this.attr('data-controller');
表格.attr('动作',“/”+控制器+“/”+动作);
表单提交();
e、 预防默认值();
});
});
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" />
}
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; }
    }
@使用(Html.BeginForm())
{    
}
它可能没有代码解决方案那么优雅,但它提供了更少的麻烦,因为当单击submitbutton时,唯一实际更改的是表单的action属性

基本上,它所做的是,每当单击带有属性数据操作集的submit按钮时,它都会将其父窗体操作属性替换为单击按钮上属性
数据控制器
数据操作
的组合,然后激发窗体的submit事件

当然,这个特定的示例的通用性很差,它总是会创建/Controller/Action url,但这可以通过单击操作中的一些逻辑轻松地进行扩展


只是一个提示:)

当在使用多个提交按钮的视图中的模型上使用RemoteAttribute时,问题就会显现出来。无论您使用什么“多按钮”解决方案,帖子不再包含任何提交输入

我通过对ActionMethodSelectorAttribute进行一些修改,并添加了一个隐藏的视图字段和一些javascript来帮助连接各个部分,成功地解决了这个问题

视图模型

@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" />
}
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; }
    }
操作方法选择属性

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) %>
<% } %>

我遇到了同样的问题

我还附上了一个提交活动,以便在提交前准备表格。有趣的是,当我在onsubmit函数中插入一个断点,然后继续时,问题就消失了


通过删除Remote属性并使用ModelState验证字段,我得到了一个Ajax表单。

感谢Nathan的文章。我听到你在说什么了。我想我必须自己使用ajax“模拟”RemoteAttribute。不幸的是,表单有多个按钮,这是我无法避免的。谢谢你的建议,但我需要支持禁用的javascript浏览器。我已经想出了一个解决办法,我很快就会发布。