Làm thế nào để bạn xử lý nhiều nút gửi trong ASP.NET MVC Framework?


733

Có một số cách dễ dàng để xử lý nhiều nút gửi từ cùng một hình thức? Ví dụ:

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

Bất kỳ ý tưởng làm thế nào để làm điều này trong ASP.NET Framework Beta? Tất cả các ví dụ tôi đã googled để có các nút duy nhất trong đó.


6
Đáng nói là bắt đầu từ ASP.NET Core, có nhiều giải pháp dễ dàng hơn nhiều so với những giải pháp được liệt kê ở đây.
Steven Jeuris

Câu trả lời:


629

Đây là một giải pháp chủ yếu dựa trên thuộc tính sạch cho vấn đề nhiều nút gửi dựa trên bài đăng và nhận xét từ Maarten 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;
    }
}

dao cạo:

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

và bộ điều khiển:

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

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

Cập nhật: Các trang dao cạo có vẻ cung cấp chức năng tương tự ra khỏi hộp. Đối với sự phát triển mới, nó có thể được ưa thích.


3
Tôi tìm thấy giải pháp này là cuộc hôn nhân hạnh phúc của các kỹ thuật khác được sử dụng. Hoạt động hoàn hảo và không ảnh hưởng đến nội địa hóa.
trevorc

17
Giải pháp tuyệt vời !! Rất nhiều hữu ích hơn những câu trả lời được ghi điểm hàng đầu
Sasha

11
Một vấn đề với cách tiếp cận này là nếu bạn cố gắng return View(viewmodel)trong trường hợp mô hình của bạn có lỗi, nó sẽ cố trả về một khung nhìn được gọi Sendhoặc tùy thuộc vào tên đối số của bạn là gì.
Giày

15
@Shoe - vừa tìm thấy một điều tương tự. Đảm bảo bạn chỉ định rõ ràng tên của chế độ xem sẽ trả về nếu bạn đang sử dụng phương thức này:return View("Index", viewModel)
ajbeaven

4
chỉ cần một thông tin, chúng ta cần thêm system.Reflection cho MethodInfo
Vignesh Subramanian

469

Đặt tên cho nút gửi của bạn và sau đó kiểm tra giá trị đã gửi trong phương thức điều khiển của bạn:

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

đăng lên

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

}

BIÊN TẬP:

Để mở rộng cách tiếp cận này để làm việc với các trang web được bản địa hóa, hãy cách ly thư của bạn ở một nơi khác (ví dụ: biên dịch tệp tài nguyên thành lớp tài nguyên được gõ mạnh)

Sau đó sửa đổi mã để nó hoạt động như sau:

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

và bộ điều khiển của bạn sẽ trông như thế này:

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

28
quá tệ, bạn phụ thuộc vào văn bản được hiển thị trên nút, thật khó khăn với giao diện người dùng đa ngôn ngữ
Omu

3
Switch / case chỉ hoạt động với các hằng số, vì vậy phiên bản được bản địa hóa không thể sử dụng switch / case. Bạn cần chuyển sang nếu khác hoặc một số phương thức điều phối khác.
mlibby

10
bạn nên sử dụng <button type = "submit" thay vì <kiểu đầu vào, bởi vì giá trị của loại nút <không phải là văn bản;). Sau đó, bạn có thể có một cái gì đó như thế này: <button name = "mySubmitButton" type = "submit" value = "keyValue"> YourButtonText </ button>
J4N

4
Làm thế nào điều này sẽ làm việc với việc chuyển mô hình cho hành động thay vì chỉ giá trị gửi?
bizzehdee

2
Cẩn thận không đặt tên cho các nút của bạn là "hành động" nếu bạn đang sử dụng jQuery. Nó gây ra xung đột trong thư viện phá vỡ URL hành động.
HotN

121

Bạn có thể kiểm tra tên trong hành động như đã được đề cập, nhưng bạn có thể xem xét liệu đây có phải là thiết kế tốt hay không. Đó là một ý tưởng tốt để xem xét trách nhiệm của hành động và không kết hợp thiết kế này quá nhiều với các khía cạnh UI như tên nút. Vì vậy, hãy xem xét sử dụng 2 hình thức và 2 hành động:

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

Ngoài ra, trong trường hợp "Hủy", bạn thường không xử lý biểu mẫu và sẽ chuyển đến một URL mới. Trong trường hợp này, bạn hoàn toàn không cần gửi biểu mẫu và chỉ cần một liên kết:

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

