有没有一些简单的方法来处理同一表单中的多个提交按钮?例子:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" value="Send" />
<input type="submit" value="Cancel" />
<% Html.EndForm(); %>

知道如何在 ASP.NET Framework Beta 中执行此操作吗?我在谷歌上搜索到的所有示例都包含单个按钮。

有帮助吗?

解决方案

这是一个针对多个提交按钮问题的基本上干净的基于属性的解决方案,很大程度上基于来自的帖子和评论 马丁·巴利奥.

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultipleButtonAttribute : ActionNameSelectorAttribute
{
    public string Name { get; set; }
    public string Argument { get; set; }

    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {
        var isValidName = false;
        var keyValue = string.Format("{0}:{1}", Name, Argument);
        var value = controllerContext.Controller.ValueProvider.GetValue(keyValue);

        if (value != null)
        {
            controllerContext.Controller.ControllerContext.RouteData.Values[Name] = Argument;
            isValidName = true;
        }

        return isValidName;
    }
}

剃刀:

<form action="" method="post">
 <input type="submit" value="Save" name="action:Save" />
 <input type="submit" value="Cancel" name="action:Cancel" />
</form>

和控制器:

[HttpPost]
[MultipleButton(Name = "action", Argument = "Save")]
public ActionResult Save(MessageModel mm) { ... }

[HttpPost]
[MultipleButton(Name = "action", Argument = "Cancel")]
public ActionResult Cancel(MessageModel mm) { ... }

更新: 剃刀页面 看起来提供相同的开箱即用功能。对于新的开发,这可能是更好的选择。

其他提示

给您提交按钮的名称,然后检查在控制器方法提交的值:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="submitButton" value="Send" />
<input type="submit" name="submitButton" value="Cancel" />
<% Html.EndForm(); %>

张贴到

public class MyController : Controller {
    public ActionResult MyAction(string submitButton) {
        switch(submitButton) {
            case "Send":
                // delegate sending to another controller action
                return(Send());
            case "Cancel":
                // call another action to perform the cancellation
                return(Cancel());
            default:
                // If they've submitted the form without a submitButton, 
                // just return the view again.
                return(View());
        }
    }

    private ActionResult Cancel() {
        // process the cancellation request here.
        return(View("Cancelled"));
    }

    private ActionResult Send() {
        // perform the actual send operation here.
        return(View("SendConfirmed"));
    }

}

编辑:

要扩展这种方法与本地化的网站工作,其他地方隔离邮件(例如编译一个资源文件来一个强类型的资源类)

然后,修改代码,以便它的工作原理是:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="submitButton" value="<%= Html.Encode(Resources.Messages.Send)%>" />
<input type="submit" name="submitButton" value="<%=Html.Encode(Resources.Messages.Cancel)%>" />
<% Html.EndForm(); %>

和控制器应该是这样的:

// Note that the localized resources aren't constants, so 
// we can't use a switch statement.

if (submitButton == Resources.Messages.Send) { 
    // delegate sending to another controller action
    return(Send());

} else if (submitButton == Resources.Messages.Cancel) {
     // call another action to perform the cancellation
     return(Cancel());
}

您可以在行动已经提到核对姓名,但你可能会考虑这是否是好的设计。这是要考虑的行动,而不是几个这样的设计太像按钮名称UI方面的责任是一个好主意。所以考虑使用2种形式和2个动作:

<% Html.BeginForm("Send", "MyController", FormMethod.Post); %>
<input type="submit" name="button" value="Send" />
<% Html.EndForm(); %>

<% Html.BeginForm("Cancel", "MyController", FormMethod.Post); %>
<input type="submit" name="button" value="Cancel" />
<% Html.EndForm(); %>

此外,在“取消”的情况下,你通常只是不处理形式,并打算在新的URL。在这种情况下,你并不需要在所有提交表单,只是需要一个链接:

<%=Html.ActionLink("Cancel", "List", "MyController") %>

Eilon建议你可以做这样的:

  

如果你有一个以上的按钮你   通过给它们之间可以区分   每个按钮的名称:

<input type="submit" name="SaveButton" value="Save data" />
<input type="submit" name="CancelButton" value="Cancel and go back to main page" />
     

在您的控制器的操作方法你   可以添加后的命名参数   HTML输入标签名:

public ActionResult DoSomeStuff(string saveButton, string
cancelButton, ... other parameters ...)
{ ... }
     

