ASP.NET MVC ActionLink และวิธีการโพสต์


98

ใครช่วยบอกฉันหน่อยว่าฉันจะส่งค่าไปยัง Controller โดยใช้ ActionLink และ POST ได้อย่างไร?
ฉันไม่ต้องการใช้ปุ่มต่างๆ
ฉันเดาว่ามันมีบางอย่างกับ jquery


1
ฉันได้เขียนวิธีการที่คล้ายกับ Html.ActionLink เพียง แต่สร้างแบบฟอร์ม POST ด้วยปุ่มส่ง ฉันจะดูว่าฉันสามารถให้ตัวเลือกในการแทนที่ปุ่มด้วยลิงก์ที่ส่งแบบฟอร์มได้หรือไม่ ดูได้ที่นี่: stackoverflow.com/questions/3449807/…
nikib3ro

คำตอบ:


58

คุณไม่สามารถใช้ an ActionLinkเพราะมันแสดงผลเพียงแค่<a>แท็กจุดยึด
คุณสามารถใช้โพสต์ jQuery AJAX
หรือเพียงแค่เรียกวิธีการส่งแบบฟอร์มโดยมีหรือไม่มี jQuery (ซึ่งจะไม่ใช่ AJAX) บางทีในonclickกรณีที่การควบคุมใด ๆ ก็ตามที่คุณต้องการ


71

หากคุณใช้ ASP MVC3 คุณสามารถใช้ Ajax.ActionLink () ซึ่งช่วยให้คุณระบุวิธี HTTP ซึ่งคุณสามารถตั้งค่าเป็น "POST" ได้


46
โปรดทราบว่าในการทำงานนี้คุณจะต้องรวมไฟล์ ajax javascript เช่น " jquery.unobtrusive-ajax.min.js" มิฉะนั้นจะยังคงทำ GET แทน POST เมื่อคลิก ไวยากรณ์ที่จะสร้างลิงค์จะเป็นดังนี้:@Ajax.ActionLink("Delete", "Delete", new { id = item.Id }, new AjaxOptions {HttpMethod = "POST"})
CodingWithSpike

1
ajax ที่ไม่สร้างความรำคาญทำงานได้ดี แต่ฉันต้องใช้ลิงก์การกระทำที่แตกต่างกันเล็กน้อยโดยส่งพจนานุกรมเป็นพารามิเตอร์แทนวัตถุ AjaxOptions นี้: stackoverflow.com/a/10657891/429521นอกจากนี้ฉันต้องส่งแอตทริบิวต์ ajax ด้วยมือเพื่อให้ JS "data-ajax"="true, "data-ajax-url"=<your link> and "data-ajax-method"="Post"สามารถจับและแทนที่กิจกรรมการคลิกที่พวกเขา Btw ฉันใช้ ASP.NET MVC 3
Felipe Sabino

1
@CokoBWare อันนี้stackoverflow.com/questions/10507737/… ? จริงๆ? ดูเหมือนจะไม่พังสำหรับฉัน ...
Felipe Sabino

21

คุณสามารถใช้ jQuery เพื่อทำการโพสต์สำหรับปุ่มทั้งหมดของคุณ เพียงตั้งชื่อ CssClass เดียวกัน

ใช้ "return false;" ในตอนท้ายของเหตุการณ์ onclick javascript ของคุณหากคุณต้องการทำ RedirectToAction ฝั่งเซิร์ฟเวอร์หลังจากโพสต์มิฉะนั้นเพียงแค่ส่งคืนมุมมอง

รหัสมีดโกน

@using (Html.BeginForm())
{
    @Html.HiddenFor(model => model.ID) 
    @Html.ActionLink("Save", "SaveAction", "MainController", null, new { @class = "saveButton", onclick = "return false;" })
}

รหัส jQuery

$(document).ready(function () {
        $('.saveButton').click(function () {
            $(this).closest('form')[0].submit();
        });
    });

ค#

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SaveAction(SaveViewModel model)
{
    // Save code here...

    return RedirectToAction("Index");
    //return View(model);
}

