I feel this may be an easy fix but I cannot seem to get around it. I have an ASP.NET Core web application and I'm using an ajax form to submit data to my controller for processing. The problem I have is that my checkboxes always pass in as "false" even though they may be checked.
I searched for some answers but nothing I've tried has worked. Things like using the checked property, ensuring the name is correct.
Can anyone shed some light on why the values are ignored when the form is submitted to the controller and how I can fix it?
Form
<form asp-action="CreateCustomView" asp-controller="Data"
data-ajax="true"
data-ajax-method="POST">
<div class="row">
<div class="col">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="ColName" name="ColName" checked>
<label class="custom-control-label" for="ColName">Name</label>
</div>
</div>
<button type="reset">Reset</button>
<button type="submit">Save changes</button>
</form>
Model
namespace MyProject.Data
{
public class GridView : BaseEntity
{
public string Name { get; set; }
public bool ColName { get; set; }
}
}
DataController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MyProject.Data;
using Microsoft.AspNetCore.Mvc;
namespace MyProject.UI.Controllers
{
public class DataController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult CreateCustomView(GridView data)
{
//This method is incomplete, there is a break at the ActionResult to see what values are passed into `data`. In production, the values would be handled and the changes would be saved.
return View();
}
}
}
I have a breakpoint on the method CreateCustomView to see what values are passed, no matter what checkboxes I check, they are always being passed as false.
Can anyone help with this rather strange problem?
Update
As per the answer supplied by #Reyan-Chougle, if you're using CORE you need to supply the input as follows:
<input asp-for="#Model.ColType" type="checkbox" />
When the page is rendered, the control is automatically given a hidden field. Here is what the HTML of the above control renders as:
<input type="checkbox" class="custom-control-input" id="ColType" value="true" data-val="true" data-val-required="The ColType field is required." name="ColType">
<input type="hidden" value="false" id="ColType" name="ColType">
As you can see it creates a hidden checkbox with a value of false. This means that, as a boolean type it always has a value of true or false on submission.
As you are using ASP.NET Core, it is recommend to use the Tag Helpers:
<div class="form-group">
<label asp-for="#Model.ColName"></label>
<input asp-for="#Model.ColName" type="checkbox" />
</div>
If not using asp-for attribute , you can modify your codes to add a hidden field. It will be submitted regardless whether the checkbox is checked or not. If the checkbox is checked, the posted value will be true,false. The model binder will correctly extract true from the value. Otherwise it will be false :
<input type="checkbox" class="custom-control-input" data-val="true" id="ColName" name="ColName" value="true" checked>
<label class="custom-control-label" for="ColName">Name</label>
<input name="ColName" type="hidden" value="false">
I ran into a similar issue. There is a form we have that contains many fields that include textboxes, select (dropdown) menus, checkboxes and of course labels. All fields save to the database properly EXCEPT for the three checkbox options we have. I just figured out the fix after fooling with it off and on for weeks. I hope this helps someone:
This is what the code used to look like:
$(this).attr('data-val', 'true');
This is what fixed the problem:
$(this).val(true);
Here is the whole function that includes the fix:
$('form').on('change', ':checkbox', function () {
if (this.checked) {
$(this).val(true);
}
else {
$(this).val(false);
}
});
try to use
#Html.CheckBox("ColName", true)
I have a list In my view. For each row, I view button and I am passing Id value as hidden. But when I click any button it is passing wrong hidden value to the controller. Always it passes the first-row hidden value to the controller.
View:
#foreach (var list in Model)
{
<div>
<div > #( ((int)1) + #Model.IndexOf(list)).</div>
<div >#list.details</div>
<div class="col-md-2 row-index">
<button class="btn btn-link" type="submit" name="action:view" id="view">View</button>
<input type="hidden" name="viewId" id="viewId" value="list.WId" />
</div>
</div>
}
Controller:
[HttpPost]
[MultipleButton(Name = "action", Argument = "view")]
public ActionResult ViewDetail(string viewId)
{
return RedirectToAction("ViewDetails");
}
To get all values you need to change the input value type in your controller to array of strings.
I hope that this solution can help you
[HttpPost]
[MultipleButton(Name = "action", Argument = "view")]
public ActionResult ViewDetail(string[] viewId)
{
return RedirectToAction("ViewDetails");
}
if you want to get the exact value you need to duplicate the form within your foreach
in this case you should write somthing like this :
#foreach (var list in Model)
{
<div>
<div > #( ((int)1) + #Model.IndexOf(list)).</div>
<div >#list.details</div>
<div class="col-md-2 row-index">
<form ... > // complete your form attributes
<button class="btn btn-link" type="submit" name="action:view" id="view">View</button>
<input type="hidden" name="viewId" id="viewId" value="list.WId" />
</form>
</div>
</div>
}
Note : You should delete the global form
You should have one form for each row. then you submit that row.
Otherwise as you state it passes first value.
You are setting each value to the same element ID (which is invalid anyway) and name. When you submit your form (which would be more helpful to fully answer your question) it is finding the first element that matches that criteria and submitting it.
There are multiple ways to resolve this such as the already mentioned form per entry but the other preference would be to modify you button to a div and add a click handler to pass the specific value to a js function which would then submit to the controller. Its a preference choice regarding how tightly coupled you want your front end. But the main problem is your element naming convention.
I want to send POST request to AdminController. But when i watch it in debugger, the request is GET.
<form method="post">
<input type="button" formmethod="post" onclick="location.href='#Url.Action("Index","Admin",new {rowID = #p.ProductID})'" value="Delete"/>
</form>
Because you wrote code to do a GET request on the submit button click !
onclick="location.href='#Url.Action("Index","Admin",new {rowID =
#p.ProductID})'"
Here you are setting the location.href value to the /Admin/Index and it will be a new GET request.
If you want to post, simply remove the onclick event on the button. If you want to send the ProductID value, you can keep that in a hidden input field inside your form and when you click submit the value of this form element will be also submitted.
#using(Html.BeginForm("Index","Admin"))
{
<input type="hidden" name="rowID" value="#p.ProductID" />
<input type="submit" value="Delete"/>
}
Assuming your HttpPost Index action method of AdminController has a parameter with same name as the input name to accept the productId.
[HttpPost]
public ActionResult Index(int rowID)
{
// to do : Return something
}
In a Asp.net MVC view, i created a form, with a input field.
The user Sets a first name (or part of it), presses the submit button.
This is the form section:
<div>
<form action="SearchCustomer" methos="post">
Enter first name: <input id="Text1" name="txtFirstName" type="text" />
<br />
<input id="Submit1" type="submit" value="Search Customer" />
</form>
</div>
This is the SearchCustomer in the Controller, that gets the data from the form:
CustomerDal dal = new CustomerDal();
string searchValue = Request.Form["txtFirstName"].ToString();
List<Customer> customers = (from x in dal.Customers
where x.FirstName.Contains(searchValue)
select x).ToList<Customer>();
CustomerModelView customerModelView = new CustomerModelView();
customerModelView.Customers = customers;
return View("ShowSearch", customerModelView);
When i run the program, and enter a first name ("Jhon" for example), the code returns to SearchCustomer function, but Request.Form is empty.
Why?
Thanks.
Your method is spelled wrongly should not read methos but method like below:
<form action="SearchCustomer" method="post">
....
</form>
You need to modify your code:
you need to provide a action name here, which should be defined in your controller(SearchController) with the same name as 'ActionName' you will put in the below code.
if SearchController is your action name then provide the controller in which the action is available.
<div>
<form action="SearchCustomer/<ActionName>" method="post">
Enter first name: <input id="Text1" name="txtFirstName" type="text" />
<br />
<input id="Submit1" type="submit" value="Search Customer" />
</form>
</div>
With Html.BeginForm :
#using (Html.BeginForm("<ActionName>","<ControllerName>", FormMethod.Post))
{
Enter first name: <input id="Text1" name="txtFirstName" type="text" />
<br />
<input id="Submit1" type="submit" value="Search Customer" />
}
Set [HttpPost] on your controller.
[HttpPost]
public ActionResult SearchFunction(string txtFirstName)
{
CustomerDal dal = new CustomerDal();
string searchValue = txtFirstName;
List<Customer> customers = (from x in dal.Customers
where x.FirstName.Contains(searchValue)
select x).ToList<Customer>();
CustomerModelView customerModelView = new CustomerModelView();
customerModelView.Customers = customers;
return View("ShowSearch", customerModelView);
}
If you View is the same name as your ActionResult method, try this:
#using(Html.BeginForm())
{
... enter code
}
By default, it'll already be a POST method type and it'll be directed to the ActionResult. One thing to make sure of: You will need the [HttpPost] attribute on your ActionResult method so the form knows where to go:
[HttpPost]
public ActionResult SearchCustomer (FormCollection form)
{
// Pull from the form collection
string searchCriteria = Convert.ToString(form["txtFirstName"]);
// Or pull directly from the HttpRequest
string searchCriteria = Convert.ToString(Request["txtFirstName"]);
.. continue code
}
I hope this helps!
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.