ASP.NET MVC ActionLink and post method
Asked Answered
G

17

105

Can anyone tell me how can I submit values to Controller using ActionLink and POST method?
I don't want to use buttons.
I guess it has something with jquery.

Grayce answered 12/1, 2010 at 12:15 Comment(1)
I've wrote a method that is similar to Html.ActionLink, only it builds POST Form with Submit button. I'll see if I can give option to replace button with link that submits form. See here: #3450307Stefanstefanac
S
60

You can't use an ActionLink because that just renders an anchor <a> tag.
You can use a jQuery AJAX post.
Or just call the form's submit method with or without jQuery (which would be non-AJAX), perhaps in the onclick event of whatever control takes your fancy.

Seibel answered 12/1, 2010 at 13:23 Comment(0)
C
72

If you're using ASP MVC3 you could use an Ajax.ActionLink(), that allows you to specify a HTTP Method which you could set to "POST".

Cronin answered 31/5, 2011 at 7:45 Comment(3)
Note that to make this work, you will have to include one of the ajax javascript files, for example "jquery.unobtrusive-ajax.min.js". Otherwise, it will continue to do a GET instead of a POST when clicked. Syntax to make the link would be like: @Ajax.ActionLink("Delete", "Delete", new { id = item.Id }, new AjaxOptions {HttpMethod = "POST"})Partook
unobtrusive ajax worked fine BUT I had to use the action link a bit different, passing a Dictionary as parameter instead of this AjaxOptions object: https://mcmap.net/q/205782/-mvc-4-actionlink-dictionary-htmlattributes-doesn-39-t-work Also, I had to pass the ajax attributes by hand so that the JS could catch and override the click events, they were "data-ajax"="true, "data-ajax-url"=<your link> and "data-ajax-method"="Post". Btw, I am using ASP.NET MVC 3Inseparable
@CokoBWare this one #10508237 ? really? It does not seem to be broken for me...Inseparable
S
60

You can't use an ActionLink because that just renders an anchor <a> tag.
You can use a jQuery AJAX post.
Or just call the form's submit method with or without jQuery (which would be non-AJAX), perhaps in the onclick event of whatever control takes your fancy.

Seibel answered 12/1, 2010 at 13:23 Comment(0)
L
22

You can use jQuery to do a POST for all your buttons. Just give them the same CssClass name.

Use "return false;" at the end of your onclick javascript event if you want to do a server side RedirectToAction after the post otherwise just return the view.

Razor Code

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

JQuery Code

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

C#

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

    return RedirectToAction("Index");
    //return View(model);
}
Lead answered 23/1, 2012 at 23:51 Comment(1)
@goodies4uall Indeed, and this answer does just that. :) The CSS class is named "saveButton" (perhaps a misleading name), but an anchor tag is used to initiate the actionImplied
L
21

@Aidos had the right answer just wanted to make it clear since it is hidden inside a comment on his post made by @CodingWithSpike.

@Ajax.ActionLink("Delete", "Delete", new { id = item.ApkModelId }, new AjaxOptions { HttpMethod = "POST" })
Leyba answered 11/12, 2012 at 3:25 Comment(0)
T
10

Here was an answer baked into the default ASP.NET MVC 5 project I believe that accomplishes my styling goals nicely in the UI. Form submit using pure javascript to some containing form.

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

The fully shown use case is a logout dropdown in the navigation bar of a web app.

@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>
}
Teleutospore answered 2/8, 2017 at 2:1 Comment(0)
A
4

ActionLink will never fire post. It always trigger GET request.

Afire answered 17/5, 2011 at 14:14 Comment(0)
A
2

Use the following the Call the Action Link:

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

For submitting the form values use:

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

It will submit the Data to Customer Controller and CustomerSearchResults Action.

Afire answered 12/1, 2010 at 12:15 Comment(0)
J
2

This is taken from the MVC sample project

@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>
            }
        }
Jamnes answered 5/6, 2019 at 14:54 Comment(0)
C
1

Use this link inside Ajax.BeginForm

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

;)

Cribbage answered 5/8, 2011 at 23:15 Comment(0)
H
1

My Solution to this issue is a fairly simple one. I have a page that does a customer search one by the whole email and the other by a partial, the partial pulls and displays a list the list has an action link that points to a actionresult called GetByID and passes in the id

the GetByID pulls the data for the selected customer then returns

return View("Index", model); 

which is the post method

Hoofbeat answered 21/10, 2011 at 19:16 Comment(0)
G
1

This has been a difficult problem for me to solve. How can I build a dynamic link in razor and html that can call an action method and pass a value or values to a specific action method? I considered several options including a custom html helper. I just came up with a simple and elegant solution.