@ goodies4uall แน่นอนและคำตอบนี้ก็แค่นั้น :) คลาส CSS มีชื่อว่า "saveButton" (อาจเป็นชื่อที่ทำให้เข้าใจผิด) แต่มีการใช้แท็ก anchor เพื่อเริ่มต้นการกระทำ
Savantes

18

@Aidos มีคำตอบที่ถูกต้องเพียงแค่ต้องการทำให้ชัดเจนเนื่องจากมันถูกซ่อนอยู่ในความคิดเห็นในโพสต์ของเขาที่สร้างโดย @CodingWithSpike

@Ajax.ActionLink("Delete", "Delete", new { id = item.ApkModelId }, new AjaxOptions { HttpMethod = "POST" })

7

นี่คือคำตอบที่รวมอยู่ในโครงการ ASP.NET MVC 5 เริ่มต้นฉันเชื่อว่าจะบรรลุเป้าหมายการจัดแต่งทรงผมได้ดีใน UI ส่งแบบฟอร์มโดยใช้จาวาสคริปต์ที่แท้จริงไปยังแบบฟอร์มที่มีบางส่วน

@using (Html.BeginForm("Logout", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
{
   <a href="javascript:document.getElementById('logoutForm').submit()">
      <span>Sign out</span>
   </a>
}

กรณีการใช้งานที่แสดงอย่างสมบูรณ์คือดรอปดาวน์ออกจากระบบในแถบนำทางของเว็บแอป

@using (Html.BeginForm("Logout", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
{
    @Html.AntiForgeryToken()

    <div class="dropdown">
        <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
            <span class="ma-nav-text ma-account-name">@User.Identity.Name</span>
            <i class="material-icons md-36 text-inverse">person</i>
        </button>

        <ul class="dropdown-menu dropdown-menu-right ma-dropdown-tray">
            <li>
                <a href="javascript:document.getElementById('logoutForm').submit()">
                    <i class="material-icons">system_update_alt</i>
                    <span>Sign out</span>
                </a>
            </li>
        </ul>
    </div>
}


2

ใช้ลิงค์เรียกการดำเนินการต่อไปนี้:

<%= Html.ActionLink("Click Here" , "ActionName","ContorllerName" )%>

สำหรับการส่งค่าแบบฟอร์มให้ใช้:

 <% using (Html.BeginForm("CustomerSearchResults", "Customer"))
   { %>
      <input type="text" id="Name" />
      <input type="submit" class="dASButton" value="Submit" />
   <% } %>

จะส่งข้อมูลไปยัง Customer Controller และ CustomerSearchResults Action


1

ใช้ลิงค์นี้ใน AjaxBeginForm

@Html.ActionLink(
    "Save", 
    "SaveAction", 
    null, 
    null, 
    onclick = "$(this).parents('form').attr('action', $(this).attr('href'));$(this).parents('form').submit();return false;" })

;)


1

วิธีแก้ปัญหาของฉันสำหรับปัญหานี้ค่อนข้างง่าย ฉันมีหน้าที่ค้นหาลูกค้าทีละคนทั้งอีเมลและอีกหน้าหนึ่งโดยการดึงข้อมูลบางส่วนและแสดงรายการรายการมีลิงค์การดำเนินการที่ชี้ไปยังผลการดำเนินการที่เรียกว่า GetByID และส่งผ่านในรหัส

GetByID ดึงข้อมูลสำหรับลูกค้าที่เลือกแล้วส่งกลับ

return View("Index", model); 

ซึ่งเป็นวิธีการโพสต์


1

นี่เป็นปัญหาที่ยากสำหรับฉันที่จะแก้ไข ฉันจะสร้างลิงก์แบบไดนามิกในมีดโกนและ html ที่สามารถเรียกใช้วิธีการดำเนินการและส่งค่าหรือค่าไปยังวิธีการดำเนินการเฉพาะได้อย่างไร ฉันพิจารณาตัวเลือกหลายอย่างรวมถึงตัวช่วย html ที่กำหนดเอง ฉันเพิ่งคิดวิธีแก้ปัญหาที่เรียบง่ายและสง่างาม

มุมมอง

@model IEnumerable<MyMvcApp.Models.Product>

@using (Html.BeginForm()) {

     <table>
         <thead>
             <tr>
                 <td>Name</td>
                 <td>Price</td>
                 <td>Quantity</td>
            </tr>
        </thead>
        @foreach (Product p in Model.Products)
        {
            <tr>
                <td><a href="@Url.Action("Edit", "Product", p)">@p.Name</a></td>
                <td>@p.Price.ToString()</td>
                <td>@p.Quantity.ToString()</td>
            </tr>
         }
    </table>
}

วิธีการดำเนินการ

public ViewResult Edit(Product prod)
{
    ContextDB contextDB = new ContextDB();

    Product product = contextDB.Products.Single(p => p.ProductID == prod.ProductId);

    product = prod;

    contextDB.SaveChanges();

    return View("Edit");
}

ประเด็นคือ Url.Action ไม่สนใจว่าวิธีการดำเนินการจะเป็น GET หรือ POST มันจะเข้าถึงวิธีการประเภทใดประเภทหนึ่ง คุณสามารถส่งข้อมูลของคุณไปยังวิธีการดำเนินการโดยใช้

@Url.Action(string actionName, string controllerName, object routeValues)

วัตถุ routeValues ฉันได้ลองแล้วและได้ผล ไม่คุณไม่ได้ทำโพสต์หรือส่งแบบฟอร์มในทางเทคนิค แต่ถ้าออบเจ็กต์ routeValues ​​มีข้อมูลของคุณก็ไม่สำคัญว่าจะโพสต์หรือได้รับ คุณสามารถใช้ลายเซ็นวิธีการดำเนินการเฉพาะเพื่อเลือกวิธีการที่เหมาะสม


1
ฉันลองใช้ตัวอย่างของคุณแล้วเบราว์เซอร์ส่ง GET ไปยังเซิร์ฟเวอร์แม้แต่แบบฟอร์มก็มีประเภทโพสต์ หาก actionMethod ในคอนโทรลเลอร์มีการร้องขอแอตทริบิวต์ [HttpPost] ล้มเหลวเนื่องจากไม่พบเส้นทาง
Vitaliy Markitanov

1

ฉันได้แก้ไขปัญหาเดียวกันโดยใช้รหัสต่อไปนี้:

@using (Html.BeginForm("Delete", "Admin"))
{
       @Html.Hidden("ProductID", item.ProductID)
       <input type="submit" value="Delete" />
}

หากคุณมีหลายรายการในหน้านี้คุณจะต้องห่อแต่ละรายการให้เป็นรูปแบบและจะมีการสร้างแบบฟอร์มมากมาย นอกจากนี้ปุ่ม <input type = submit> แสดงผลไม่ใช่ลิงก์
Vitaliy Markitanov

@VitaliyMarkitanov คุณแนะนำให้ใช้ jQuery ajax?
isxaker

ดูโพสต์ของฉันด้านล่างในหัวข้อนี้ฉันอธิบายวิธีแก้ปัญหาที่นั่น
Vitaliy Markitanov

ในโครงการตัวอย่าง MVC นี่ก็เป็นสิ่งที่พวกเขาทำเช่นกัน
Maya

1

นี่คือทางออกสำหรับปัญหาของฉัน นี่คือคอนโทรลเลอร์ที่มี 2 วิธีการดำเนินการ

public class FeedbackController : Controller
{
public ActionResult Index()
{
   var feedbacks =dataFromSomeSource.getData;
   return View(feedbacks);
}

[System.Web.Mvc.HttpDelete]
[System.Web.Mvc.Authorize(Roles = "admin")]
public ActionResult Delete([FromBody]int id)
{
   return RedirectToAction("Index");
}
}

ในมุมมองฉันสร้างโครงสร้างต่อไปนี้

<html>
..
<script src="~/Scripts/bootbox.min.js"></script>
<script>
function confirmDelete(id) {
  bootbox.confirm('@Resources.Resource.AreYouSure', function(result) {
    if (result) {
      document.getElementById('idField').value = id;
      document.getElementById('myForm').submit();
    }
  }.bind(this));
}
</script>

@using (Html.BeginForm("Delete", "Feedback", FormMethod.Post, new { id = "myForm" }))
{
  @Html.HttpMethodOverride(HttpVerbs.Delete)
  @Html.Hidden("id",null,new{id="idField"})
  foreach (var feedback in @Model)
  {
   if (User.Identity.IsAuthenticated && User.IsInRole("admin"))
   {
    @Html.ActionLink("Delete Item", "", new { id = @feedback.Id }, new { onClick = "confirmDelete("+feedback.Id+");return false;" })
   }
  }
...
</html>

จุดที่น่าสนใจใน Razor View :

  1. ฟังก์ชัน JavaScript confirmDelete(id)ซึ่งเรียกว่าเมื่อการเชื่อมโยงสร้างขึ้นด้วย@Html.ActionLinkการคลิก;

  2. confirmDelete()ฟังก์ชั่นรหัสที่จำเป็นของรายการที่คลิก รายการนี้ถูกส่งผ่านจากonClickตัวจัดการconfirmDelete("+feedback.Id+");return false;Pay Attention handler จะส่งกลับเท็จเพื่อป้องกันการดำเนินการเริ่มต้น - ซึ่งได้รับการร้องขอไปยังเป้าหมาย OnClickสามารถแนบเหตุการณ์สำหรับปุ่มด้วย jQuery สำหรับปุ่มทั้งหมดในรายการเป็นทางเลือกอื่น (อาจจะดีกว่านี้เนื่องจากจะมีข้อความน้อยลงในหน้า HTML และข้อมูลสามารถส่งผ่านdata-แอตทริบิวต์ได้)

  3. แบบฟอร์มมีเพื่อที่จะหาได้ในid=myFormconfirmDelete()

  4. แบบฟอร์มรวมถึง@Html.HttpMethodOverride(HttpVerbs.Delete)การใช้HttpDeleteคำกริยาเป็นการกระทำที่มีเครื่องหมายHttpDeleteAttribute.

  5. ในฟังก์ชัน JS ฉันใช้การยืนยันการดำเนินการ (ด้วยความช่วยเหลือของปลั๊กอินภายนอก แต่การยืนยันมาตรฐานก็ใช้ได้เช่นกันอย่าลืมใช้bind()ในการโทรกลับหรือvar that=this(อะไรก็ได้ที่คุณต้องการ)

  6. แบบฟอร์มมีองค์ประกอบที่ซ่อนอยู่ด้วยและid='idField' name='id'ดังนั้นก่อนที่จะส่งแบบฟอร์มหลังจากการยืนยัน ( result==true) ค่าขององค์ประกอบที่ซ่อนอยู่จะถูกตั้งค่าเป็นอาร์กิวเมนต์ที่ส่งผ่านค่าและเบราว์เซอร์จะส่งข้อมูลไปยังตัวควบคุมดังนี้:

ขอ URL :http://localhost:38874/Feedback/Delete

วิธีการขอ : รหัสสถานะ POST: พบ 302

ส่วนหัวการตอบกลับ

ตำแหน่ง: / โฮสต์ข้อเสนอแนะ: localhost: 38874 แบบฟอร์มข้อมูล X-HTTP-Method-Override: DELETE id: 5

ดังที่คุณเห็นคือคำขอ POST ที่มี X-HTTP-Method-Override: DELETE และข้อมูลในเนื้อหาถูกตั้งค่าเป็น "id: 5" การตอบกลับมีรหัส 302 ซึ่งเปลี่ยนเส้นทางไปยังการดำเนินการของดัชนีโดยคุณจะรีเฟรชหน้าจอของคุณหลังจากลบ


1

นำมาจากโครงการตัวอย่าง MVC

@if (ViewBag.ShowRemoveButton)
      {
         using (Html.BeginForm("RemoveLogin", "Manage"))
           {
              @Html.AntiForgeryToken()
                  <div>
                     @Html.Hidden("company_name", account)
                     @Html.Hidden("returnUrl", Model.returnUrl)
                     <input type="submit" class="btn btn-default" value="Remove" title="Remove your email address from @account" />
                  </div>
            }
        }

0

ฉันขอแนะนำให้ปฏิบัติตามหลักการ REST อย่างบริสุทธิ์ใจและใช้การลบ HTTP สำหรับการลบของคุณ ขออภัยข้อกำหนด HTML มีเพียง HTTP Get & Post แท็กสามารถรับ HTTP เท่านั้น แท็กแบบฟอร์มสามารถทำ HTTP Get หรือ Post โชคดีถ้าคุณใช้ ajax คุณสามารถทำ HTTP Delete ได้และนี่คือสิ่งที่ฉันแนะนำ ดูรายละเอียดในโพสต์ต่อไปนี้: http Deletes


0

การเรียก $ .post () จะไม่ทำงานเนื่องจากใช้ Ajax ดังนั้นจึงต้องใช้วิธีไฮบริดเพื่อจุดประสงค์นี้

ต่อไปนี้เป็นวิธีแก้ปัญหาที่ใช้ได้ผลสำหรับฉัน

ขั้นตอน: 1. สร้าง URL สำหรับ href ซึ่งเรียกเมธอดด้วย url และพารามิเตอร์ 2. เรียก POST ปกติโดยใช้วิธี JavaScript

วิธีการแก้:

ใน. cshtml:

<a href="javascript:(function(){$.postGo( '@Url.Action("View")', { 'id': @receipt.ReceiptId  } );})()">View</a>

หมายเหตุ: วิธีการที่ไม่ระบุตัวตนควรอยู่ใน (.... ) () เช่น

(function() {
    //code...
})();

postGoถูกกำหนดไว้ด้านล่างใน JavaScript พักผ่อนง่ายๆ ..

@ Url.Action ("View")สร้าง url สำหรับการโทร

{'id': @ Receipt.ReceiptId}สร้างพารามิเตอร์เป็นวัตถุซึ่งจะถูกแปลงเป็นช่อง POST ในวิธี postGo ซึ่งอาจเป็นพารามิเตอร์ใดก็ได้ตามที่คุณต้องการ

ใน JavaScript:

(function ($) {
    $.extend({
        getGo: function (url, params) {
            document.location = url + '?' + $.param(params);
        },
        postGo: function (url, params) {
            var $form = $("<form>")
                .attr("method", "post")
                .attr("action", url);
            $.each(params, function (name, value) {
                $("<input type='hidden'>")
                    .attr("name", name)
                    .attr("value", value)
                    .appendTo($form);
            });
            $form.appendTo("body");
            $form.submit();
        }
    });
})(jQuery);

URL อ้างอิงที่ฉันใช้สำหรับ postGo

ไม่ใช่ ajax GET / POST โดยใช้ jQuery (ปลั๊กอิน?)

http://nuonical.com/jquery-postgo-plugin/


0

jQuery.post()จะทำงานถ้าคุณมีข้อมูลที่กำหนดเอง ajaxSubmit()หากคุณต้องการที่จะโพสต์รูปแบบที่มีอยู่มันง่ายต่อการใช้งาน

และคุณไม่จำเป็นต้องตั้งค่ารหัสนี้ในActionLinkตัวเองเนื่องจากคุณสามารถแนบตัวจัดการลิงก์ในdocument.ready()เหตุการณ์ได้ (ซึ่งเป็นวิธีที่ต้องการ) เช่นใช้$(function(){ ... })เคล็ดลับ jQuery


0

เมื่อเจอสิ่งนี้จำเป็นต้องโพสต์จากหน้าค้นหา (ดัชนี) ไปยังหน้าผลลัพธ์ ฉันไม่ต้องการมากเท่าที่ @Vitaliy ระบุ แต่มันชี้ให้ฉันไปในทิศทางที่ถูกต้อง สิ่งที่ฉันต้องทำก็คือ:

@using (Html.BeginForm("Result", "Search", FormMethod.Post)) {
  <div class="row">
    <div class="col-md-4">
      <div class="field">Search Term:</div>
      <input id="k" name="k" type="text" placeholder="Search" />
    </div>
  </div>
  <br />
  <div class="row">
    <div class="col-md-12">
      <button type="submit" class="btn btn-default">Search</button>
    </div>
  </div>
}

ตัวควบคุมของฉันมีวิธีลายเซ็นดังต่อไปนี้:

[HttpPost]
public async Task<ActionResult> Result(string k)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.