53
Điều này là ổn khi bạn không cần dữ liệu biểu mẫu giống nhau cho mỗi nút gửi. Nếu bạn cần tất cả dữ liệu ở dạng phổ biến hơn Dylan Beattie là cách tốt nhất. Có cách nào thanh lịch hơn để làm điều này?
zidane

3
Về trình bày trực quan, làm thế nào trong trường hợp này có nút "Gửi" bên cạnh nút "Hủy"?
Kris-I

1
Dylan: Vâng, đối với một nút hủy, bạn hoàn toàn không cần gửi dữ liệu và việc kết hợp bộ điều khiển với các thành phần UI là một thực tế xấu. Tuy nhiên, nếu bạn có thể tạo một "lệnh" chung chung hoặc ít hơn thì tôi nghĩ nó ổn, nhưng tôi sẽ không buộc nó vào "submitButton" vì đó là tên của một thành phần UI.
Trevor de Koekkoek

1
@Kris: bạn có thể định vị các nút của mình bằng CSS và chúng vẫn có thể nằm trong 2 phần biểu mẫu khác nhau.
Trevor de Koekkoek

8
nghiêm túc? Điều đó không có mùi với bất cứ ai ngoài tôi?!

99

Eilon gợi ý bạn có thể làm như thế này:

Nếu bạn có nhiều nút, bạn có thể phân biệt giữa chúng bằng cách đặt tên cho mỗi nút:

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

Trong phương thức hành động của bộ điều khiển, bạn có thể thêm các tham số được đặt tên theo tên thẻ đầu vào HTML:

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

Nếu bất kỳ giá trị nào được đăng lên một trong các tham số đó, điều đó có nghĩa là nút đó là nút được nhấp. Trình duyệt web sẽ chỉ đăng một giá trị cho một nút được nhấp. Tất cả các giá trị khác sẽ là null.

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

Tôi thích phương pháp này vì nó không dựa vào thuộc tính giá trị của các nút gửi có khả năng thay đổi nhiều hơn tên được gán và không yêu cầu bật javascript

Xem: http://forums.asp.net/p/1369617/2865166.aspx#2865166


2
Nếu bất cứ ai gặp phải câu hỏi cũ này, đây là câu trả lời rõ ràng nhất nếu bạn không sử dụng các yếu tố HTML5 <button>. Nếu bạn không quan tâm đến HTML5 thì hãy sử dụng <button> với thuộc tính value.
Kugel

Làm thế nào bạn sẽ làm điều đó nếu tạo một cuộc gọi ajax trên mẫu này. Có vẻ như form.serialize () không nhận tên nút gửi ..
mko

@Kugel đã đúng, đây vẫn là câu trả lời rõ ràng nhất. Cảm ơn
Arif YILMAZ

45

Chỉ cần viết một bài về điều đó: Nhiều nút gửi với ASP.NET MVC :

Về cơ bản, thay vì sử dụng ActionMethodSelectorAttribute, tôi đang sử dụng ActionNameSelectorAttribute, cho phép tôi giả vờ tên hành động là bất cứ điều gì tôi muốn. May mắn thay, ActionNameSelectorAttributekhông chỉ khiến tôi chỉ định tên hành động, thay vào đó tôi có thể chọn xem hành động hiện tại có khớp với yêu cầu hay không.

Vì vậy, có lớp học của tôi (btw tôi không quá thích tên này):

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

Để sử dụng chỉ cần xác định một hình thức như thế này:

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

và bộ điều khiển với hai phương thức

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

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

Như bạn thấy, thuộc tính không yêu cầu bạn chỉ định bất cứ điều gì cả. Ngoài ra, tên của các nút được dịch trực tiếp sang tên phương thức. Ngoài ra (tôi chưa thử điều đó) chúng cũng hoạt động như các hành động bình thường, vì vậy bạn có thể đăng trực tiếp lên bất kỳ hành động nào trong số chúng.


1
Xinh đẹp! Tôi nghĩ rằng đây là giải pháp thanh lịch nhất. Nó loại bỏ giá trị của submitthẻ khỏi xem xét, điều này rất lý tưởng vì đây là thuộc tính UI thuần nên không có liên quan đến luồng điều khiển. Thay vào đó, namethuộc tính duy nhất của mỗi submitthẻ dịch trực tiếp thành một phương thức hành động riêng biệt trên bộ điều khiển của bạn.
Kirk Woll