如果任何值被发布到的一个   这些参数,这意味着   按钮是点击得到的一个。   Web浏览器将只发布一个值   为一个按钮得到点击的。   所有其他值将是空的。

if (saveButton != null) { /* do save logic */ }
if (cancelButton != null) { /* do cancel logic */ }

我喜欢这个方法,因为它不依赖于在提交按钮,其更可能不同于所分配的名称改变,并且不需要Javascript被激活的value属性

请参阅: http://forums.asp.net/p/1369617/2865166.aspx#2865166

刚写了一个关于这个职位: 多个提交按钮与ASP.NET MVC

基本上,代替使用ActionMethodSelectorAttribute,我使用 ActionNameSelectorAttribute,这让我假装动作的名称是什么我希望它是。幸运的是,ActionNameSelectorAttribute不只是让我指定动作的名称,而不是我可以选择当前的行动是否符合要求。

因此,有我的课(顺便说一句,我不是太喜欢这个名字):

public class HttpParamActionAttribute : ActionNameSelectorAttribute {
    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) {
        if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
            return true;

        if (!actionName.Equals("Action", StringComparison.InvariantCultureIgnoreCase))
            return false;

        var request = controllerContext.RequestContext.HttpContext.Request;
        return request[methodInfo.Name] != null;
    }
} 

要使用刚刚定义像这样的形式:

<% using (Html.BeginForm("Action", "Post")) { %>
  <!— …form fields… -->
  <input type="submit" name="saveDraft" value="Save Draft" />
  <input type="submit" name="publish" value="Publish" />
<% } %> 

和与两种方法控制器

public class PostController : Controller {
    [HttpParamAction]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult SaveDraft(…) {
        //…
    }

    [HttpParamAction]
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Publish(…) {
        //…
    } 
}

正如你看到的,属性不要求你在所有指定任何东西。此外,按钮的名字被直接翻译的方法名。另外(我还没有尝试过),这应该是正常的行为以及工作,这样你就可以张贴到任何人 直接

我建议有关方面的看看马腾Balliauw的解决方案。我觉得这是非常优雅。

在情况下,链接自败,它的使用施加到一个控制器动作的MultiButton属性,以指示哪个按钮点击该动作涉及的应

它短,套房:

  

它是由的Jeroen DOP 回答

<input type="submit" name="submitbutton1" value="submit1" />
<input type="submit" name="submitbutton2" value="submit2" />

和做这样在代码behinde

 if( Request.Form["submitbutton1"] != null)
{
    // Code for function 1
}
else if(Request.Form["submitButton2"] != null )
{
       // code for function 2
}

好运。

您应该能够命名的按钮,并给他们一个值;然后映射这个名称作为参数传递给动作。或者,使用2个独立的动作链接或2种形式。

您可以这样写:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="button" value="Send" />
<input type="submit" name="button" value="Cancel" />
<% Html.EndForm(); %>

然后在页面检查,如果名称==“发送”或名称==“取消” ...

东西我不喜欢ActionSelectName是IsValidName被称为用于在控制器的每一个动作的方法;我不知道为什么是这样工作的。我想,每一个按钮都有基于它做什么不同名称的解决方案,但我不喜欢,你必须有在动作方法的形式按钮多参数的事实。我已经创建了一个枚举所有按钮类型:

public enum ButtonType
{
    Submit,
    Cancel,
    Delete
}

相反ActionSelectName的,我使用一个ActionFilter:

public class MultipleButtonsEnumAttribute : ActionFilterAttribute
{
    public Type EnumType { get; set; }

    public MultipleButtonsEnumAttribute(Type enumType)
    {
        EnumType = enumType;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        foreach (var key in filterContext.HttpContext.Request.Form.AllKeys)
        {
            if (Enum.IsDefined(EnumType, key))
            {
                var pDesc = filterContext.ActionDescriptor.GetParameters()
                    .FirstOrDefault(x => x.ParameterType == EnumType);
                filterContext.ActionParameters[pDesc.ParameterName] = Enum.Parse(EnumType, key);
                break;
            }
        }
    }
}

在过滤器将在表格数据找到按钮名称,如果按钮名称匹配任何在枚举定义的按钮类型,它会发现动作参数中的按钮类型参数:

[MultipleButtonsEnumAttribute(typeof(ButtonType))]
public ActionResult Manage(ButtonType buttonPressed, ManageViewModel model)
{
    if (button == ButtonType.Cancel)
    {
        return RedirectToAction("Index", "Home");
    }
    //and so on
    return View(model)
}

