Is it possible to Invoke a HttpPost Action method from #Html.ActionLink ?
[HttpPost]
public ActionResult Delete()
{
// delete
}
#Html.ActionLink("Delete","Delete","Cart") will render an anchor tag which is a get request.
I have a list of products i am showing in the shopping cart and i want to add a delete button.
add a javascript listener on the click event of that actionLink and in the callback function of the listener just do s POST to your action.
Related
I have a list, select a record, press the edit button and get an update view (form) via ajax. Then I modify some property and press save. This form is used both for creating and updating data. I distinguish in the view via ViewBag, like this:
<form asp-action=#(ViewBag.Mode == "new" ? "AddSender" : "UpdateSender") asp-controller="Sender" method="post">
In the ajax call I get the properties of the edited model with this url: /MasterData/Sender/UpdateSender/3 (3 is here only an example). Now, when I save and post back the data, the update action doesn't get hit, because the html getting for the update view looks like this:
<form method="post" action="/MasterData/Sender/UpdateSender/3">
The question is, why is the action method like this? Why is the earlier get url used? I thought, it should be just UpdateSender, as intended.
To be complete, here are the related actions in this order:
[Route("{SenderId}")]
public IActionResult UpdateSender(long SenderId)
{
ViewBag.Mode = "update";
return PartialView("Sender", SenderRepository.GetSender(SenderId));
}
[HttpPost]
public IActionResult UpdateSender(Sender Sender)
{
SenderRepository.UpdateSender(Sender);
return RedirectToAction(nameof(List));
}
And I have on the top of the controller class this attribute: [Route("MasterData/[controller]/[action]")]
The POST action needs to have a route as well if the intention is to use attribute routing.
Add the Route attribute on your [HttpPost] action.
[HttpPost]
[Route("UpdateSender")]
public IActionResult UpdateSender(Sender Sender)
{
SenderRepository.UpdateSender(Sender);
return RedirectToAction(nameof(List));
}
I have a link and search button. Clicking on search button posts the page to a predefined action. Now clicking on a link should post the page to another action and should post all the values hidden varible values to another action. Can it be done.
Typically A link will generate an anchor tag and it usually gives you an HTTP GET request. Not the post request. You can supply parameters in your link which will be accepted as the parameters of the action method
#Html.ActionLink("Search","Search","Items",new { #id="nokia" },null);
This will generate a link with a querystring key called id with value nokia.
../Items/Search/nokia
or
../Items/Search?id=nokia
And your action method with id parameter can handle this GET request
public ActionResult Search(string id)
{
//Do whatever you want to do with the value in id. return a view with results
}
IF you really want to do an HTTPPost from a link, You can grab the click event of the link in the javascript and make an httppost call. The below script does that with jQuery library.
$(function(){
$("a").click(function(e){
e.preventDefault();
$.post($(this).attr("href"),function(result){
//do whatever with the results
});
});
});
But make sure you have an HttpPost version of the ActionMethod in your controller to handle this request
[HttpPost]
public ActionResult Search(string id)
{
//This is a POST request.Do whatever you want to do with the value in id. return a view with results
}
You can't use #Html.ActionLink for HTTP POST (edited: unless you use javascript function to submit the form via specifying onClick HtmlAttribute) . You can use submit buttons instead and style them as hyperlinks using jQuery. In this case you should be able to post your model with whatever values.
Alternatively you can use #Ajax.ActionLink and specify AjaxOptions { HttpMethod = "POST" }
UPDATE:
My model going into the save method is PartialViewModel, which in the save method, is pushed into the index's ContactViewModel and sent back. This wasn't clear.
I am playing around with MVC3, and have a contact controller with a SaveDetails action. The index cshtml has a partial with a form whose action is pointing to this controller.
When I submit the form not having completed it fully, thereby firing the validation, the url now contains the SaveDetails action name (http://localhost:7401/Contact/SaveDetails).
The form code is:
#using (Html.BeginForm("SaveDetails", "Contact")) {
...
}
The controller action looks like this:
public ActionResult SaveDetails(Models.PartialsViewModel pvm)
{
return View("Index", new ContactViewModel{ PartialsViewModel = pvm } );
}
What am I doing wrong?
The form has the action attribute set to SaveDetails action, so after submit it redirects the browser to this action.
I don' think you are doing anything wrong but I don't think you are able to do what you are tying to achieve. A request has to go somewhere and in mvc the url is used to identify which action you want to perform. If you are not submitting a post back then the url is going to change.
One way to submit the forms to different actions would be using some ajax.
Submitting the form is a POST. You can use an attribute to identify what request method an action should respond to. This means that you can create another action also called Index but give it the [HttpPost] attribute.
[HttpPost]
public ActionResult Index(Models.ContactViewModel cvm)
{
return View();
}
This way it won't display the action in the url.
I'm looking into using partial views in MVC3 using Razor, and I get my partial view to render and it works fine.
What I'd like to do, though, is refresh the parent view when the partial view is submitted.
Code in my parent view to render partial view
<div id="mydiv">
#{ Html.RenderAction("Add", "Request"); }
</div>
Action for parent view is simple,
public ActionResult Index()
{
List<obj> reqs = //some query
return View(reqs);
}
In my partial view's get action I have:
public ActionResult Add()
{
AddRequestViewModel vm = new AddRequestViewModel();
//set some stuff on the VM here
return PartialView(vm);
}
In the post action called by the partial view, if modelstate isn't valid, return PartialView(vm)
If it is valid, I'd like the parent and partial views to refresh.
I tried RedirectToAction, but this can't be called in an action called by a partial, apparently, and I tried return Index();, but this causes an issue with the code used to render the partial view,
Exception Details: System.InvalidOperationException: The model item passed into the dictionary is of type 'System.Collections.Generic.List'1[DatRequests.Models.ReqRequest]', but this dictionary requires a model item of type 'DatRequests.ViewModels.AddRequestViewModel'.
Any suggestions on how to do this would be appreciated. The purpose of the page is to show a list of elements, and the partial contains a form to add a new element to the list.
Edit: The partial's model is different, as it contains data for selection, which is from a db, which is why I tried RenderAction, but I'm not sure if there are other ways of doing this.
When the partial view is submitted normally you submit it to some controller action. You could either submit it using a normal request or an AJAX request. If you use a normal request you could perform a standard redirect to the Index inside the POST controller action that will handle the form submission. If you use AJAX, you could return a JSON result pointing to the url that you want to redirect:
[HttpPost]
public ActionResult Foo(MyViewModel model)
{
if (!ModelState.IsValid)
{
return PartialView(model);
}
return Json(new { url = Url.Action("Index") });
}
and inside your AJAX success callback:
success: function(result) {
if (result.url) {
// we have a success
window.location.href = result.url;
} else {
// invalid modelstate => refresh the partial
$('#mydiv').html(result);
}
}
Probably RenderAction should not be used this way.
When using Html.RenderAction, a new/seperate request would be sent to the server. And you got another chance to load some data from db or somewhere else to display to the client. Also, you could apply OutputCache to this action. this is usually the way doing global cache.
Here you are doing a POST to the server. Either directly put a element here or using a partial view to do the Post. And in the corresponding action, do a RedirectToAction.
Do it with ajax or not isn't the point. my opinion is more about the right way using RenderAction
I have a controller with the codes like this:
[AcceptVerbs("POST")]
public ActionResult Create(FormCollection collection)
{
//why is that the collection is null?
}
I am calling this action using the ajax.actionlink.
my problem is the collection is null, unlike if i use the submit(input) button
the formcollection has values.
FormCollection has a default binder associated with it which always initializes the collection and you should never get null. It is more likely that you have an empty collection when using Ajax.ActionLink in contrast to when using a form submit button. This is because the ActionLink method doesn't POST any form values when it performs the AJAX request.
You need to use Ajax.BeginForm