+1 Đối với tôi, đó là giải pháp tốt nhất cho vấn đề này. Kể từ khi tôi triển khai nó, tôi nhận thấy rằng có rất nhiều lưu lượng truy cập thông qua httpParamActionAttribut nhưng so với tất cả những thứ khác mà Asp.Net MVC phải làm trong khi xử lý yêu cầu, điều đó hoàn toàn chấp nhận được. Để chỉ hack tôi phải làm là đặt một 'Hành động' trống có tên trong bộ điều khiển của tôi để ngăn Resharper cảnh báo tôi rằng hành động 'Hành động' không tồn tại. Cảm ơn rât nhiều!
Samuel

Tôi đã xem xét tất cả các giải pháp và cũng đồng ý rằng đây là một giải pháp đơn giản, thanh lịch. Great bc không có câu lệnh có điều kiện và mạnh mẽ nơi bạn có thể xác định một hành động điều khiển mới khi bạn có một nút mới. Được gọi là lớp của tôi MultiButtonActionHandler FYI ;-)
ejhost

36

nó ngắn và bộ:

Nó đã được trả lời bởi Jeroen Dop

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

và làm như thế này trong mã phía sau

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

Chúc may mắn.


Tuyệt vời. chính xác những gì tôi đã từng làm trong các biểu mẫu web. Chúc mừng bạn thân
djack109

Đơn giản hơn nhiều so với câu trả lời hàng đầu! Cảm ơn!
pabben

35

Tôi muốn đề nghị các bên quan tâm xem xét giải pháp của Maarten Balliauw . Tôi nghĩ rằng nó rất thanh lịch.

Trong trường hợp liên kết biến mất, nó sử dụng MultiButtonthuộc tính được áp dụng cho hành động của bộ điều khiển để cho biết nút nào nhấp vào hành động đó sẽ liên quan đến.


Đây là giải pháp chúng tôi đang sử dụng và nó rất gọn gàng. Có phải là MVC 2 không?
Simon Giữ

Thật là đẹp Tôi chưa từng thấy điều này trước đây! Mặc dù tôi đồng ý rằng bạn có thể muốn thiết kế lại bất kỳ giải pháp nào đang sử dụng nhiều lần gửi để chỉ sử dụng một nút, tôi đang ở một nơi mà tôi bị mắc kẹt và phải làm điều này. Câu trả lời này lẽ ra phải thắng!
Rikon

Đây là một giải pháp tuyệt vời. Rất sạch sẽ
Arnej65

Đã thử cách tiếp cận này và không thể làm cho nó hoạt động trong MVC3. Một biến thể của công cụ bầu chọn số 1 làm việc cho tôi.
Scott Lawrence

Ngắn và ngọt ngào .. nhưng không dành cho mvc 3+
Piotr Kula

21

Bạn sẽ có thể đặt tên cho các nút và cung cấp cho chúng một giá trị; sau đó ánh xạ tên này như là một đối số cho hành động. Ngoài ra, sử dụng 2 liên kết hành động riêng biệt hoặc 2 hình thức.


Cho đến nay, giải pháp sạch nhất và dễ nhất mà tôi từng thấy.
Jason Evans

13

Bạn có thể viết:

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

Và sau đó trong trang kiểm tra xem tên == "Gửi" hoặc tên == "Hủy" ...


1
Mặc dù điều này đang hoạt động, nhưng tôi nghĩ rằng thực tế sai khi có hai yếu tố có cùng tên.
Péter

1
Nó không cần thiết sai. Nó phụ thuộc vào cách bạn đang sử dụng các đầu vào. Bạn có thể có nhiều thành phần có cùng tên và mong muốn nhận được nhiều dữ liệu (đây là cách hoạt động của các hộp phóng xạ và hộp kiểm). Nhưng vâng, nếu bạn đang sử dụng phương pháp này là vì bạn đang làm "sai" ... Đó là lý do tại sao tôi đặt "Bạn có thể" chứ không phải "Bạn nên": P
Ironicnet

12

Một điều tôi không thích về ActionSelectName là IsValidName được gọi cho mọi phương thức hành động trong bộ điều khiển; Tôi không biết tại sao nó hoạt động theo cách này. Tôi thích một giải pháp trong đó mỗi nút có một tên khác nhau dựa trên những gì nó làm, nhưng tôi không thích thực tế là bạn phải có nhiều tham số trong phương thức hành động như các nút trong biểu mẫu. Tôi đã tạo một enum cho tất cả các loại nút:

public enum ButtonType
{
    Submit,
    Cancel,
    Delete
}

Thay vì ActionSelectName, tôi sử dụng 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;
            }
        }
    }
}

Bộ lọc sẽ tìm thấy tên nút trong dữ liệu biểu mẫu và nếu tên nút khớp với bất kỳ loại nút nào được xác định trong enum, nó sẽ tìm thấy tham số NútType trong số các tham số hành động:

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

và sau đó trong chế độ xem, tôi có thể sử dụng:

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

11

Đây là những gì làm việc tốt nhất cho tôi:

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

Tôi nhận được giá trị null cho onDelete và onSave trong phương thức điều khiển. Bạn có biết tại sao?
Diganta Kumar

Một trong hai sẽ không có giá trị nếu bạn nhấp vào nút theo. Nút nào bạn nhấp vào nhận null?
Serge

11

Tôi cũng đã gặp phải "vấn đề" này nhưng đã tìm thấy một giải pháp khá logic bằng cách thêm namethuộc tính. Tôi không thể nhớ lại có vấn đề này trong các ngôn ngữ khác.

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

  • ...
  • Nếu một biểu mẫu chứa nhiều nút gửi, chỉ có nút gửi được kích hoạt là thành công.
  • ...

Có nghĩa là các valuethuộc tính mã sau đây có thể được thay đổi, bản địa hóa, quốc tế hóa mà không cần thêm mã kiểm tra các tệp hoặc hằng tài nguyên được gõ mạnh.

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

Vào cuối nhận, bạn chỉ cần kiểm tra xem có bất kỳ loại gửi nào bạn biết không 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

    }

}

Đây là giải pháp chúng tôi chọn sử dụng cho một ứng dụng web đơn giản, nơi chúng tôi muốn chức năng ASP.NET WebForms nhưng trong MVC.
BrandonG

10

Nếu bạn không có hạn chế về việc sử dụng HTML 5, bạn có thể sử dụng <button>thẻ với formactionThuộc tính:

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

Tham khảo: http://www.w3schools.com/html5/att_button_formaction.asp


9

Nếu trình duyệt của bạn hỗ trợ định dạng thuộc tính cho các nút đầu vào (IE 10+, không chắc chắn về các trình duyệt khác) thì các thao tác sau sẽ hoạt động:

@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") />

}

Hãy xem câu trả lời của tôi dưới đây, nó không dựa vào thông số kỹ thuật dự thảo. Câu trả lời của bạn không cho phép khả năng có các url hành động khác nhau, mà tôi thì không.
Tom Hofman

9

Có ba cách để bạn giải quyết vấn đề trên

  1. Cách HTML
  2. Jquery cách
  3. Cách ActionNameSelectorAttribution Cách

Dưới đây là một video tóm tắt tất cả ba cách tiếp cận một cách trình diễn.

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

Cách HTML: -

Theo cách HTML, chúng ta cần tạo hai biểu mẫu và đặt nút Gửi Gửi bên trong mỗi biểu mẫu. Và mọi hành động của hình thức sẽ chỉ ra các hành động khác nhau / tương ứng. Bạn có thể thấy đoạn mã dưới đây, hình thức đầu tiên được đăng lên trên Action Action1 và hình thức thứ hai sẽ được đăng lên trên Action Action2, tùy thuộc vào nút nào mà Gửi Gửi.

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

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

Cách Ajax: -

Trong trường hợp bạn là người yêu thích Ajax, tùy chọn thứ hai này sẽ kích thích bạn nhiều hơn. Theo cách Ajax, chúng ta có thể tạo hai chức năng khác nhau, Fun Fun1, và Fun Fun1, xem đoạn mã dưới đây. Các hàm này sẽ thực hiện các cuộc gọi Ajax bằng cách sử dụng JQUERY hoặc bất kỳ khung công tác nào khác. Mỗi chức năng này được liên kết với các sự kiện On On của nút của nút Gửi Gửi. Mỗi chức năng này thực hiện cuộc gọi đến các tên hành động tương ứng.

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

Sử dụng hành động của ActionNameSelectorAttribution của: -

