当前位置:  开发笔记 > 编程语言 > 正文

如何在ASP.NET MVC框架中处理多个提交按钮?

如何解决《如何在ASP.NETMVC框架中处理多个提交按钮?》经验,为你挑选了25个好方法。

是否有一些简单的方法来处理来自同一表单的多个提交按钮?例:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>


<% Html.EndForm(); %>

知道如何在ASP.NET Framework Beta中执行此操作吗?我用Google搜索的所有示例中都有单个按钮.



1> mkozicki..:

以下是基于Maartin Balliauw的帖子和评论的多重提交按钮问题的基于属性的解决方案.

[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;
    }
}

剃刀:

和控制器:

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

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

更新: Razor页面看起来提供了开箱即用的相同功能.对于新的开发,可能更可取.


好方案!比那些得分最高的答案更有用
@Shoe - 刚刚发现了类似的事情.如果您使用此方法,请确保显式指定要返回的视图的名称:`return View("Index",viewModel)`
这种方法的一个问题是,如果你在模型有错误的情况下尝试"返回View(viewmodel)",它将尝试返回一个名为"Send"的视图或者取决于你的参数名称.
只是一个信息,我们需要为MethodInfo添加system.Reflection
我发现这个解决方案是使用其他技术的幸福婚姻.工作完美,不会影响本地化.
Yeaaaaaaaa.适用于MVC 4.5.另一个似乎不起作用.很棒+1

2> Dylan Beatti..:

为提交按钮指定名称,然后在控制器方法中检查提交的值:

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>


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


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


太糟糕了,你依赖于按钮上显示的文字,这对于多语言用户界面来说有点棘手
你应该使用

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



13> 小智..:

如果您的浏览器支持输入按钮的属性格式(IE 10+,不确定其他浏览器),则以下内容应该有效:

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





}



14> Tom Hofman..:

我也遇到过这个"问题",但通过添加name属性找到了一个相当合理的解决方案.我记不起在其他语言中遇到这个问题了.

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

...

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

...

这意味着value可以更改,本地化,国际化以下代码属性,而无需额外的代码检查强类型资源文件或常量.

<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>



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

    }

}



15> Shivprasad K..:

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

    HTML方式

    Jquery的方式

    "ActionNameSelectorAttribute"方式

以下是一个视频,以演示的方式总结了所有这三种方法.

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

HTML方式: -

在HTML方式中,我们需要创建两个表单,并在每个表单中放置"提交"按钮.每个表单的操作都将指向不同/相应的操作.您可以看到下面的代码,第一个表单发布到"Action1",第二个表单将发布到"Action2",具体取决于单击"提交"按钮.

Ajax方式: -

如果你是一个Ajax爱好者,这第二个选项会让你更兴奋.在Ajax方式中,我们可以创建两个不同的函数"Fun1"和"Fun1",请参阅下面的代码.这些函数将使用JQUERY或任何其他框架进行Ajax调用.这些功能中的每一个都与"提交"按钮的"OnClick"事件绑定在一起.这些函数中的每一个都调用各自的动作名称.



使用"ActionNameSelectorAttribute": -

这是一个伟大而干净的选择."ActionNameSelectorAttribute"是一个简单的属性类,我们可以编写决策逻辑,决定可以执行哪个操作.

所以第一件事就是HTML,我们需要在提交按钮上加上适当的名称,以便在服务器上识别它们.

您可以看到我们已将"保存"和"删除"添加到按钮名称中.您还可以注意到我们刚刚将控制器名称"Customer"而不是特定的操作名称放在操作中.我们希望操作名称由"ActionNameSelectorAttribute"决定.


因此,当单击提交按钮时,它首先点击"ActionNameSelector"属性,然后根据触发的提交,它会调用相应的操作.

在此输入图像描述

所以第一步是创建一个继承自"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");
        }
}



16> Saajid Ismai..:

David Findley在他的ASP.Net博客上写了大约3种不同的选项.

阅读同一表格中的文章多个按钮,看看他的解决方案,以及每个按钮的优缺点.恕我直言,他提供了一个非常优雅的解决方案,利用你装饰你的行动的属性.



17> mlibby..:

这是我使用的技术,我还没有在这里看到它.启动此解决方案的链接(由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); %>


<% Html.EndForm(); %>

在控制器中:

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



18> Jay Douglass..:

此脚本允许指定data-form-action属性,该属性将作为所有浏览器中的HTML5格式属性(以不显眼的方式):

$(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);             
});

包含该按钮的表单将发布到data-form-action属性中指定的URL:

   

这需要jQuery 1.7.对于以前的版本,您应该使用live()而不是on().



19> Simon_Weaver..:

这是我为处理多个图像和/或文本按钮而编写的扩展方法.

这是图像按钮的HTML:


或者用于文本提交按钮:



这是您从控制器调用的扩展方法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().Where(x => x.EndsWith(".x")).SingleOrDefault();
        var textButton = formCollection.Keys.OfType().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".



20> 小智..:

我没有足够的代表在正确的地方发表评论,但我整天都花在这上面,所以想分享.

在尝试实现"MultipleButtonAttribute"解决方案时ValueProvider.GetValue(keyValue)会错误地返回null.

事实证明,当它应该是4.0(其他程序集是4.0)时,我引用的是System.Web.MVC 3.0版.我不知道为什么我的项目没有正确升级,我没有其他明显的问题.

所以如果你ActionNameSelectorAttribute不工作......检查一下.



21> Aaron Hudon..:

我很晚才参加派对,但是这里......我的实现借鉴了@mkozicki,但需要较少的硬编码字符串才能出错. 需要框架4.5+.实质上,控制器方法名称应该是路由的关键.

标记.必须键入按钮名称"action:[controllerMethodName]"

(注意使用C#6 nameof API,提供特定于类型的引用,以指向您想要调用的控制器方法的名称.

... form fields ....

控制器:

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

        [SubmitActionToThisMethod]
        public async Task 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;
    }
}



22> 小智..:

这是我找到的最佳方式:

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

这是代码:

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

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

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

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

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

           Func formGetter;
           Func 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);
           }
       }
   }

享受无需代码气味的多提交按钮未来.

谢谢



23> codetuner..:

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

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

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


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

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

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



24> SHAURAJ SING..:
//model
    public class input_element
        {
         public string Btn { get; set; }
        }   

//views--submit btn can be input type also...
    @using (Html.BeginForm())
    {
            
                
            
    }

//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();
        }


此外,您似乎发布只包含代码的答案,没有任何解释.您是否会考虑添加一些叙述来解释代码的工作原理,以及是什么使它成为问题的答案?这对提出问题的人以及其他任何人来说非常有帮助.
当然,它工作正常.但很久以前,这个答案已经由其他人*给出了.他们还包括关于*为什么*它的工作原理的解释.

25> 小智..:
[HttpPost]
public ActionResult ConfirmMobile(string nameValueResend, string nameValueSubmit, RegisterModel model)
    {
        var button = nameValueResend ?? nameValueSubmit;
        if (button == "Resend")
        {

        }
        else
        {

        }
    }


    Razor file Content:
    @using (Html.BeginForm()
    {
        

Confirm Mobile Number

@Html.EditorFor(model => model.VefificationCode) @Html.LabelFor(model => model.VefificationCode, new { }) @Html.ValidationMessageFor(model => model.VefificationCode)
}

推荐阅读
黄晓敏3023
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有