和然后在视图中,我可以使用:

<input type="submit" value="Button Cancel" name="@ButtonType.Cancel" />
<input type="submit" value="Button Submit" name="@ButtonType.Submit" />

下面是什么工作最适合我:

<input type="submit" value="Delete" name="onDelete" />
<input type="submit" value="Save" name="onSave" />


public ActionResult Practice(MyModel model, string onSave, string onDelete)
{
    if (onDelete != null)
    {
        // Delete the object
        ...
        return EmptyResult();
    }

    // Save the object
    ...
    return EmptyResult();
}

如果你没有对使用HTML 5的限制,可以使用与<button>属性的formaction标签:

<form action="demo_form.asp" method="get">
   First name: <input type="text" name="fname" /><br />
   Last name: <input type="text" name="lname" /><br />
   <button type="submit">Submit</button><br />
   <button type="submit" formaction="demo_admin.asp">Submit as admin</button>
</form>

参考: http://www.w3schools.com/html5/att_button_formaction.asp

如果你的浏览器支持的输入按钮的属性formaction(IE 10+,不知道其他的浏览器),那么以下应该工作:

@using (Html.BeginForm()){
    //put form inputs here

<input id="sendBtn" value="Send" type="submit" formaction="@Url.Action("Name Of Send Action")" />

<input id="cancelBtn" value="Cancel" type="submit" formaction="@Url.Action("Name of Cancel Action") />

}

我也遇到过这个“问题”,但通过添加以下内容找到了一个相当合乎逻辑的解决方案 name 属性。我不记得在其他语言中遇到过这个问题。

http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2

  • ...
  • 如果一张表单包含多个提交按钮,则只有激活的提交按钮才成功。
  • ...

