I have a View which displays a list of file names. Also i have two buttons called View and Release. When I select a file name from the list and click on view, it navigates to the appropriate action method along with the file name selected as a parameter and performs the functionality as required.
But when i click on Release after selecting a file name, it does navigates to the appropriate action method, but does not passes the file name as a parameter to the action method. It shows as null.
Please note that View and Release directs to a single controller having different action methods.
How can i get to pass the filename as a parameter when i click on release?
Please see the code below:
public class HoldFilesController : Controller
{
// GET: HoldFiles
string holdpath = ConfigurationManager.AppSettings["HoldPath"].ToString();
public ActionResult Index()
{
DirectoryInfo dirInfo = new DirectoryInfo(holdpath);
List<FileInfo> files = dirInfo.GetFiles().ToList();
return View("Index",files);
}
}
[HttpPost]
public ActionResult ViewFile(string[] Name)
{
byte[] ImageData = null;
for (int i = 0; i < Name.Length; i++)
{
string filepath = holdpath + #"\" + Name[i];
FileStream fs = new FileStream(filepath, FileMode.Open,
FileAccess.ReadWrite);
ImageData = new byte[fs.Length];
fs.Read(ImageData, 0, System.Convert.ToInt32(fs.Length));
fs.Close();
}
return File(ImageData,"application/pdf");
}
[HttpPost]
public ActionResult ReleaseFile(string[] Name)
{
for(int i=0; i<Name.Length;i++)
{
string sourcefilepath= holdpath + #"\" + Name[i];
string Destinationfilepath =
ConfigurationManager.AppSettings["ReleaseFolderPath"].ToString();
string ReleaseFilePath = Destinationfilepath + #"\" + Name[i];
if (Directory.Exists(Destinationfilepath))
{
System.IO.File.Move(sourcefilepath, ReleaseFilePath);
}
}
return RedirectToAction("Index");
}
Here's the code for my view:
#model IEnumerable<FileInfo>
#{
ViewBag.Title = "files";
}
<h2>Held files</h2>
#using (Html.BeginForm())
{
<div style="border:solid;width:100%;overflow-x:auto;">
<table align="center" style="width:100%">
<thead>
<tr>
<th>File Name</th>
<th>Action</th>
</tr>
</thead>
<tbody>
#foreach (FileInfo file in Model)
{
<tr>
<td>
<input type="checkbox" name="Name" value="#file.Name" />
#file.Name
</td>
</tr>
}
</tbody>
</table>
</div>
<input type="submit" id="Held" name="Held file" value="View" />
<input type="submit" id="Release" name="release" value="Release" />
}
Just to avoid confusion, the View button redirects to the ViewFile method
and the Release button redirects to Releasefile method.
You have multiple options to do this.
You can hijack the submit button click and update the form action attribute value based on what button is clicked and do the form submit using javascript.
You can keep the url to the 2 action methods in html5 data attributes on the button.
<input type="submit" data-myaction="#Url.Action("View")" value="View"/>
<input type="submit" data-myaction="#Url.Action("Release")" value="Release"/>
Using the Url.Action method to generate the correct relative path to the action method is a safe practice. Let the method worry about generating the correct path for you.
And the javascript
$(function () {
$("input[data-myaction]").click(function(e) {
e.preventDefault(); // stop the normal form submit
// read the data attribute and update the forms action and do a submit
$(this).closest("form").attr('action', $(this).data('myaction')).submit();
});
});
Another option is using html5 formaction which does not need any javascript hijacking. When you specify a formaction attribute value, it will override the parent form's action attribute. this is very useful when you have more than one submit button with 2 different action methods to submit to (your use case)
<input type="submit" formaction="#Url.Action("View")" value="View"/>
<input type="submit" formaction="#Url.Action("Release")" value="Release"/>
1-HTML5 formaction and formmethod attributes
<input type="submit" name="view" value="view" formaction="ViewFile" formmethod="post" />
<input type="submit" name="Release" value="Release" formaction="ReleaseFile" formmethod="post" />
2-jQuery / JavaScript code
$(document).ready(function () {
$("#Held").click(function () {
$("form").attr("action", "/HoldFiles/ViewFile");
});
$("#Release").click(function () {
$("form").attr("action", "/HoldFiles/ReleaseFile");
});
});
Related
I want to show an info modal that says "Record successfully deleted." after clicking the button inside a Confirmation Modal.
Here is my code to show the confirmation modal
Controller
public IActionResult Delete()
{
return PartialView("_ModalDelete");
}
_ModalDelete.cshtml
#using Data.ViewModels.Modal
#using (Html.BeginForm())
{
#await Html.PartialAsync("_ModalHeader", new ModalHeader { Heading = "Delete" })
<div class="modal-body form-horizontal">
Are you sure you want to delete this record?
</div>
#await Html.PartialAsync("_ModalFooter", new ModalFooter { SubmitButtonText = "Delete" })
}
Example Screenshot:
This seems to be okay on this part. No issues encounter. But after clicking the Delete button, it will show my modal like a whole view. See below:
Here is my code:
Controller - for post of data after clicking delete button
[HttpPost]
public async Task<IActionResult> Delete(int id)
{
try
{
var validationResult = await new RegionHandler(_regionService).CanDelete(id);
if (validationResult == null)
{
await _regionService.DeleteById(id);
return PartialView("_ModalInfo", new Tuple<string, string>(Constants.Message.Info, Constants.Message.RecordSuccessDelete));
}
ModelState.AddModelError(validationResult);
}
catch (Exception ex)
{
var exceptionMessage = await Helpers.GetErrors(ex, _emailService);
ModelState.AddModelError(new ValidationResult(exceptionMessage));
}
ModelState.AddModelError(string.Empty, "Invalid delete attempt.");
return PartialView("_ModalInfo", new Tuple<string, string>(Constants.Message.Error, ModelState.ToString()));
}
_ModalInfo.cshtml
#using Data.ViewModels.Modal
#model Tuple<string,string>
#await Html.PartialAsync("_ModalHeader", new ModalHeader { Heading = Model.Item1})
<div class="modal-body form-horizontal">
#Model.Item2
</div>
#await Html.PartialAsync("_ModalFooter", new ModalFooter { CancelButtonText = "OK", OnlyCancelButton = true})
With the submission of your form you are making a roundtrip to the server, which will issue a completely new html page (even if your html code is only partial).
To remove the question-modal and replace it with a message-modal in the original page (region-list), you will have to use javascript (for the post AND the replacement).
If you want to stick with the roundtrip, make the Delete method return a full html page, which integrates the message-dialog (like the region-list intergrates the question-dialog).
Finally found an answer with this. So basically I just revised everything so that the model validation from controller will still be there.
Heres my code:
For the table markup
<tr>
<td>
#Html.DisplayFor(modelItem => item.RegionName)
</td>
<td>
#Html.DisplayFor(modelItem => item.RegionCode)
</td>
<td>
#Html.DisplayFor(modelItem => item.RegionKey)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td class="text-center">
<a asp-action="Edit" asp-route-id="#item.RegionId"><i class="fa fa-edit text-info"></i></a>
<i class="fa fa-trash text-danger"></i>
</td>
</tr>
where it call a javascript function below:
#section Scripts{
<script type="text/javascript">
function showDeleteConfirmation(message, event, id) {
event.preventDefault();
showConfirmationModal(message).then(function () {
$("#id").val(id);
$("#formDelete").submit();
});
}
</script>
}
where showConfirmationModal() is a promise function that uses bootbox.js (library that wraps bootstrap modal for easier usage).
site.js
function showConfirmationModal(message, title = "Confirm", size = "medium", confirmText = "Yes", canceltext = "No") {
const deffered = $.Deferred();
bootbox.confirm({
title: title,
message: message,
size: size,
buttons: {
confirm: {
label: confirmText,
className: "btn-success"
},
cancel: {
label: canceltext,
className: "btn-danger"
}
},
callback: function (result) {
if (result) {
deffered.resolve(result);
} else {
deffered.reject(result);
}
}
});
return deffered.promise();
}
On callback, it will submit the hidden form below. Ofcourse don't forget to set the id to be deleted.
Hidden form for Delete action
<form method="post" asp-action="Delete" id="formDelete" class="hidden">
<input type="hidden" id="id" name="id" />
<input type="hidden" asp-for="Item1.RegionName" name="RegionName" />
<input type="hidden" asp-for="Item1.Page" name="Page" />
<input type="hidden" asp-for="Item1.SortBy" name="SortBy" />
<input type="hidden" asp-for="Item1.SortOrder" name="SortOrder" />
</form>
To show the Info Message(for success delete), I created a PartialView to make the modal show if theres a data set in a Temporary Data or TempData. This was added under the _Layout.cshtml page:
_ModalScriptsInit.cshtml
#using Data.Utilities
#{
var text = TempData[Constants.Common.ModalMessage];
if (text != null && !text.Equals(string.Empty))
{
<script type="text/javascript">
showDefaultModal("#text");
</script>
}
}
So in my controller once successfully delete I will just set the TempData with its key as shown below:
Controller
[HttpPost]
public async Task<IActionResult> Delete(int id, RegionSearchViewModel searchViewModel)
{
try
{
var validationResult = await new RegionHandler(_regionService).CanDelete(id);
if (validationResult == null)
{
await _regionService.DeleteById(id);
TempData[Constants.Common.ModalMessage] = Constants.Message.RecordSuccessDelete;
return RedirectToAction(nameof(List), searchViewModel);
}
ModelState.AddModelError(validationResult);
}
catch (Exception ex)
{
var exceptionMessage = await Helpers.GetErrors(ex, _emailService);
ModelState.AddModelError(new ValidationResult(exceptionMessage));
}
ModelState.AddModelError(string.Empty, "Invalid delete attempt.");
return RedirectToAction(nameof(List), searchViewModel);
}
I am not sure yet if this is the best way so far. Please give suggestion on how to improve this code. Thanks!
I trying to create ImageBrowser in Asp.net MVC 5. Problem is when I try to switch to another picture.
Here's my code:
In View:
#model Katalog.Models.Model
#{
Model.enumerator = 0;
int count = Model.ImageList.Count;
int index = 1;
}
....
<table>
<tbody>
<tr>
<td> #index/#count </td>
....
</tr>
<tr>
#using (Html.BeginForm("previous", "Home",FormMethod.Post))
{
<td>
<input type="hidden" name="number" value="1" />
<input value="<" type="submit" onclick="ImageLeft()" class="buttonLeftRight"/>
</td>
}
<td>#{Html.RenderPartial("~/Views/Shared/ImageViews.cshtml", Model);}</td>
<td>
#using (Html.BeginForm("next", "Home", FormMethod.Post))
{
#Html.HiddenFor(a => a.ImageList)
#Html.HiddenFor(a => a.enumerator)
<input type="submit" class="buttonLeftRight" onclick="ImageRight()"/>
}
</td>
</tr>
</tbody>
</table>
....
<script>
function ImageRight()
{
#{ Model.enumerator++; }
}
</script>
My Controller
....
public ActionResult next(Katalog.Models.Model model)
{
model = MyModel;
return View("Searcher",model);
}
....
and my PartialView:
#model Katalog.Models.Model
<img id="foto" class="imgFinded" src="#Model.ImageList[#Model.enumerator]"/>
When I click Next button my model.ImageList is empty. Why?
The reason your models ImageList property is null is because your generating a hidden input #Html.HiddenFor(a => a.ImageList) which generates
<input name="ImageList" value="System.Collections.Generic.List[]String" .. />
which will not bind to your collection in the POST method (when something is not binding, always insect the name and value attribute of the form controls your generating.
In order to bind to that list you would need to generate an input for each item in the list using a loop.
The other issue is that your scripts does nothing at all. Your model is server side code, and you cannot increment the value of a model property using javascript - you need to send a request to the controller to do that.
Since you sending the collection of images to the view, there is no need to make a request back to the server - you can just update the src attribute of the <img> tag.
Change the model to
public class Model
{
public int InitialIndex { get; set; }
public int ImageCount { get { return ImageList.Count; } }
public List<string> ImageList { get; set; }
}
and then the view can be just (the partial is unnecessary)
<img id="foto" class="imgFinded" src="#Model.ImageList[#Model.InitialIndex ]"/>
<button type="button" id="previous">Previous</button>
<button type="button" id="next">Next</button>
and the scripts
var imagelist = #Html.Raw(Json.Encode(Model.ImageList));
var index = #Html.Raw(Json.Encode(Model.InitialIndex));
var max = #Html.Raw(Json.Encode(Model.ImageCount));
var image = $('#foto');
// Set the initial state of the buttons
if (index === 0) {
$('#previous').prop('disabled', true);
} else if (index === max) {
$('#previous').prop('disabled', true);
}
$('#next').click(function() {
$('#previous').prop('disabled', false);
index++;
image.attr('src', imagelist[index]);
if (index === max) {
$(this).prop('disabled', true);
}
})
$('#previous').click(function() {
$('#next').prop('disabled', false);
index--;
image.attr('src', imagelist[index]);
if (index === 0) {
$(this).prop('disabled', true);
}
})
The code #{Model.enumerator++;} and #{Model.enumerator--;} within the two Javascript functions is server side code so it will only be executed once when the view is rendering on the server and before it is passed to the client browser. So triggering the onclick="ImageRight()" by pressing the submit button will not change the server side value.
You could instead try to post the current index to the action in your controller and increment or decrement it depending on which action has been invoked.
#using (Html.BeginForm("Next", "Home", FormMethod.Post))
{
#Html.HiddenFor(a=>a.CurrentIndex)
<input type="submit" class="buttonRightLeft"/>
}
#using (Html.BeginForm("Previous", "Home", FormMethod.Post))
{
#Html.HiddenFor(a=>a.CurrentIndex)
<input type="submit" class="buttonLeftRight"/>
}
public ActionResult Next(int CurrentIndex)
{
// Get the NEXT image and return as model
model = MyModel;
return View("Searcher",model);
}
public ActionResult Previous(int CurrentIndex)
{
// Get the PREVIOUS image and return as model
model = MyModel;
return View("Searcher",model);
}
I have a view where I display a list of users, setting the model as:
#model List<MyProject.Models.User>
In this view I want to be able to choose to perform an action on a specific user, i.e. post to the controller that I want to disable a user. How do I post the specific User object to the controller?
This is what I've got so far, but I can't see how to post the specific object from the collection:
#foreach (var c in Model)
{
<tr>
<td>#c.Username</td>
<td>#c.IsEnabled</td>
<td>
#using (Html.BeginForm("DisableUser", "UserManagement"))
{
<input type="submit" value="Disable" class="btn btn-primary"/>
}
</td>
</tr>
}
My controller has the signature:
public ActionResult DisableUser(User user)
Rather than posting back all propeties of User, you can just add a route value in the BeginForm() method to post back the ID or the User. Assuming that property is namedUserId`, then
#foreach (var c in Model)
{
<tr>
....
<td>
#using (Html.BeginForm("DisableUser", "UserManagement", new { id = c.UserId ))
{
<input type="submit" value="Disable" class="btn btn-primary"/>
}
</td>
</tr>
}
and the controller method would be
public ActionResult DisableUser(int id)
{
// Get the User based on id, update it and redirect
}
You could also consider using ajax to submit the value, which would allow the user to stay on the same page and continue to 'disable' other User objects without need to make a redirect, in which case the code might be
#foreach (var c in Model)
{
<tr>
....
<td>
<button type="button" class="disable" data-id="#c.UserId">Disable</button>
</td>
</tr>
}
var url = '#Url.Action("DisableUser", "UserManagement")';
$('.disable').click(function() {
var row = $(this).closest('tr');
$.post(url, { id: $(this).data('id') }, function(result) {
if(result) {
// for example, remove the row from the table
row.remove();
} else {
// Oops
}
}).fail(function (result) {
// Oops
});
});
and the controller method would be
public JsonResult DisableUser(int id)
{
// Get the User based on id and update it
return Json(true);
// or if the update failed - return Json(null);
}
The simple way to disable a user is to use a Html.ActionLink instead of the form - you should be able to see plenty of examples of this in the template code. The action link could redirect to a confirmation page or you could just disable the user and redirect to a message page saying "the user has been disabled".
I better way is to use AJAX. You can do this with jQuery or you could use the MVC Ajax form or Ajax Action Link. I would recommend that you google MVC Ajax Action Link examples.
You may also want to style the link by setting it's class to the Bootstrap 'btn' class.
There is a way to post a single user
#foreach (var c in Model)
{
<tr>
<td>#c.Username</td>
<td>#c.IsEnabled</td>
<td>
#using (Html.BeginForm("DisableUser", "UserManagement"))
{
<input type="text" name="Username" value="#c.Username">
<input type="text" name="IsEnabled" value="#c.IsEnabled">
<input type="hidden" name="id" value="#c.id">
<input type="submit" value="Disable" class="btn btn-primary"/>
}
</td>
</tr>
}
The ideas is same,due to lack of time, please proceed according to your requirements, use the Class Property name as input name, the action will get the value
First of all you must not declare Html.BeginForm inside of any loop to post the object to controller.
#using (Html.BeginForm("DisableUser", "UserManagement"))
{
#foreach (var c in Model)
{
<tr>
<td>#c.Username</td>
<td>#c.IsEnabled</td>
<td>
<input data-id="#c.Id" type="submit" value="Disable" class="clsBtnPost btn btn-primary"/>
</td>
</tr>
}
}
This is for your reference
$(document).ready(function(){
$(".clsBtnPost").click(function(){
var userId = $(this).data("id");
$.ajax({
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: 'POST',
url: 'ControllName/MethodName', //Your Url
data: { 'userId': userId },
success: function () {
alert("successfully called.");
},
failure: function (response) {
alert("Error");
}
});
});
});
You can go with the Ajax Call to pass a single object to controller.
I want to generate table with, for example, 4 columns. In last column i need link to remove user whitch is in that row. When i am using form tag like this:
#foreach (var item in Model.Approvers)
{
<tr>
<td>#item.FullName</td>
<td>#item.Email</td>
<td>#item.AdAccount</td>
<td>
<form id="removeApproverRoleForm" action="~/Admin/RemoveRole" method="post">
#Html.AntiForgeryToken()
<input type="text" id="userId" name="userId" value="#item.Id" />
<input type="text" id="role" name="role" value="Approver" />
Remove
</form>
</td>
</tr>
}
It passes last value of userId and role to RemoveRole method. It have to be POST method so this whould not work:
#Html.ActionLink(Remove, "RemoveRole", "Admin", new { role = "Approver", userid = item.Id }, new { onclick = "return removeRole();" })
Even if i place form tag above that, the parameters are still visible in the link.
So i need somehow use new { role = "Approver", userid = item.Id } but send it as a POST and hide those values.
Any ideas?
Thank you for help!
It is a popular problem, so you can find detailed solution here
Short answer is:
use <input type="submit">Remove</input> inside the form
OR use
#Ajax.ActionLink("Remove, "RemoveRole", "Admin", new { role = "Approver", userid = item.Id }, new AjaxOptions { HttpMethod = "POST" })
to be able to create ActionLink with controlling the method parameter.
A Razor view has 3 buttons inside a form. All button's actions will need form values which are basically values coming input fields.
Every time I click any of buttons it redirected me to default action. Can you please guide how I can submit form to different actions based on button press ?
I really appreciate your time, guidance and help.
You could also try this:
<input type="submit" name="submitbutton1" value="submit1" />
<input type="submit" name="submitbutton2" value="submit2" />
Then in your default function you call the functions you want:
if( Request.Form["submitbutton1"] != null)
{
// Code for function 1
}
else if(Request.Form["submitButton2"] != null )
{
// code for function 2
}
This elegant solution works for number of submit buttons:
#Html.Begin()
{
// Html code here
<input type="submit" name="command" value="submit1" />
<input type="submit" name="command" value="submit2" />
}
And in your controllers' action method accept it as a parameter.
public ActionResult Create(Employee model, string command)
{
if(command.Equals("submit1"))
{
// Call action here...
}
else
{
// Call another action here...
}
}
in the view
<form action="/Controller_name/action" method="Post>
<input type="submit" name="btn1" value="Ok" />
<input type="submit" name="btn1" value="cancel" />
<input type="submit" name="btn1" value="Save" />
</form>
in the action
string str =Request.Params["btn1"];
if(str=="ok"){
}
if(str=="cancel"){
}
if(str=="save"){
}
You can use JS + Ajax.
For example, if you have any button you can say it what it must do on click event.
Here the code:
<input id="btnFilterData" type="button" value="myBtn">
Here your button in html:
in the script section, you need to use this code (This section should be at the end of the document):
<script type="text/javascript">
$('#btnFilterData').click(function () {
myFunc();
});
</script>
And finally, you need to add ajax function (In another script section, which should be placed at the begining of the document):
function myFunc() {
$.ajax({
type: "GET",
contentType: "application/json",
url: "/myController/myFuncOnController",
data: {
//params, which you can pass to yu func
},
success: function(result) {
error: function (errorData) {
}
});
};
This is what worked for me.
formaction="#Url.Action("Edit")"
Snippet :
<input type="submit" formaction="#Url.Action("Edit")" formmethod="post" value="Save" class="btn btn-primary" />
<input type="submit" formaction="#Url.Action("PartialEdit")" formmethod="post" value="Select Type" class="btn btn-primary" />
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit( Quote quote)
{
//code
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult PartialEdit(Quote quote)
{
//code
}
Might help some one who wants to have 2 different action methods instead of one method using selectors or using client scripts .
The cleanest solution I've found is as follows:
This example is to perform two very different actions; the basic premise is to use the value to pass data to the action.
In your view:
#using (Html.BeginForm("DliAction", "Dli", FormMethod.Post, new { id = "mainForm" }))
{
if (isOnDli)
{
<button name="removeDli" value="#result.WeNo">Remove From DLI</button>
}
else
{
<button name="performDli" value="#result.WeNo">Perform DLI</button>
}
}
Then in your action:
public ActionResult DliAction(string removeDli, string performDli)
{
if (string.IsNullOrEmpty(performDli))
{
...
}
else if (string.IsNullOrEmpty(removeDli))
{
...
}
return View();
}
This code should be easy to alter in order to achieve variations along the theme, e.g. change the button's name to be the same, then you only need one parameter on the action etc, as can be seen below:
In your view:
#using (Html.BeginForm("DliAction", "Dli", FormMethod.Post, new { id = "mainForm" }))
{
<button name="weNo" value="#result.WeNo">Process This WeNo</button>
<button name="weNo" value="#result.WeNo">Process A Different WeNo This Item</button>
}
Then in your action:
public ActionResult DliAction(string weNo)
{
// Process the weNo...
return View();
}
Try wrapping each button in it's own form in your view.
#using (Html.BeginForm("Action1", "Controller"))
{
<input type="submit" value="Button 1" />
}
#using (Html.BeginForm("Action2", "Controller"))
{
<input type="submit" value="Button 2" />
}
You could use normal buttons(non submit). Use javascript to rewrite (at an 'onclick' event) the form's 'action' attribute to something you want and then submit it. Generate the button using a custom helper(create a file "Helper.cshtml" inside the App_Code folder, at the root of your project) .
#helper SubmitButton(string text, string controller,string action)
{
var uh = new System.Web.Mvc.UrlHelper(Context.Request.RequestContext);
string url = #uh.Action(action, controller, null);
<input type=button onclick="(
function(e)
{
$(e).parent().attr('action', '#url'); //rewrite action url
//create a submit button to be clicked and removed, so that onsubmit is triggered
var form = document.getElementById($(e).parent().attr('id'));
var button = form.ownerDocument.createElement('input');
button.style.display = 'none';
button.type = 'submit';
form.appendChild(button).click();
form.removeChild(button);
}
)(this)" value="#text"/>
}
And then use it as:
#Helpers.SubmitButton("Text for 1st button","ControllerForButton1","ActionForButton1")
#Helpers.SubmitButton("Text for 2nd button","ControllerForButton2","ActionForButton2")
...
Inside your form.
Simplest way is to use the html5 FormAction and FormMethod
<input type="submit"
formaction="Save"
formmethod="post"
value="Save" />
<input type="submit"
formaction="SaveForLatter"
formmethod="post"
value="Save For Latter" />
<input type="submit"
formaction="SaveAndPublish"
formmethod="post"
value="Save And Publish" />
[HttpPost]
public ActionResult Save(CustomerViewModel model) {...}
[HttpPost]
public ActionResult SaveForLatter(CustomerViewModel model){...}
[HttpPost]
public ActionResult SaveAndPublish(CustomerViewModel model){...}
There are many other ways which we can use, see this article ASP.Net MVC multiple submit button use in different ways
As well as #Pablo's answer, for newer versions you can also use the asp-page-handler tag helper.
In the page:
<button asp-page-handler="Action1" type="submit">Action 1</button>
<button asp-page-handler="Action2" type="submit">Action 2</button>
then in the controller:
public async Task OnPostAction1Async() {...}
public async Task OnPostAction2Async() {...}
Didn't see an answer using tag helpers (Core MVC), so here it goes (for a delete action):
On HTML:
<form action="" method="post" role="form">
<table>
#for (var i = 0; i < Model.List.Count(); i++)
{
<tr>
<td>#Model.List[i].ItemDescription</td>
<td>
<input type="submit" value="REMOVE" class="btn btn-xs btn-danger"
asp-controller="ControllerName" asp-action="delete" asp-route-idForDeleteItem="#Model.List[i].idForDeleteItem" />
</td>
</tr>
}
</table>
</form>
On Controller:
[HttpPost("[action]/{idForDeleteItem}"), ActionName("Delete")]
public async Task<IActionResult> DeleteConfirmed(long idForDeleteItem)
{
///delete with param id goes here
}
Don't forget to use [Route("[controller]")] BEFORE the class declaration - on controller.
Information acquired from:
http://www.codedigest.com/posts/46/multiple-submit-button-in-a-single-form-in-aspnet-mvc
For you chaps coming more recently, you can use the HTML 5 Formaction Attribute.
In your <input> or <button>
Just define:
<button id="btnPatientSubmit" type="submit" class="btn btn-labeled btn-success" formaction="Edit" formmethod="post">
Notice the addition of formation= "Edit", this specifies which ActionResult I want to submit to in my controller.
This will allow you to have multiple submit buttons, where each could submit to independent ActionResults (Methods) in your controller.
This answer will show you that how to work in asp.net with razor, and to control multiple submit button event. Lets for example we have two button, one button will redirect us to "PageA.cshtml" and other will redirect us to "PageB.cshtml".
#{
if (IsPost)
{
if(Request["btn"].Equals("button_A"))
{
Response.Redirect("PageA.cshtml");
}
if(Request["btn"].Equals("button_B"))
{
Response.Redirect("PageB.cshtml");
}
}
}
<form method="post">
<input type="submit" value="button_A" name="btn"/>;
<input type="submit" value="button_B" name="btn"/>;
</form>
In case you're using pure razor, i.e. no MVC controller:
<button name="SubmitForm" value="Hello">Hello</button>
<button name="SubmitForm" value="World">World</button>
#if (IsPost)
{
<p>#Request.Form["SubmitForm"]</p>
}
Clicking each of the buttons should render out Hello and World.