Đây là một lựa chọn tuyệt vời và sạch sẽ. Nhóm ActionNameSelectorAttribution 'là một lớp thuộc tính đơn giản nơi chúng ta có thể viết logic ra quyết định sẽ quyết định hành động nào có thể được thực thi.

Vì vậy, điều đầu tiên là trong HTML, chúng ta cần đặt tên thích hợp cho các nút gửi để xác định chúng trên máy chủ.

Bạn có thể thấy chúng tôi đã đặt các trò chơi Lưu Lưu và Xóa Xóa vào các tên nút. Ngoài ra, bạn có thể nhận thấy trong hành động chúng tôi vừa đặt tên bộ điều khiển là khách hàng của khách hàng và không phải là một tên hành động cụ thể. Chúng tôi hy vọng tên hành động sẽ được quyết định bởi nhóm ActionNameSelectorAttribution '.

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

Vì vậy, khi nhấp vào nút gửi, đầu tiên, nó chạm vào thuộc tính của Action ActionSSectorector và sau đó tùy thuộc vào lần gửi nào được kích hoạt, nó sẽ gọi hành động thích hợp.

nhập mô tả hình ảnh ở đây

Vì vậy, bước đầu tiên là tạo một lớp kế thừa từ lớp Action ActionNameSelectorAttribution. Trong lớp này, chúng tôi đã tạo ra một thuộc tính đơn giản Tên Tên.

Chúng ta cũng cần ghi đè hàm IsValidName. Trả về true hoặc flase. Hàm này là nơi chúng ta viết logic cho dù một hành động phải được thực hiện hay không. Vì vậy, nếu hàm này trả về true thì hành động được thực thi nếu không thì không.

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;

        }
    }

Trung tâm chính của chức năng trên nằm trong đoạn mã dưới đây. Bộ sưu tập của Value Valuevvider có tất cả dữ liệu đã được đăng từ biểu mẫu. Vì vậy, trước tiên, nó tìm kiếm giá trị của Tên Tên và nếu tìm thấy trong yêu cầu HTTP, nó sẽ trả về giá trị true hoặc nếu không thì nó trả về false.

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

Lớp thuộc tính này sau đó có thể được trang trí trên hành động tương ứng và giá trị Tên Tên tương ứng có thể được cung cấp. Vì vậy, nếu trình gửi đang nhấn hành động này và nếu tên trùng khớp với tên nút gửi HTML thì nó sẽ thực thi hành động thêm nếu không thì không.

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

7

David Findley viết về 3 tùy chọn khác nhau mà bạn có để thực hiện điều này, trên weblog ASP.Net của mình.

Đọc bài viết nhiều nút trong cùng một hình thức để xem giải pháp của anh ấy, và những ưu điểm và nhược điểm của mỗi nút . IMHO anh ấy cung cấp một giải pháp rất thanh lịch, sử dụng các thuộc tính mà bạn trang trí cho hành động của mình.


7

Đây là kỹ thuật tôi sử dụng và tôi chưa thấy nó ở đây. Liên kết (được đăng bởi Saajid Ismail) truyền cảm hứng cho giải pháp này là http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multipl-buttons-in-the-same-form .aspx ). Nó điều chỉnh câu trả lời của Dylan Beattie để thực hiện nội địa hóa mà không gặp vấn đề gì.

Theo quan điểm:

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

Trong Bộ điều khiển:

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

Có vẻ như giải pháp Ironicnet cung cấp.
Kris van der Mast

Chắc chắn tương tự, nhưng điều này cho thấy cả nội địa hóa và mã điều khiển, đây là điều mà tôi không thấy được thực hiện theo cách này trong luồng này. Tôi tìm thấy chủ đề này trong khi tìm kiếm cách làm điều này và muốn ghi lại những gì tôi đã đưa ra cho bất kỳ ai khác có thể ở trong cùng một chiếc thuyền.
mlibby

1
Trên thực tế, nó không giống như Ironicnet ngoài điều đó. Ông sử dụng <input>các yếu tố. Tôi sử dụng <button>, được yêu cầu để thực hiện nội địa hóa mà không có thuộc tính giá trị biến.
mlibby

7

Tập lệnh này cho phép chỉ định một thuộc tính hành động dạng dữ liệu sẽ hoạt động như thuộc tính định dạng HTML5 trong tất cả các trình duyệt (theo cách không phô trương):

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

Biểu mẫu chứa nút sẽ được đăng lên URL được chỉ định trong thuộc tính hành động dữ liệu biểu mẫu:

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