The view

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

The action method

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

The point here is that Url.Action does not care whether the action method is a GET or a POST. It will access either type of method. You can pass your data to the action method using

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

the routeValues object. I have tried this and it works. No, you are not technically doing a post or submitting the form but if the routeValues object contains your data, it doesnt matter if its a post or a get. You can use a particular action method signature to select the right method.

Goebel answered 19/12, 2011 at 16:45 Comment(1)
I tried your sample and browser sends GET to the server, even form has Post type. If actionMethod in controller has attribute [HttpPost] request fails as route not found.Strow
Q
1

I have done the same issue using following code:

@using (Html.BeginForm("Delete", "Admin"))
{
       @Html.Hidden("ProductID", item.ProductID)
       <input type="submit" value="Delete" />
}
Quasijudicial answered 20/11, 2014 at 7:9 Comment(4)
If you have many items on the page, you will need to wrap each of them into form, and as result many forms will be generated. Also <input type=submit > renders button, not link.Strow
@VitaliyMarkitanov you're suggest to use jQuery ajax?Quasijudicial
Look at my post below in this thread, i explained my solution there.Strow
In the MVC sample project, this is pretty much exactly what they do tooJamnes
S
1

This is my solution for the problem. This is controller with 2 action methods

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

In View I render construct following structure.

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

Point of interest in Razor View:

  1. JavaScript function confirmDelete(id) which is called when the link generated with @Html.ActionLink is clicked;

  2. confirmDelete() function required id of item being clicked. This item is passed from onClick handler confirmDelete("+feedback.Id+");return false; Pay attention handler returns false to prevent default action - which is get request to target. OnClick event for buttons could be attached with jQuery for all buttons in the list as alternative (probably it will be even better, as it will be less text in the HTML page and data could be passed via data- attribute).

  3. Form has id=myForm, in order to find it in confirmDelete().

  4. Form includes @Html.HttpMethodOverride(HttpVerbs.Delete) in order to use the HttpDelete verb, as action marked with the HttpDeleteAttribute.

  5. In the JS function I do use action confirmation (with help of external plugin, but standard confirm works fine too. Don't forget to use bind() in call back or var that=this (whatever you prefer).

  6. Form has a hidden element with id='idField' and name='id'. So before the form is submitted after confirmation (result==true), the value of the hidden element is set to value passed argument and browser will submit data to controller like this:

Request URL:http://localhost:38874/Feedback/Delete

Request Method:POST Status Code:302 Found

Response Headers

Location:/Feedback Host:localhost:38874 Form Data X-HTTP-Method-Override:DELETE id:5

As you see it is POST request with X-HTTP-Method-Override:DELETE and data in body set to "id:5". Response has 302 code which redirect to Index action, by this you refresh your screen after delete.

Strow answered 30/7, 2015 at 20:15 Comment(0)
G
0

jQuery.post() will work if you have custom data. If you want to post existing form, it's easier to use ajaxSubmit().

And you don't have to setup this code in the ActionLink itself, since you can attach link handler in the document.ready() event (which is a preferred method anyway), for example using $(function(){ ... }) jQuery trick.

Glyphography answered 12/1, 2010 at 12:37 Comment(0)
S
0

I would recommend staying pure to REST principles and using an HTTP delete for your deletes. Unfortunately HTML Specs only has HTTP Get & Post. A tag only can a HTTP Get. A form tag can either do a HTTP Get or Post. Fortunately if you use ajax you can do a HTTP Delete and this is what i recommend. See the following post for details: Http Deletes

Sweetmeat answered 31/7, 2011 at 5:34 Comment(0)
D
0

Calling $.post() won't work as it is Ajax based. So a hybrid method needs to be used for this purpose.

Following is the solution which is working for me.

Steps: 1. Create URL for href which calls the a method with url and parameter 2. Call normal POST using JavaScript method

Solution:

In .cshtml:

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

Note: the anonymous method should be wrapped in (....)() i.e.

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

postGo is defined as below in JavaScript. Rest are simple..

@Url.Action("View") creates url for the call

{ 'id': @receipt.ReceiptId } creates parameters as object which is in-turn converted to POST fields in postGo method. This can be any parameter as you require

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

Reference URLs which I have used for postGo

Non-ajax GET/POST using jQuery (plugin?)

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

Dosimeter answered 29/7, 2015 at 10:54 Comment(0)
S
0

Came across this needing to POST from a Search (Index) page to the Result page. I did not need as much as @Vitaliy stated but it pointed me in the right direction. All I had to do was this:

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

My Controller had the following signature method:

[HttpPost]
public async Task<ActionResult> Result(string k)
Saida answered 8/2, 2017 at 15:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.