下面代码的意思 value 属性可以被更改、本地化、国际化,而无需 需要 用于检查强类型资源文件或常量的额外代码。

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="send" value="Send" />
<input type="submit" name="cancel" value="Cancel" />
<input type="submit" name="draft" value="Save as draft" />
<% Html.EndForm(); %>`

在接收端,您只需要检查您已知的提交类型是否不存在 null

public ActionResult YourAction(YourModel model) {

    if(Request["send"] != null) {

        // we got a send

    }else if(Request["cancel"]) {

        // we got a cancel, but would you really want to post data for this?

    }else if(Request["draft"]) {

        // we got a draft

    }

}

您可以通过三种方式解决上述问题

  1. HTML方式
  2. Jquery方式
  3. “ActionNameSelectorAttribute”方式

下面的视频以演示方式总结了所有三种方法。

https://www.facebook.com/shivprasad.koirala/videos/vb.100002224977742/809335512483940

HTML 方式:-

在 HTML 方式中,我们需要创建两个表单并将“提交”按钮放置在每个表单内。每种形式的动作都会指向不同/各自的动作。您可以看到下面的代码,第一个表单将发布到“Action1”,第二个表单将发布到“Action2”,具体取决于单击哪个“提交”按钮。

<form action="Action1" method=post>
<input type=”submit” name=”Submit1”/>
</form>

<form action="Action2" method=post>
<input type=”submit” name=”Submit2”>
</form>

阿贾克斯方式:-

如果您是 Ajax 爱好者,那么第二个选项会让您更兴奋。通过Ajax方式我们可以创建两个不同的函数“Fun1”和“Fun1”,见下面的代码。这些函数将使用 JQUERY 或任何其他框架进行 Ajax 调用。这些函数中的每一个都与“Submit”按钮的“OnClick”事件绑定。这些函数中的每一个都会调用各自的操作名称。

<Script language="javascript">
function Fun1()
{
$.post(“/Action1”,null,CallBack1);
}
function Fun2()
{
$.post(“/Action2”,null,CallBack2);
}
</Script>

<form action="/Action1" method=post>
<input type=submit name=sub1 onclick=”Fun2()”/>
</form>
<form action="/Action2" method=post>
<input type=submit name=sub2 onclick=”Fun1()”/>
</form>

使用“ActionNameSelectorAttribute”:-

这是一个很棒且干净的选择。“ActionNameSelectorAttribute”是一个简单的属性类,我们可以在其中编写决策逻辑来决定可以执行哪个操作。

因此,第一件事是在 HTML 中,我们需要为提交按钮添加正确的名称,以便在服务器上识别它们。

您可以看到我们已将“保存”和“删除”添加到按钮名称中。您还可以注意到,在操作中我们刚刚输入了控制器名称“Customer”,而不是特定的操作名称。我们期望操作名称将由“ActionNameSelectorAttribute”决定。

<form action=”Customer” method=post>
<input type=submit value="Save" name="Save" /> <br />
<input type=submit value="Delete" name="Delete"/>
</form>

因此,当单击提交按钮时,它首先会点击“ActionNameSelector”属性,然后根据触发的提交来调用适当的操作。

enter image description here

因此,第一步是创建一个继承自“ActionNameSelectorAttribute”类的类。在这个类中,我们创建了一个简单的属性“Name”。

我们还需要重写返回 true 或 flase 的“IsValidName”函数。这个函数是我们编写是否必须执行某个操作的逻辑的地方。因此,如果此函数返回 true,则执行该操作,否则不执行该操作。

public class SubmitButtonSelector : ActionNameSelectorAttribute
    {
        public string Name { get; set; }
        public override bool IsValidName(ControllerContext controllerContext, string actionName, System.Reflection.MethodInfo methodInfo)
        {
            // Try to find out if the name exists in the data sent from form
var value = controllerContext.Controller.ValueProvider.GetValue(Name);
            if (value != null)
            {
                return true;
            }
            return false;

        }
    }

上述函数的核心部分在下面的代码中。“ValueProvider”集合包含从表单发布的所有数据。因此,它首先查找“Name”值,如果在 HTTP 请求中找到它,则返回 true,否则返回 false。

var value = controllerContext.Controller.ValueProvider.GetValue(Name);
if (value != null)
      {
        return true;
      }
      return false;

然后可以在相应的操作上修饰该属性类,并可以提供相应的“名称”值。因此,如果提交正在执行此操作,并且名称与 HTML 提交按钮名称匹配,则它会进一步执行该操作,否则不会执行。

public class CustomerController : Controller
{
        [SubmitButtonSelector(Name="Save")]
        public ActionResult Save()
        {
            return Content("Save Called");
        }
        [SubmitButtonSelector(Name = "Delete")]
        public ActionResult Delete()
        {
            return Content("Delete Called");
        }
}

David Findley 在他的 ASP.Net 博客上写了关于执行此操作的 3 种不同选项。

阅读文章 同一表单中的多个按钮 查看他的解决方案以及每个解决方案的优点和缺点。恕我直言,他提供了一个非常优雅的解决方案,它利用了您装饰动作的属性。

这是我会使用的技术,但我在这里还没有看到它。激发此解决方案的链接(由Saajid Ismail发布)是 http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multiple-buttons-in-the-same-form.aspx)。它采用了 Dylan Beattie 的答案来毫无问题地进行本地化。

在视图中:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<button name="button" value="send"><%: Resources.Messages.Send %></button>
<button name="button" value="cancel"><%: Resources.Messages.Cancel %></button>
<% Html.EndForm(); %>

在控制器中:

public class MyController : Controller 
{
    public ActionResult MyAction(string button)
    {
         switch(button)
         {
             case "send":
                 this.DoSend();
                 break;
             case "cancel":
                 this.DoCancel();
                 break;
         }
    }
}

这个脚本允许指定一个数据formaction属性,这将在所有的浏览器HTML5 formaction属性工作(以不显眼的方式):

$(document).on('click', '[type="submit"][data-form-action]', function(event) {
    var $this = $(this),
    var formAction = $this.attr('data-form-action'),
    $form = $($this.closest('form'));
    $form.attr('action', formAction);             
});

包含按钮的形式将被张贴到在数据形式-action属性中指定的URL:

<button type="submit" data-form-action="different/url">Submit</button>   

此需要的jQuery 1.7。对于先前的版本,你应该使用live()代替on()

下面是我写处理多个图像和/或文本按钮的扩展方法。

下面是一种用于图像按钮HTML:

<input id="btnJoin" name="Join" src="/content/images/buttons/btnJoin.png" 
       type="image">

或用于文本提交按钮:

<input type="submit" class="ui-button green" name="Submit_Join" value="Add to cart"  />
<input type="submit" class="ui-button red" name="Submit_Skip" value="Not today"  />

下面是从与form.GetSubmitButtonName()控制器调用扩展方法。对于图像按钮,它看起来与.x一个形状参数(其表示图像按钮被单击)并提取名称。对于经常input按钮,它看起来与Submit_开始的姓名和事后提取命令。因为我抽象掉确定“命令”的逻辑可以图像+文本按钮之间的客户端上不改变服务器端代码切换。

public static class FormCollectionExtensions
{
    public static string GetSubmitButtonName(this FormCollection formCollection)
    {
        return GetSubmitButtonName(formCollection, true);
    }

    public static string GetSubmitButtonName(this FormCollection formCollection, bool throwOnError)
    {
        var imageButton = formCollection.Keys.OfType<string>().Where(x => x.EndsWith(".x")).SingleOrDefault();
        var textButton = formCollection.Keys.OfType<string>().Where(x => x.StartsWith("Submit_")).SingleOrDefault();

        if (textButton != null)
        {
            return textButton.Substring("Submit_".Length);
        }

        // we got something like AddToCart.x
        if (imageButton != null)
        {
            return imageButton.Substring(0, imageButton.Length - 2);
        }

        if (throwOnError)
        {
            throw new ApplicationException("No button found");
        }
        else
        {
            return null;
        }
    }
}

注意:对于你必须前缀Submit_名称文本按钮。我喜欢这种方式,原因是其意味着你可以改变文本(显示)值,而无需更改代码。不像SELECT元件,INPUT按钮仅具有“价值”和没有单独的“文本”属性。我说的按钮在不同的上下文有不同的事情 - 但映射到相同的“命令”。我更喜欢不必为== "Add to cart"码提取的名字这样。

我没有足够的代表在正确的位置发表评论,但我花了这一切的日子,所以想分享。

虽然试图执行 “MultipleButtonAttribute” 溶液ValueProvider.GetValue(keyValue)会错误地回来null

原来我被引用System.Web.MVC版本3.0时它应该是4.0(其它组件是4.0)。我不知道为什么我的项目没有正确升级,我没有其他明显的问题。

因此,如果您ActionNameSelectorAttribute是不工作...检查。

我敢迟到了,但在这里不用... 我从执行借用@mkozicki但需要较少的硬编码字符串来得到错误的。的框架4.5+需要即可。从本质上讲,控制器方法名应该是关键的路由。

<强>标记即可。按钮名称必须以"action:[controllerMethodName]"被键入

(注意使用C#6 nameof API的,到要调用控制器方法的名称提供特定类型的参考。

<form>
    ... form fields ....
    <button name="action:@nameof(MyApp.Controllers.MyController.FundDeathStar)" type="submit" formmethod="post">Fund Death Star</button>
    <button name="action:@nameof(MyApp.Controllers.MyController.HireBoba)" type="submit" formmethod="post">Hire Boba Fett</button>
</form>

<强>控制器

namespace MyApp.Controllers
{
    class MyController
    {    
        [SubmitActionToThisMethod]
        public async Task<ActionResult> FundDeathStar(ImperialModel model)
        {
            await TrainStormTroopers();
            return View();
        }

        [SubmitActionToThisMethod]
        public async Task<ActionResult> HireBoba(ImperialModel model)
        {
            await RepairSlave1();
            return View();
        }
    }
}

<强>属性魔术即可。注意使用 CallerMemberName 善。

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class SubmitActionToThisMethodAttribute : ActionNameSelectorAttribute
{        
    public SubmitActionToThisMethodAttribute([CallerMemberName]string ControllerMethodName = "")
    {
        controllerMethod = ControllerMethodName;
        actionFormat = string.Concat(actionConstant, ":", controllerMethod);
    }
    const string actionConstant = "action";
    readonly string actionFormat;
    readonly string controllerMethod;

    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {
        var isValidName = false;
        var value = controllerContext.Controller.ValueProvider.GetValue(actionFormat);

        if (value != null)
        {
            controllerContext.Controller.ControllerContext.RouteData.Values[actionConstant] = controllerMethod;
            isValidName = true;
        }
        return isValidName;
    }
}

我尝试综合所有解决方案,并创建了一个 [ButtenHandler] 属性,可以轻松处理表单上的多个按钮。

我在 CodeProject 上描述过 ASP.NET MVC 中的多个参数化(可本地化)表单按钮.

要处理此按钮的简单情况:

<button type="submit" name="AddDepartment">Add Department</button>

您将拥有类似于以下操作方法的内容:

[ButtonHandler()]
public ActionResult AddDepartment(Company model)
{
    model.Departments.Add(new Department());
    return View(model);
}

请注意按钮的名称如何与操作方法的名称相匹配。本文还介绍了如何使用带有值的按钮和带有索引的按钮。

//model
    public class input_element
        {
         public string Btn { get; set; }
        }   

//views--submit btn can be input type also...
    @using (Html.BeginForm())
    {
            <button type="submit" name="btn" value="verify">
             Verify data</button>
            <button type="submit" name="btn" value="save">
             Save data</button>    
            <button type="submit" name="btn" value="redirect">
                 Redirect</button>
    }

//controller

    public ActionResult About()
        {
            ViewBag.Message = "Your app description page.";
            return View();
        }

        [HttpPost]
        public ActionResult About(input_element model)
        {
                if (model.Btn == "verify")
                {
                // the Verify button was clicked
                }
                else if (model.Btn == "save")
                {
                // the Save button was clicked
                } 
                else if (model.Btn == "redirect")
                {
                // the Redirect button was clicked
                } 
                return View();
        }

这是我发现的最佳方式:

HTTP:// iwayneo。 blogspot.co.uk/2013/10/aspnet-mvc-action-selector-with-list.html

下面是代码:

    /// <summary>
    /// ActionMethodSelector to enable submit buttons to execute specific action methods.
    /// </summary>
    public class AcceptParameterAttribute : ActionMethodSelectorAttribute
   {
        /// <summary>
        /// Gets or sets the value to use to inject the index into
        /// </summary>
       public string TargetArgument { get; set; }

       /// <summary>
       /// Gets or sets the value to use in submit button to identify which method to select. This must be unique in each controller.
       /// </summary>
       public string Action { get; set; }

       /// <summary>
       /// Gets or sets the regular expression to match the action.
       /// </summary>
       public string ActionRegex { get; set; }

       /// <summary>
       /// Determines whether the action method selection is valid for the specified controller context.
       /// </summary>
       /// <param name="controllerContext">The controller context.</param>
       /// <param name="methodInfo">Information about the action method.</param>
       /// <returns>true if the action method selection is valid for the specified controller context; otherwise, false.</returns>
       public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
       {

           if (controllerContext == null)
           {
               throw new ArgumentNullException("controllerContext");
           }

           Func<NameValueCollection> formGetter;
           Func<NameValueCollection> queryStringGetter;

           ValidationUtility.GetUnvalidatedCollections(HttpContext.Current, out formGetter, out queryStringGetter);

           var form = formGetter();
           var queryString = queryStringGetter();

           var req = form.AllKeys.Any() ? form : queryString;

           if (!string.IsNullOrEmpty(this.ActionRegex))
           {
               foreach (var key in req.AllKeys.Where(k => k.StartsWith(Action, true, System.Threading.Thread.CurrentThread.CurrentCulture)))
               {
                   if (key.Contains(":"))
                   {
                       if (key.Split(':').Count() == this.ActionRegex.Split(':').Count())
                       {
                           bool match = false;
                           for (int i = 0; i < key.Split(':').Count(); i++)
                           {
                               if (Regex.IsMatch(key.Split(':')[0], this.ActionRegex.Split(':')[0]))
                               {
                                   match = true;
                               }
                               else
                               {
                                   match = false;
                                   break;
                               }
                           }

                           if (match)
                           {
                               return !string.IsNullOrEmpty(req[key]);
                           }
                       }
                   }
                   else
                   {
                       if (Regex.IsMatch(key, this.Action + this.ActionRegex))
                       {
                           return !string.IsNullOrEmpty(req[key]);
                       }
                   }

               }
               return false;
           }
           else
           {
               return req.AllKeys.Contains(this.Action);
           }
       }
   }

享受代码臭味少多提交按钮的未来。

感谢您

[HttpPost]
public ActionResult ConfirmMobile(string nameValueResend, string nameValueSubmit, RegisterModel model)
    {
        var button = nameValueResend ?? nameValueSubmit;
        if (button == "Resend")
        {

        }
        else
        {

        }
    }


    Razor file Content:
    @using (Html.BeginForm()
    {
        <div class="page registration-result-page">

            <div class="page-title">
                <h1> Confirm Mobile Number</h1>
            </div>

            <div class="result">
                @Html.EditorFor(model => model.VefificationCode)
                @Html.LabelFor(model => model.VefificationCode, new { })
                @Html.ValidationMessageFor(model => model.VefificationCode)
            </div>
            <div class="buttons">
                <button type="submit" class="btn" name="nameValueResend" value="Resend">
                    Resend
                </button>
                <button type="submit" class="btn" name="nameValueSubmit" value="Verify">
                    Submit
                </button>

            </div>
            </div>

    }

HttpParamActionAttribute方法的但具有错误修正对过期/无效的会话回发不导致错误修改版本。要查看这是否与您当前网站的问题,在一个窗口中打开你的表单,只是你去点击SavePublish,打开一个复制窗口,以及注销之前。现在回到你的第一个窗口,并尝试使用任一按钮提交表单。对我来说,所以这一变化解决了这个问题对我来说我得到了一个错误。我忽略了一堆东西为简洁起见,但你应该明白我的意思。关键部件是ActionName所述属性,并确保列入传入的名字是显示形式视图的名称

<强>属性类

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class HttpParamActionAttribute : ActionNameSelectorAttribute
{
    private readonly string actionName;

    public HttpParamActionAttribute(string actionName)
    {
        this.actionName = actionName;
    }

    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {
        if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
            return true;

        if (!actionName.Equals(this.actionName, StringComparison.InvariantCultureIgnoreCase))
            return false;

        var request = controllerContext.RequestContext.HttpContext.Request;
        return request[methodInfo.Name] != null;
    }
}

<强>控制器

[Authorize(Roles="CanAddContent")]
public ActionResult CreateContent(Guid contentOwnerId)
{
    var viewModel = new ContentViewModel
    {
        ContentOwnerId = contentOwnerId
        //populate rest of view model
    }
    return View("CreateContent", viewModel);
}

[Authorize(Roles="CanAddContent"), HttpPost, HttpParamAction("CreateContent"), ValidateAntiForgeryToken]
public ActionResult SaveDraft(ContentFormModel model)
{
    //Save as draft
    return RedirectToAction("CreateContent");
}

[Authorize(Roles="CanAddContent"), HttpPost, HttpParamAction("CreateContent"), ValidateAntiForgeryToken]
public ActionResult Publish(ContentFormModel model)
{
    //publish content
    return RedirectToAction("CreateContent");
}

查看

@using (Ajax.BeginForm("CreateContent", "MyController", new { contentOwnerId = Model.ContentOwnerId }))
{
    @Html.AntiForgeryToken()
    @Html.HiddenFor(x => x.ContentOwnerId)

    <!-- Rest of your form controls -->
    <input name="SaveDraft" type="submit" value="SaveDraft" />
    <input name="Publish" type="submit" value="Publish" />
}

使用一个扩展方法我JQuery的方法:

public static MvcHtmlString SubmitButtonFor<TController>(this HtmlHelper helper, Expression<Action<TController>> action, string value) where TController : Controller
{
    RouteValueDictionary routingValues = Microsoft.Web.Mvc.Internal.ExpressionHelper.GetRouteValuesFromExpression(action);

    var onclick = string.Format("$('form').first().attr('action', '/{0}')", string.Join("/", routingValues.Values.ToArray().Where(x => x != null).Select(x => x.ToString()).ToArray()));
    var html = "<input type=\"submit\" value=\"" + value + "\" onclick=\"" + onclick + "\" />";

    return MvcHtmlString.Create(html);
}

可以使用这样的:

@(Html.SubmitButtonFor<FooController>(c => c.Save(null), "Save"))

和它呈现像这样:

<input type="submit" value="Save" onclick="$('form').first().attr('action', '/Foo/Save')" >

有关每个提交按钮只需添加:

$('#btnSelector').click(function () {

    $('form').attr('action', "/Your/Action/);
    $('form').submit();

});

根据mkozicki答案我拿出一个有点不同的解决方案。我仍然使用ActionNameSelectorAttribute但我需要处理两个按钮“保存”和“同步”。他们做的几乎是相同的,所以我不想有两个动作。

<强>属性

public class MultipleButtonActionAttribute : ActionNameSelectorAttribute
{        
    private readonly List<string> AcceptedButtonNames;

    public MultipleButtonActionAttribute(params string[] acceptedButtonNames)
    {
        AcceptedButtonNames = acceptedButtonNames.ToList();
    }

    public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
    {            
        foreach (var acceptedButtonName in AcceptedButtonNames)
        {
            var button = controllerContext.Controller.ValueProvider.GetValue(acceptedButtonName);
            if (button == null)
            {
                continue;
            }                
            controllerContext.Controller.ControllerContext.RouteData.Values.Add("ButtonName", acceptedButtonName);
            return true;
        }
        return false;
    }
}

查看

<input type="submit" value="Save" name="Save" />
<input type="submit" value="Save and Sync" name="Sync" />

<强>控制器

 [MultipleButtonAction("Save", "Sync")]
 public ActionResult Sync(OrgSynchronizationEditModel model)
 {
     var btn = this.RouteData.Values["ButtonName"];

我也想指出,如果动作做不同的事情,我可能会跟着mkozicki职务。

我已经创建了一个的 ActionButton 作为方式的HtmlHelper 即可。它会产生正常的输入按钮以位的的JavaScript OnClick事件将表单提交到指定的控制器/动作。

您使用助手一样,

@Html.ActionButton("MyControllerName", "MyActionName", "button text")

这将产生下面的HTML

<input type="button" value="button text" onclick="this.form.action = '/MyWebsiteFolder/MyControllerName/MyActionName'; this.form.submit();">

下面是扩展方法的代码:

<强> VB.Net

<System.Runtime.CompilerServices.Extension()>
Function ActionButton(pHtml As HtmlHelper, pAction As String, pController As String, pRouteValues As Object, pBtnValue As String, pBtnName As String, pBtnID As String) As MvcHtmlString
    Dim urlHelperForActionLink As UrlHelper
    Dim btnTagBuilder As TagBuilder

    Dim actionLink As String
    Dim onClickEventJavascript As String

    urlHelperForActionLink = New UrlHelper(pHtml.ViewContext.RequestContext)
    If pController <> "" Then
        actionLink = urlHelperForActionLink.Action(pAction, pController, pRouteValues)
    Else
        actionLink = urlHelperForActionLink.Action(pAction, pRouteValues)
    End If
    onClickEventJavascript = "this.form.action = '" & actionLink & "'; this.form.submit();"

    btnTagBuilder = New TagBuilder("input")
    btnTagBuilder.MergeAttribute("type", "button")

    btnTagBuilder.MergeAttribute("onClick", onClickEventJavascript)

    If pBtnValue <> "" Then btnTagBuilder.MergeAttribute("value", pBtnValue)
    If pBtnName <> "" Then btnTagBuilder.MergeAttribute("name", pBtnName)
    If pBtnID <> "" Then btnTagBuilder.MergeAttribute("id", pBtnID)

    Return MvcHtmlString.Create(btnTagBuilder.ToString(TagRenderMode.Normal))
End Function

C#(C#代码是刚刚从VB DLL反编译,所以它可以得到一些美化......但时间短: - ))

public static MvcHtmlString ActionButton(this HtmlHelper pHtml, string pAction, string pController, object pRouteValues, string pBtnValue, string pBtnName, string pBtnID)
{
    UrlHelper urlHelperForActionLink = new UrlHelper(pHtml.ViewContext.RequestContext);
    bool flag = Operators.CompareString(pController, "", true) != 0;
    string actionLink;
    if (flag)
    {
        actionLink = urlHelperForActionLink.Action(pAction, pController, System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(pRouteValues));
    }
    else
    {
        actionLink = urlHelperForActionLink.Action(pAction, System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(pRouteValues));
    }
    string onClickEventJavascript = "this.form.action = '" + actionLink + "'; this.form.submit();";
    TagBuilder btnTagBuilder = new TagBuilder("input");
    btnTagBuilder.MergeAttribute("type", "button");
    btnTagBuilder.MergeAttribute("onClick", onClickEventJavascript);
    flag = (Operators.CompareString(pBtnValue, "", true) != 0);
    if (flag)
    {
        btnTagBuilder.MergeAttribute("value", pBtnValue);
    }
    flag = (Operators.CompareString(pBtnName, "", true) != 0);
    if (flag)
    {
        btnTagBuilder.MergeAttribute("name", pBtnName);
    }
    flag = (Operators.CompareString(pBtnID, "", true) != 0);
    if (flag)
    {
        btnTagBuilder.MergeAttribute("id", pBtnID);
    }
    return MvcHtmlString.Create(btnTagBuilder.ToString(TagRenderMode.Normal));
}

这些方法有不同的参数,但对于易用性,你可以创建一些重载带你需要的参数。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top