Điều này đòi hỏi jQuery 1.7. Đối với các phiên bản trước, bạn nên sử dụng live()thay vì on().


6

Đây là một phương pháp mở rộng tôi đã viết để xử lý nhiều nút hình ảnh và / hoặc văn bản.

Đây là HTML cho một nút hình ảnh:

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

hoặc cho một nút gửi văn bản:

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

Đây là phương thức mở rộng mà bạn gọi từ bộ điều khiển form.GetSubmitButtonName(). Đối với các nút hình ảnh, nó tìm kiếm một tham số biểu mẫu với .x(cho biết nút hình ảnh đã được nhấp) và trích xuất tên. Đối với các inputnút thông thường, nó tìm kiếm một tên bắt đầu bằng Submit_và trích xuất lệnh từ sau đó. Bởi vì tôi trừu tượng hóa logic xác định 'lệnh', bạn có thể chuyển đổi giữa các nút hình ảnh + văn bản trên máy khách mà không thay đổi mã phía máy chủ.

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

Lưu ý: Đối với các nút văn bản, bạn phải đặt tiền tố tên Submit_. Tôi thích cách này vì nó có nghĩa là bạn có thể thay đổi giá trị văn bản (hiển thị) mà không phải thay đổi mã. Không giống như SELECTcác yếu tố, một INPUTnút chỉ có một 'giá trị' và không có thuộc tính 'văn bản' riêng biệt. Các nút của tôi nói những điều khác nhau trong các bối cảnh khác nhau - nhưng ánh xạ tới cùng một 'lệnh'. Tôi thích trích xuất tên theo cách này hơn là phải viết mã == "Add to cart".


Tôi thích kiểm tra tên thay thế vì bạn không thể luôn kiểm tra giá trị, vd. bạn có một danh sách các mục và mỗi mục có nút "Xóa".
Tối đa

6

Tôi không có đủ đại diện để bình luận ở vị trí chính xác, nhưng tôi đã dành cả ngày cho việc này vì vậy muốn chia sẻ.

Trong khi cố gắng thực hiện giải pháp "NhiềuButtonAttribution" ValueProvider.GetValue(keyValue)sẽ quay lại không chính xác null.

Hóa ra tôi đã tham khảo System.Web.MVC phiên bản 3.0 khi nó phải là 4.0 (các hội đồng khác là 4.0). Tôi không biết tại sao dự án của tôi không nâng cấp chính xác và tôi không có vấn đề rõ ràng nào khác.

Vì vậy, nếu bạn ActionNameSelectorAttributekhông làm việc ... hãy kiểm tra xem.


6

Tôi đến bữa tiệc khá muộn, nhưng đến đây ... Việc triển khai của tôi mượn từ @mkozicki nhưng đòi hỏi ít chuỗi mã hóa cứng hơn để nhận sai. Yêu cầu khung 4.5+ . Về cơ bản, tên phương thức của bộ điều khiển phải là chìa khóa để định tuyến.

Đánh dấu . Tên nút phải được khóa bằng"action:[controllerMethodName]"

