html - كيف يمكنك التعامل مع أزرار إرسال متعددة في ASP.NET MVC Framework؟




asp.net-mvc http-post (20)

هل هناك طريقة سهلة للتعامل مع أزرار إرسال متعددة من نفس النموذج؟ مثال:

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

أي فكرة عن كيفية القيام بذلك في ASP.NET Framework Beta؟ جميع الأمثلة التي استخدمها googled لها أزرار فردية فيها.


أود أن أقترح على الأطراف المهتمة إلقاء نظرة على حل مارتن بالياو . أعتقد أنه أنيق للغاية.

في حالة MultiButton الرابط ، يتم استخدام السمة MultiButton المطبقة على إجراء وحدة التحكم للإشارة إلى الزر الذي يجب أن يرتبط به الإجراء.


إذا كان المستعرض يدعم خاصية إنشاء السمة لأزرار الإدخال (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") />

}

إليك أفضل ما يناسبني:

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

إنها قصيرة وجناح:

تم الرد عليه بواسطة Jeroen Dop

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

وتفعل مثل هذا في الكود

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

حظا طيبا وفقك الله.


شيء ما لا يعجبني في 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;
            }
        }
    }
}

سيجد عامل التصفية اسم الزر في بيانات النموذج وإذا كان اسم الزر يطابق أيًا من أنواع الأزرار المحددة في التعداد ، فسيجد معلمة ButtonType بين معلمات الإجراء:

[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" />

في ما يلي حل يستند إلى السمة النظيفة في الغالب لقضية زر الإرسال المتعدد اعتمادًا كبيرًا على المشاركة والتعليقات من 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;
    }
}

موس الحلاقة:

<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) { ... }

تحديث: صفحات Razor يبدو لتوفير نفس الوظائف خارج منطقة الجزاء. لتطوير جديدة ، قد يكون من الأفضل.


لقد حاولت إنشاء توليفة من كافة الحلول وإنشاء سمة [ButtenHandler] التي تسهّل التعامل مع أزرار متعددة في نموذج.

لقد وصفت ذلك على أزرار نموذج معلمات MultipleProject (قابل للتخصيص) 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);
}

لاحظ كيف يتطابق اسم الزر مع اسم طريقة الإجراء. توضح المقالة أيضًا كيفية الحصول على أزرار تحتوي على قيم وأزرار تحتوي على فهارس.


لقد عثرت على هذه "المشكلة" أيضًا ولكنني وجدت حلًا منطقيًا إلى حد ما عن طريق إضافة سمة 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

    }

}

هذه هي التقنية التي سأستخدمها ولا أراها هنا بعد. الرابط (نشره ساجد إسماعيل) الذي يلهم هذا الحل هو http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multiple-buttons-in-the-same-form .aspx ). انها تتكيف مع إجابة ديلان 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;
         }
    }
}

هناك ثلاث طرق يمكنك من خلالها حل المشكلة المذكورة أعلاه

  1. طريقة HTML
  2. طريقة مسج
  3. طريقة "ActionNameSelectorAttribute"

يوجد أدناه مقطع فيديو يلخص جميع الطرق الثلاثة بطريقة برهانية.

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

طريقة HTML: -

في طريقة HTML ، نحتاج إلى إنشاء نموذجين ووضع زر "إرسال" داخل كل نموذج. وسيشير كل إجراء في النموذج إلى إجراءات مختلفة. يمكنك الاطلاع على الشفرة التالية التي يرسلها النموذج الأول إلى "Action1" وسيتم نشر النموذج الثاني إلى "Action2" بناءً على زر "Submit" الذي يتم النقر عليه.

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

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

طريقة اياكس: -

إذا كنت من محبي أجاكس ، فإن هذا الخيار الثاني سيثير حماسك أكثر. في طريقة Ajax ، يمكننا إنشاء وظيفتين مختلفتين هما "Fun1" و "Fun1" ، راجع الكود التالي. هذه الوظائف ستجعل مكالمات Ajax باستخدام JQUERY أو أي إطار آخر. يتم ربط كل من هذه الوظائف بأحداث "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 هو أننا نحتاج إلى وضع الاسم المناسب لأزرار الإرسال لتحديدها على الخادم.

يمكنك أن ترى أننا وضعنا "حفظ" و "حذف" لأسماء الأزرار. كما يمكنك ملاحظة الإجراء الذي وضعناه للتو باسم وحدة التحكم "العميل" وليس اسم إجراء معين. نتوقع أن يتم تحديد اسم الإجراء من خلال "ActionNameSelectorAttribute".

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

