I have a basic form for which I want to handle buttons inside the form by calling the ActionResult method in the View's associated Controller class. Here is the following HTML5 code for the form:
<h2>Welcome</h2>
<div>
<h3>Login</h3>
<form method="post" action= <!-- what goes here --> >
Username: <input type="text" name="username" /> <br />
Password: <input type="text" name="password" /> <br />
<input type="submit" value="Login">
<input type="submit" value="Create Account"/>
</form>
</div>
<!-- more code ... -->
The corresponding Controller code is the following:
[HttpPost]
public ActionResult MyAction(string input, FormCollection collection)
{
switch (input)
{
case "Login":
// do some stuff...
break;
case "Create Account"
// do some other stuff...
break;
}
return View();
}
you make the use of the HTML Helper and have
#using(Html.BeginForm())
{
Username: <input type="text" name="username" /> <br />
Password: <input type="text" name="password" /> <br />
<input type="submit" value="Login">
<input type="submit" value="Create Account"/>
}
or use the Url helper
<form method="post" action="#Url.Action("MyAction", "MyController")" >
Html.BeginForm has several (13) overrides where you can specify more information, for example, a normal use when uploading files is using:
#using(Html.BeginForm("myaction", "mycontroller", FormMethod.Post, new {enctype = "multipart/form-data"}))
{
< ... >
}
If you don't specify any arguments, the Html.BeginForm() will create a POST form that points to your current controller and current action. As an example, let's say you have a controller called Posts and an action called Delete
public ActionResult Delete(int id)
{
var model = db.GetPostById(id);
return View(model);
}
[HttpPost]
public ActionResult Delete(int id)
{
var model = db.GetPostById(id);
if(model != null)
db.DeletePost(id);
return RedirectToView("Index");
}
and your html page would be something like:
<h2>Are you sure you want to delete?</h2>
<p>The Post named <strong>#Model.Title</strong> will be deleted.</p>
#using(Html.BeginForm())
{
<input type="submit" class="btn btn-danger" value="Delete Post"/>
<text>or</text>
#Url.ActionLink("go to list", "Index")
}
Here I'm basically wrapping a button in a link. The advantage is that you can post to different action methods in the same form.
<a href="Controller/ActionMethod">
<input type="button" value="Click Me" />
</a>
Adding parameters:
<a href="Controller/ActionMethod?userName=ted">
<input type="button" value="Click Me" />
</a>
Adding parameters from a non-enumerated Model:
<a href="Controller/ActionMethod?userName=#Model.UserName">
<input type="button" value="Click Me" />
</a>
You can do the same for an enumerated Model too. You would just have to reference a single entity first. Happy Coding!
I want to call the same class from different buttons. Here is what I am doing:
<div class="buttondiv">
#using (Html.BeginForm("TankList","Forms", FormMethod.Post))
{
<input class="allformsbutton" type="submit" value="ASME Basic Form" id="buttonAsmeBasic" />
}
</div>
<div class="buttondiv">
#using (Html.BeginForm("TankList", "Forms", FormMethod.Post))
{
<input class="allformsbutton" type="submit" value="ASME Detailed Form" id="buttonAsmeDetailed" />
}
</div>
I want to pass to the class that I'm calling "TankList" which button was clicked.
How would I capture that in the class?
EDIT
I wanted to clarify. The point of the buttons is to uniquely identify which button was pressed. So, I want to pass to the TankList the value "ASME Basic Form" if the ASME Basic button was pressed or pass "ASME Detailed Form" if the ASME Detailed button was pressed.
your .cshtml-file:
<div class="buttondiv">
#using (Html.BeginForm("TankList","Home", FormMethod.Post))
{
<input name="theClass" class="allformsbutton" type="submit" value="ASME Basic Form" id="buttonAsmeBasic" />
}
</div>
<div class="buttondiv">
#using (Html.BeginForm("TankList", "Home", FormMethod.Post))
{
<input name="theClass" class="allformsbutton" type="submit" value="ASME Detailed Form" id="buttonAsmeDetailed" />
}
</div>
your FormsController.cs
public class FormsController : Controller
{
[HttpPost]
public void TankList(string theClass)
{
}
}
When you post the form the result in the controller is as follows depending on the button you clicked:
I am currently working on a basic To Do List on ASP.NET CORE. I have a button on top of the To-Do list to says "Add Task" upon clicking on the button you'll be re-directed to a Create Task Form. At the moment when click on the Add Task button to be re-directed to the form I am getting a localhost not found error. The URL is correct as it says http://localhost:51797/Todo/Create but my .cshtml page does not appear. I'm new to ASP.Net so apologies if the reason is obvious but I have gone through my code and I cant seem to find why this is happening.
[HttpPost]
[ActionName("Create")]
public ActionResult Create(int? id, string newText)
{
int i = id ?? 0;
TodoListItem toDo = _todoListService.GetList(i);
toDo.Text = newText; //Set new text
_todoListService.WriteToFile(toDo);
return RedirectToAction("Index");
}
}
This is my Create.cshtml page
#model TodoListItem
#{
ViewData["Title"] = "Create";
}
<h2>Add Task</h2>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Text" class="control-label"></label>
<input asp-for="Text" class="form-control" name="newText" />
<span asp-validation-for="Text" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Submit" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
app.UseMvc(routes =>
routes.MapRoute(
name: "create",
template: "{controller=Todo}/{action=Create}");
});
You need an HTTPGET attribute for the GET action, which should return the create view with an empty model.
public IActionResult Create()
{
return View(new TodoListItem());
}
So when you click on Add Task, it will execute this action method and returns the create view.
i have a form in html and i want to submit it to a controler
what i have tried
#using (Html.BeginForm("RegisterApartmentOwner", "Home", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
<p>
<label>First Name</label>
<input type="text" placeholder="Enter your first Name" name="firstName" />
<span class="errorMessage"></span>
</p>
<p>
<label>Last Name</label>
<input type="text" placeholder="Enter your last Name" />
<span class="errorMessage"></span>
</p>
<p>
<label>Password</label>
<input type="text" placeholder="Enter your password" name="Password"/>
<span class="errorMessage"></span>
</p>
<p>
<label>Password Again</label>
<input type="text" placeholder="Enter your password again" name="Password2"/>
<span class="errorMessage"></span>
</p>
<p>
<label>Mobile Number</label>
<input type="text" placeholder="Enter your mobile number" />
<span class="errorMessage"></span>
</p>
<p>
<input type="submit" value="Register" class="submit"/>
</p>
}
</div>
and in the controller i receive the submit in this function
public String RegisterTenant() {
return "done";
}
i can see the done message, however, i want to receive the values of the input that i used in the form, how please?
i just to know what to receive the form in the controller
You could accept the formcollection (as in: FormCollection collection) as a parameter in your post action, or, better yet, create a view model, send that to the view and post it to the controller. You'd have to set it as a parameter of your http post action course.
Example:
[HttpPost]
public String RegisterTenant(FormCollection collection) {
// give all your html elements you want to read values out of an Id, like 'Password'
var password = collection["Password"];
// do something with your data
return "done";
}
Or (better!):
View model:
public class HomeViewModel
{
[Required]
public string UserName {get;set;}
}
View (on top):
#model Namespace.HomeViewModel
View (in your form):
#Html.TextBoxFor(m => m.UserName)
Controller:
[HttpPost]
public String RegisterTenant(HomeViewModel model)
{
var userName = model.UserName;
// do something
}
But you should really do some investigation into MVC: Views, Models & Controllers and what they do. It is really better to create a typesafe view model and work with that.
Consider the following markup:
<h2>Edit SAS Program</h2>
#using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post))
{
<label for="Name">Name</label>
#Html.TextBoxFor(model => model.Name)
using (Html.BeginForm("Delete", "SasProgram", FormMethod.Post))
{
<input type="submit" class="button" value="Delete" />
}
<input type="submit" class="button" value="Save Changes" />
}
I'd like to have the Delete button on the same view as the Edit. However, it's not letting me have nested forms. What is the appropriate way to handle this situation?
I tried leveraging this answer, How to handle nested forms in ASP.NET MVC, but it's a broken link now.
I would use different values for button name in the same form:
#using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post))
{
<label for="Name">Name</label>
#Html.TextBoxFor(model => model.Name)
<button name="action" value="delete">Delete</button>
<button name="action" value="save">Save Changes</button>
}
and then switch in controller:
[HttpPost]
public ActionResult Edit( SomeModel model, string action )
{
switch( action ) {
case "delete":
// delete action
break;
case "save":
// save action
break;
}
}
The code is written from memory but it works in production. Note that buttons are of default type - submit.
The best and easiest way would be to use two forms but don't nest them:
<h2>Edit SAS Program</h2>
#using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post))
{
<label for="Name">Name</label>
#Html.TextBoxFor(model => model.Name)
<input type="submit" class="button" value="Save Changes" />
}
#using (Html.BeginForm("Delete", "SasProgram", FormMethod.Post))
{
<input type="submit" class="button" value="Delete" />
}
This way you have:
Two separate forms
No GET requests
The delete button below the edit button, which makes more sense when you're on a view that allows you to edit something.
First of all. Every modification request should be use the post method.
I make some R&D and build the basics of a multi submit button handler in a wiki A clean solution to use multiple submit button in ASP.NET MVC.
I think it could solve your problem.
First, you cannot nest <form> element. The specification doesn't allow it. Since you are using the MVC pattern I have two options that came to my mind:
You can retain the save button as the submit button of the form, and make the delete button a HTML link. Then the delete button will target to a different route, it could be something like: GET /program/delete/{id}.
You can have two buttons inside the same form, then with JavaScript after clicking one of the buttons you will change the action attribute of the form.
Update
There is a third option, that is more clean: using two submit buttons with same name attribute and different values.
Your form will have two buttons:
public ActionResult MyAction(string submitButton) {
switch (submitButton) {
case "save":
// ...
case "delete":
// ...
}
}
For more details check this answer: https://stackoverflow.com/a/443047/439427
You can also use html 5 feature to target a form from an input button. Below I have created both a delete and save form and have the submit buttons outside of the forms but targeting them via the form attribute.
I think most browsers support this except IE.
No javascript required.
#using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post, new { id = "editForm" }))
{
<label for="Name">Name</label>
#Html.TextBoxFor(model => model.Name)
}
#using (Html.BeginForm("Delete", "SasProgram", FormMethod.Post, new { id = "deleteForm" }))
{
<input type="submit" class="button" value="Delete" />
}
<input type="submit" class="button" value="Save" form="editForm"/>
<input type="submit" class="button" value="Delete" form="deleteForm" />
This allows for a nice button layout without any fancy javascript or css styling.
The OLD way to do this but still applicable is to have one form tag and change the action with multiple submit buttons.
<input class="btn btn-default" type="submit" value="Save" />
<input class="btn btn-default" type="submit" value="Delete" onclick="this.form.action='/SasProgram/delete/#Model.Id';" />
Edit : Here's how to do it with ajax using an HttpPost.
//
// POST: /Divisions/Delete
[HttpPost, ActionName("Delete"), Authorize]
public ActionResult DeleteConfirmed(int id)
{
Division division = _db.Divisions.Single(x => x.DivisionId == id);
string errorMessage;
if (DbRelationEnforcer.CanDelete(_db, division, out errorMessage))
{
division.SetDeleted(User.Identity.Name);
_db.SaveChanges();
return Json(new JsonResponseCreatePartial { Success = true }, JsonRequestBehavior.AllowGet);
}
return Json(new JsonResponseCreatePartial { Success = false, Message = errorMessage }, JsonRequestBehavior.AllowGet);
}
Then, on the view, you must use the <input type="submit">Save changes</input> to save your changes (within the form), and a simple link/button to delete, like this:
<h2>Edit SAS Program</h2>
#using (Html.BeginForm("Edit", "SasProgram", FormMethod.Post))
{
<label for="Name">Name</label>
#Html.TextBoxFor(model => model.Name)
<input id='delete-btn' type="button" class="button" value="Delete" />
<input type="submit" class="button" value="Save Changes" />
}
Finally, you have to use JS to post to your action from the view, when the user clicks on Delete.
<script type='text/javascript'>
$(function() {
$("input#delete-btn").click(function(){
$.post('#Url.Action("Delete")', '#Model.Id', function(data) {
if(data.Success) {
' ... handle the success case
} else {
' ... error management
}
});
});
});
</script>
This will work, but in order to have a better UX, it would be preferable to have the Delete button from the Index/list view, and using a JQuery UI dialog to confirm before doing the ajax post. This will skip having to load the Edit page if/when you want to delete multiple items one after the other.