MVC3远程属性和多个提交按钮

时间:2011-05-30 04:22:08

标签: 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不再包含任何导致“多提交按钮”解决方案失败的提交按钮。 p>

还有其他人遇到过这种情况吗?

4 个答案:

答案 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-controllerdata-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表单。