(thông báo việc sử dụng C # 6 nameof API, cung cấp tài liệu tham khảo loại cụ thể để tên của phương pháp điều khiển bạn muốn gọi.

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

Điều khiển :

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

Thuộc tính ma thuật . Chú ý việc sử dụng CallerMemberNamelòng tốt.

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

Mặc dù đây là một cách tiếp cận hay, nhưng bạn sẽ không thể sử dụng chất kết dính mô hình mvc tích hợp vì nó sử dụng thuộc tính "name" của nút.
ooXei1sh

Mục đích của giải pháp này là một công việc xoay quanh định tuyến bài MVC. Hãy mô tả một sự cải tiến.
Aaron Hudon

6
[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>

    }

Đây là một liên kết hữu ích khác giải thích các cách khác nhau của bài mẫu.
Himalaya Garg

5

Tôi đã cố gắng tổng hợp tất cả các giải pháp và tạo thuộc tính [ButtenHandler] để giúp dễ dàng xử lý nhiều nút trên một biểu mẫu.

Tôi đã mô tả nó trên CodeProject Nhiều nút biểu mẫu (có thể bản địa hóa) trong ASP.NET MVC .

Để xử lý trường hợp đơn giản của nút này:

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

Bạn sẽ có một cái gì đó giống như phương pháp hành động sau:

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

Lưu ý cách tên của nút khớp với tên của phương thức hành động. Bài viết cũng mô tả làm thế nào để có các nút có giá trị và nút có chỉ mục.


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

Bạn có thể không nhận ra nó, nhưng câu trả lời tương tự này đã được đăng khá nhiều lần cho câu hỏi này rồi.
Andrew Barber

2
Ngoài ra, bạn dường như đăng câu trả lời chỉ chứa mã, không có lời giải thích. Bạn có xem xét việc thêm một số tường thuật để giải thích tại sao mã hoạt động không, và điều gì làm cho nó trở thành một câu trả lời cho câu hỏi? Điều này sẽ rất hữu ích cho người đặt câu hỏi và bất kỳ ai khác đi cùng.
Andrew Barber

2
Chắc chắn, nó hoạt động tốt. Nhưng câu trả lời đó đã được đưa ra bởi những người khác , từ lâu. Và họ bao gồm giải thích về lý do tại sao nó hoạt động, quá.
Andrew Barber

5

đây là cách tốt nhất mà tôi đã tìm thấy:

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

Đây là mã:

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

Tận hưởng một nút gửi mã ít mùi trong tương lai.

cảm ơn bạn


Liên kết hiện đang bị hỏng, đây là phiên bản lưu trữ gần nhất mà tôi có thể tìm thấy: web.archive.org/web/20110706230408/http://bloss.sonatribe.com/ Lỗi
Ian Kemp

Xin chào Ian - cảm ơn vì đã đào nó ra - Tôi đã đăng lại nó ở đây: iwayneo.blogspot.co.uk/2013/10/ mẹo

4

Phiên bản sửa đổi của HttpParamActionAttributephương thức nhưng với một sửa lỗi không gây ra lỗi trên các postback phiên hết hạn / không hợp lệ. Để xem đây có phải là sự cố với trang web hiện tại của bạn không, hãy mở biểu mẫu của bạn trong một cửa sổ và ngay trước khi bạn nhấp vào Savehoặc Publish, mở một cửa sổ trùng lặp và đăng xuất. Bây giờ hãy quay lại cửa sổ đầu tiên của bạn và thử gửi biểu mẫu của bạn bằng một trong hai nút. Đối với tôi, tôi đã gặp một lỗi nên sự thay đổi này giải quyết vấn đề đó cho tôi. Tôi bỏ qua một loạt các công cụ vì lợi ích của sự ngắn gọn nhưng bạn nên có ý tưởng. Các phần chính là bao gồm ActionNamethuộc tính và đảm bảo tên được truyền vào là tên của Chế độ xem hiển thị biểu mẫu

Lớp thuộc tính

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

Bộ điều khiển

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

Lượt xem

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

3

Cách tiếp cận JQuery của tôi bằng cách sử dụng một phương thức mở rộng:

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

Bạn có thể sử dụng nó như thế này:

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

Và nó biểu hiện như thế này:

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

3

Đối với mỗi nút gửi chỉ cần thêm:

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

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

});

3

Dựa trên câu trả lời của mkozicki, tôi đưa ra một giải pháp khác. Tôi vẫn sử dụng ActionNameSelectorAttributeNhưng tôi cần xử lý hai nút 'Lưu' và 'Đồng bộ hóa'. Họ làm gần như nhau nên tôi không muốn có hai hành động.

thuộc tính :

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

lượt xem

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

bộ điều khiển

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

Tôi cũng muốn chỉ ra rằng nếu các hành động làm những việc khác nhau thì có lẽ tôi sẽ theo dõi bài đăng của mkozicki.


1

Tôi đã tạo một phương thức ActionButton cho HtmlHelper . Nó sẽ tạo nút đầu vào bình thường với một chút javascript trong sự kiện OnClick sẽ gửi biểu mẫu đến Bộ điều khiển / Hành động được chỉ định.

Bạn sử dụng người trợ giúp như thế

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

điều này sẽ tạo ra HTML sau

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

Đây là mã phương thức mở rộng:

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 # (mã C # chỉ được dịch ngược từ VB DLL, vì vậy nó có thể được làm đẹp ... nhưng thời gian rất ngắn :-))

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

Các phương thức này có các tham số khác nhau, nhưng để dễ sử dụng, bạn có thể tạo một số quá tải chỉ lấy các tham số bạn cần.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.