لذلك عندما يتم النقر فوق الزر إرسال ، يقوم أولاً بالضغط على السمة "ActionNameSelector" ومن ثم يعتمد على الإجراء الذي يتم تشغيله ، فإنه يستدعي الإجراء المناسب.

لذا فإن الخطوة الأولى هي إنشاء فئة ترث من فئة "ActionNameSelectorAttribute". في هذه الفئة ، أنشأنا خاصية "Name" بسيطة.

نحتاج أيضًا إلى إلغاء الوظيفة "IsValidName" التي تُرجع true أو flase. هذه الوظيفة هي حيث نكتب منطق ما إذا كان يجب تنفيذ إجراء أم لا. لذلك إذا كانت هذه الدالة ترجع إلى 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" على جميع البيانات التي تم نشرها من النموذج. لذا ، فإنها تبحث أولاً عن قيمة "الاسم" ، وإذا كانت موجودة في طلب HTTP ، فإنها تعرض القيمة true أو تعرض خطأً.

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");
        }
}

يجب أن تكون قادرًا على تسمية الأزرار ومنحها قيمة ؛ ثم عيّن هذا الاسم كحجة لهذا الإجراء. بدلاً من ذلك ، استخدم رابطين عمل منفصلين أو شكلين.


يسمح هذا النص البرمجي بتحديد سمة نموذج - إجراء - عمل تعمل كسمات formion 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);             
});

سيتم نشر النموذج الذي يحتوي على الزر إلى عنوان URL المحدد في سمة نموذج عمل البيانات:

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

هذا يتطلب jQuery 1.7. بالنسبة للإصدارات السابقة ، يجب استخدام live() بدلاً من on() .


يكتب ديفيد Findley عن 3 خيارات مختلفة لديك للقيام بذلك ، على موقع ويب ASP.Net الخاص به.

قراءة المقالة أزرار متعددة في نفس النموذج لرؤية حلوله ، ومزايا وعيوب كل منهما. IMHO أنه يوفر حلا رائعا جدا مما يجعل استخدام السمات التي تزين عملك مع.


يمكنك أن تكتب:

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

ثم في الصفحة تحقق مما إذا كان الاسم == "إرسال" أو اسم == "إلغاء" ...


Based on mkozicki answer I come up with a bit different solution. I still use ActionNameSelectorAttribute But I needed to handle two buttons 'Save' and 'Sync'. They do almost the same so I didn't want to have two actions.

attribute :

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"];

I also want to point out that if actions do different things I would probably follow mkozicki post.


For each submit button just add:

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

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

});

I've created an ActionButton method for the HtmlHelper . It will generate normal input button with a bit of javascript in the OnClick event that will submit the form to the specified Controller/Action.

You use the helper like that

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

this will generate the following HTML

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

Here is the extension method code:

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# (the C# code is just decompiled from the VB DLL, so it can get some beautification... but time is so short :-))

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

These methods have various parameters, but for the ease of use you can create some overload that take just the parameters you need.


Modified version of HttpParamActionAttribute method but with a bug fix for not causing an error on expired/invalid session postbacks. To see if this is a problem with your current site, open the your form in a window and just before you go to click Save or Publish , open a duplicate window, and logout. Now go back to your first window and try to submit your form using either button. For me I got an error so this change solves that problem for me. I omit a bunch of stuff for the sake of brevity but you should get the idea. The key parts are the inclusion of ActionName on the attribute and making sure the name passed in is the name of the View that shows the form

Attribute Class

[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" />
}

When using ajax forms, we can use ActionLinks with POST HttpMethod and serialize the form in the AjaxOptions.OnBegin event.

Let's say you have two actions, InsertAction and UpdateAction:

<form>
    @Html.Hidden("SomeField", "SomeValue")

    @Ajax.ActionLink(
        "Insert",
        "InsertAction",
        null,
        new AjaxOptions { 
            OnBegin = "OnBegin", 
            UpdateTargetId = "yourDiv", 
            HttpMethod = "POST" })
    @Ajax.ActionLink(
        "Update",
        "UpdateAction",
        null,
        new AjaxOptions { 
            OnBegin = "OnBegin", 
            UpdateTargetId = "yourDiv", 
            HttpMethod = "POST" })
</form>

Javascript

function OnBegin(xhr, settings) {
    settings.data = $("form").serialize();
}

this is the best way that i have found:

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

Enjoy a code-smell-less multi submit button future.

شكرا





form-submit