this is my controller:
public ActionResult Create() {
Number newNumber = new Number();
return View(newNumber);
}
and View :
#model PhoneBook.Models.Number
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="../../Scripts/jQuery.AddNewNumber.js" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Contact.Id)
<fieldset>
<legend>Number</legend>
<div class="TargetElements">
<div class="editor-label">
#Html.LabelFor(model => model.PhoneNumber)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PhoneNumber)
#Html.ValidationMessageFor(model => model.PhoneNumber)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.NumberKind)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.NumberKind.Title, NumberKinds)
</div>
</div>
<p>
<input class="AddNew" value="Add New" type="button" /></p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
By press AddNew button (use jQuery AddNewNumber.js) new input+DropDown Added to form in client side. But there is a problem in retrieve values, When I have one entry element(include input+DropDown) I can retrieve values like the following in post of my controller:
[HttpPost]
public ActionResult Create(Number NewNumber, FormCollection collection) {
db.Numbers.Add(NewNumber);
db.SaveChanges();
return RedirectToAction("Index")
}
But when there is multi-entry how can I retrieve values and add them to DataBase?
Use by the name of element like this:
string[] PhoneNumbers = collection.GetValues("PhoneNumber");
You want all of your input elements to have the same name. Then in your POST action method, the parameter would be List. Here is an example:
Model Binding to a List of objects
Related
I want to retrieve data from a view, it should work like this:
User fill a form available on the webpage
User clicks SEARCH button
Some function(s) collect the data and display them in another view
I tried all the basic tutorials and tips on others stackoverflow question but it still doesn't work. I don't know what I'm doing wrong...
Here's my code from the view:
section id="roomSearch">
<div class="banner">
<div class="banner-info">
<div class="container">
<div class="details-1">
#using (Html.BeginForm("UploadRoomSearchData", "HomeController", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="col-md-10 dropdown-buttons">
<div class="col-md-3 dropdown-button">
#Html.AntiForgeryToken()
<div class="input-group">
#Html.TextBoxFor(m => m.YourName, new { #class = "form-control has-dark-background", #placeholder = "Imię" })
#Html.ValidationMessageFor(m => m.YourName, "", new { #class = "text-danger" })
<!--<input class="form-control has-dark-background"
name="slider-name" id="slider-name" placeholder="Imię" type="text" required="">-->
</div>
</div>
<!---strat-date-piker---->
<link rel="stylesheet" href="~/Content/jquery-ui.css" />
<script src="~/Scripts/jquery-ui.js"></script>
<script>
$(function () {
$("#datepicker,#datepicker1").datepicker();
});
</script>
<!---/End-date-piker---->
<div class="col-md-3 dropdown-button">
<div class="book_date">
<form>
<input class="date" id="datepicker" type="text" value="Przyjazd" onfocus="this.value = '';" onblur="if (this.value == '') {this.value = 'Przyjazd';}">
<!-- #Html.TextBoxFor(m => m.CheckIn, new { #class = "date" })
#Html.ValidationMessageFor(m => m.CheckIn, "", new { #class = "datefield" })-->
</form>
</div>
</div>
<div class="col-md-3 dropdown-button">
<div class="book_date">
<form>
<input class="date1" id="datepicker1" type="text" value="Wyjazd" onfocus="this.value = '';" onblur="if (this.value == '') {this.value = 'Wyjazd';}">
<!--#Html.TextBoxFor(m => m.CheckOut, new { #class = "date1" })
#Html.ValidationMessageFor(m => m.CheckOut, "", new { #class = "datefield" })-->
</form>
</div>
</div>
<div class="col-md-3 dropdown-button">
<div class="section_1">
<select id="country" onchange="change_country(this.value)" class="frm-field required">
<option value="null">Dwuosobowy</option>
<option value="null">Jednoosobowy</option>
<option value="AX">Apartament</option>
<option value="AX">Gościnny</option>
</select>
</div>
</div>
<div class="clearfix"> </div>
</div>
<div class="col-md-2 submit_button">
<form >
<input type="submit" value="SZUKAJ">
<!-- <p> #Html.ActionLink("SZUKAJ", "Book1", "Home")</p>-->
</form>
</div>}
And here's my code in the controller. For now I try to retrieve only a name, to see if it's working.
[HttpPost]
public ActionResult UploadRoomSearchData(FormCollection form)
{
string name = Request["YourName"].ToString();
StringBuilder sbRoom = new StringBuilder();
sbRoom.Append("<b>Amount :</b> " + name + "<br/>");
//return RedirectToAction("Book1");
return Content(sbRoom.ToString());
}
I also tried something like this:
foreach(var v in form)
{
Write.Response("name:" + v);
}
I tried your code and it seems to work.
First I have the controller method to display the form
public ActionResult CreatePerson()
{
Person model = new Person();
return View(model);
}
Then the form:
#model RetrieveDataFromaView.Models.Person
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Person</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.YourName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.YourName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.YourName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="submit" class="btn btn-default" />
</div>
</div>
</div>
}
Which does a post to the controller method
[HttpPost]
public ActionResult CreatePerson(FormCollection formCollection)
{
string name = Request["YourName"].ToString();
StringBuilder sbRoom = new StringBuilder();
sbRoom.Append("<b>Amount :</b> " + name + "<br/>");
return Content(sbRoom.ToString());
}
This returns a view with only the content of the StringBuilder.
Maybe you are looking for RedirectToAction?
Hello you have this line inside the form:
#Html.AntiForgeryToken()
You can remove it or add the corresponding attribute to use it:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreatePerson(FormCollection formCollection)
{
///Your code here
}
Basically this is a token generated for the server to avoid requests from forms not generated by the server.
You have many ways of retrieving data from a form Post in ASP.NET MVC.
Using a Model
Usually, forms are created by specifying a Model type in the Razor view. You can use that type to retrieve the data. ASP.NET MVC will parse the body and populate the object in parameter for you.
Ex:
Controller:
public class HomeController: Controller
{
[HttpGet]
public ActionResult Index()
{
return View(new Person());
}
[HttpPost]
public ActionResult Index(Person p)
{
//Just for the sake of this example.
return Json(p);
}
}
Razor view
#model WebApplication2.Models.Person
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
<div>
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div>
#Html.LabelFor(m => m.FirstName): <br/>
#Html.TextBoxFor(m => m.FirstName)
</div>
<div>
#Html.LabelFor(m => m.LastName): <br/>
#Html.TextBoxFor(m => m.LastName)
</div>
<input type="submit" value="Submit" />
}
</div>
</body>
</html>
Using a FormsCollection
The FormsCollection object allows you to access the raw values of a form. It acts as a Dictionary for the Forms value. This is useful, especially when you have a dynamic model to parse, or if you just plain don't know about the Model type.
It's also pretty straightforward to use.
[HttpPost]
public ActionResult Index(FormCollection form)
{
var dict = form.AllKeys.ToDictionary(key => key, key => form[key]);
return Json(dict);
}
PS: I saw you are using Request[key]. It may just be me, but this call just looks like Dark magic, where you get data from who knows where (it uses the Query String, the cookies, the Request body, etc. It seems like it could be really problematic in some cases in the future. I much prefer knowing exactly where the data comes from. But that may just be me.
Conclusion
In conclusion, use the Model approach if you know exactly what should be in the Form. Use the FormCollection approach if you really need to. That's pretty much it.
Good luck.
This is my controller code. I have one view and inside that i have one partial view. At the end in partial view i have one submit button. When i click this button i want to save data of main view and partial view to thier respective tables.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication2.Models;
using System.Data.Entity.Validation;
namespace MvcApplication2.Controllers
{
public class HomePageController : Controller
{
//
// GET: /HomePage/
MVCDemoEntities db = new MVCDemoEntities();
public ActionResult Submit()
{
List<DocTypeMaster> alldoclist = new List<DocTypeMaster>();
using (MVCDemoEntities db = new MVCDemoEntities())
{
alldoclist = db.DocTypeMasters.OrderBy(a => a.DocTypeName).ToList();
}
ViewBag.docid = new SelectList(alldoclist, "Id", "DocTypeName");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Submit(DetailsEntry de)
{
List<DocTypeMaster> alldoclist = new List<DocTypeMaster>();
using (MVCDemoEntities db = new MVCDemoEntities())
{
alldoclist = db.DocTypeMasters.OrderBy(a => a.DocTypeName).ToList();
}
ViewBag.docid = new SelectList(alldoclist, "Id", "DocTypeName", de.DocumentId);
return View(de);
}
[HttpGet]
public PartialViewResult RacersByCountryPartial(string id)
{
Passport ps = new Passport();
Pan pn = new Pan();
string id1 = id.Trim();
if (id1 == "Passport")
return PartialView("~/Views/HomePage/id1.cshtml", ps);
else
return PartialView("~/Views/HomePage/pancard.cshtml", pn);
}
[HttpPost]
public ActionResult RacersByCountryPartial(string id,Passport ps, Pan pn,DetailsEntry dt)
{
return View(id);
}
}
}
this is my Mainview.
#model MvcApplication2.DetailsEntry
#{
ViewBag.Title = "Submit";
}
<h2>Submit</h2>
#using (Html.BeginForm("Submit", "HomePage", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>DetailsEntry</legend>
<div class="editor-label">
#Html.LabelFor(model => model.ClientId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ClientId)
#Html.ValidationMessageFor(model => model.ClientId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ClientName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ClientName)
#Html.ValidationMessageFor(model => model.ClientName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.EmployeeId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.EmployeeId)
#Html.ValidationMessageFor(model => model.EmployeeId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.EmpCitizenId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.EmpCitizenId)
#Html.ValidationMessageFor(model => model.EmpCitizenId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.EmpName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.EmpName)
#Html.ValidationMessageFor(model => model.EmpName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Nationality)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Nationality)
#Html.ValidationMessageFor(model => model.Nationality)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DocumentId)
</div>
<div class="editor-field">
#Html.DropDownListFor(Model => Model.DocumentId, #ViewBag.docid as SelectList,"Select document Type")
#Html.ValidationMessageFor(Model=>Model.DocumentId)
</div>
</fieldset>
}
<div id="container"> </div>
<script src="http://code.jquery.com/jquery-1.9.1.js" type="text/javascript"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.2.js"></script>
<script src="//code.jquery.com/jquery-1.11.2.min.js" type="text/javascript"></script>
<script type="text/javascript" src="scripts/jquery-1.8.2.js"></script>
<script src="~/Scripts/jquery-1.7.1.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#DocumentId").change(function () {
$("#log").ajaxError(function (event, jqxhr, settings, exception) {
alert(exception);
});
var countrySelected = $("select option:selected").first().text();
$.get('#Url.Action("RacersByCountryPartial")',
{ id: countrySelected }, function (data) {
$("#container").html(data);
});
});
});
</script>
This is my partial view.
#model MvcApplication2.Passport
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Passport</legend>
<div class="editor-label">
#Html.LabelFor(model => model.pissueddate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.pissueddate)
#Html.ValidationMessageFor(model => model.pissueddate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.pissuedlocation)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.pissuedlocation)
#Html.ValidationMessageFor(model => model.pissuedlocation)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.pimage)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.pimage)
#Html.ValidationMessageFor(model => model.pimage)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
There is one submit button at the end of partial view. I want to save both main view and partial view data on single button click to respective tables. Please advise me.
So, if I understand correctly what you're trying to achieve...
Remove the submit button from the partial view and move it to the main view
Remove the form from the partial view and let the main form to handle a whole user's input - in your case you have two forms, that means each form should submit its own data to the respective controller/action. Nesting of html forms is impossible - Can you nest html forms?
If you need to do some actions (like showing dynamic dropdowns with loading of different data or something else) - do that as separate AJAX calls inside the partial view. But the main form, that finally submits data, should be the only one.
I'm trying to use some features of MVC. In practice I made this view:
#using (Html.BeginForm("ResetPasswordToken", "Account", FormMethod.Post, new { rt = #Request.QueryString["rt"] })))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "Reset Password non riuscito")
<div class="container above-footer login-form">
<div class="col-md-6" align="center" style=" margin-left:25%; margin-top:100px; margin-bottom:100px;">
<div class="editor-label">
#Html.LabelFor(m => m.ResetToken)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.ResetToken, new { #Value = #Request.QueryString["rt"] })
#Html.ValidationMessageFor(m => m.ResetToken)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.NewPassword)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.NewPassword)
#Html.ValidationMessageFor(m => m.NewPassword)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.ConfirmPassword)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.ConfirmPassword)
#Html.ValidationMessageFor(m => m.ConfirmPassword)
</div>
<p>
<input type="submit" value="Change Password" />
</p>
</div>
</div>
The view is used to reset a password and i want to call the method ResetPasswordToken in AccountController when i click on "Change Password".
The AccountController is so structured, but it doesn't go to the method when i click on button:
[HttpPost]
public ActionResult ResetPasswordToken()
{
return View();
}
[HttpPost]
public ActionResult ResetPasswordToken(RecoverPasswordModel model)
{
if (ModelState.IsValid)
{
if (WebSecurity.ResetPassword(model.ResetToken, model.NewPassword))
{
return RedirectToAction("PasswordResetSuccess");
}
else
{
ModelState.AddModelError("", "The password reset token is invalid.");
}
}
return View(model);
}
Please someone can help me?
Thank you very much and good holidays
Roberto
You have two action with same name and same httppost attibute. Mark first action (without parameter) as httpget
Ok. It missing [AllowAnonymus]. Great and thank you. Now one question. What is the best method to pass the value of the tokens in the URL to the controller without use # Html.TextBoxFor (m => m.ResetToken, new { #Value = #Request.QueryString["rt"] }). I want to hidden this value to user.
I've got a controller in MVC5 for an apply form. There is a GET to return the view and a POST to take the form data from the application and process it:-
public ActionResult Apply(string jobReference)
{
Apply form = new Apply();
Session[Settings.JOBREFERENCE] = jobReference;
return View(form);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Apply(Apply form)
{
if (ModelState.IsValid)
{
}
}
When I press the to submit the form, it calls the GET controller instead of the the POST controller, despite it having [HttpPost] on the latter.
If I actively renamed the HTTPPost controller and navigate to it, I see a Server Error, with a message saying it cannot be found. Submitting the form causes the page to crash.
Form Code
#model Salt.Models.Apply
<div class='applyForRoleExt popupBox'>
<img src="/img/closePopup.png" alt="close" />
<div class="innerContainer">
#using (Html.BeginForm("Apply", "Form", FormMethod.Post, new { enctype = "multipart/form-data", #id = "ApplyForm" }))
{
#Html.AntiForgeryToken()
<h6>Apply for this role</h6>
#*<div class="haveAccount">
<span>Have an account? Apply quickly by logging in now</span>
Login to my account
</div>*#
<div class="leftCol">
<label>Name<span>*</span></label>
<div class="inputBox">
#Html.TextBoxFor(m => m.Name)
</div>
<label>Email Address<span>*</span></label>
<div class="inputBox">
#Html.TextBoxFor(m => m.EmailAddress)
</div>
<label>Telephone Number<span>*</span></label>
<div class="inputBox">
#Html.TextBoxFor(m => m.TelephoneNumber)
</div>
<label>Portfolio Link<span>*</span></label>
<div class="inputBox">
#Html.TextBoxFor(m => m.PortfolioLink)
</div>
</div>
<div class="rightCol">
<label>CV Upload</label>
<div class="inputBox">
#Html.TextBoxFor(m => m.CV, new { #type = "file" })
</div>
<label>Covering Note</label>
<div class="inputArea">
#Html.TextAreaFor(m => m.CoveringNote)
</div>
</div>
<div class="actions">
<p class="terms">By submitting this form you consent to Salt Recruitment processing your personal data in accordance with our privacy policy and agree to future contact material.</p>
<!--<button class="submit">Apply Now</button>-->
<input type="submit" name="submit" value="Apply Now" />
</div>
}
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$.validator.unobtrusive.parse("#ApplyForm");
});
</script>
Thanks,
Mike.
It's been fixed. It took a second pair of eyes but a rule in the web.config was removing the trailing slash from the form post URL and it was defaulting to loading the GET. No idea why that would cause the problem but it did.
I'm only starting in MVC4 and
I'm trying to put multiple partial views in one page every partial is suppose to be with different data but it is always show one partial with only one data
every partial is shown on button click.
This is the view code:
<section id="comments">
<h3>Comments</h3>
#{
foreach (MvcApplication4.Models.comment item in postComments)
{
<article>
<p>#item.body</p>
using (Html.BeginForm("Delete", null, new { id = item.ID ,pid = item.idPost}, FormMethod.Post))
{
#Html.HttpMethodOverride(HttpVerbs.Delete)
<button type="submit" class="button delete" >Delete</button>
}
<section>
<button type="submit" class="button Edit" id="edit" onclick="return showHide();" >Edit</button>
<div id="partial" hidden="hidden">
#Html.Partial("editCom",item)
</div>
</section>
}
}
</article>
}
}
</section>
This is the showhide partial:
<script type="text/javascript" language="javascript">// <![CDATA[
function showHide() {
var ele = document.getElementById("partial");
if(ele.style.display == "block") {
ele.style.display = "none";
}
else {
ele.style.display = "block";
}
}
// ]]></script>
This is the partial :
#using MvcApplication4.Models
#model MvcApplication4.Models.comment
#{comment com = Model;
}
#using (Html.BeginForm("Edit", null,new{ pid=com.idPost,cid=com.ID}, FormMethod.Post))
{
<fieldset>
<div class="editor-label">
#Html.LabelFor(x => com.user)
</div>
<div class="editor-field">
#Html.LabelFor(x => com.user,Session["username"].ToString())
#Html.ValidationMessageFor(x => com.user)
</div>
<div class="editor-label">
#Html.LabelFor(x => com.email)
</div>
<div class="editor-field">
#Html.EditorFor(x => com.email,com.email)
#Html.ValidationMessageFor(x => com.email)
</div>
<div class="editor-label">
#Html.LabelFor(x => com.url)
</div>
<div class="editor-field">
#Html.EditorFor(x => com.url,com.url)
#Html.ValidationMessageFor(x => com.url)
</div>
<div class="editor-label">
#Html.LabelFor(x => com.body)
</div>
<div class="editor-field">
#Html.EditorFor(x => com.body,com.body)
#Html.ValidationMessageFor(x => com.body)
</div>
<p>
<input type="submit" value="save" />
</p>
</fieldset>
}
Your code for
<div id="partial" hidden="hidden">
#Html.Partial("editCom",item)
</div>
Determines which sections are controled by the buttons:
var ele = document.getElementById("partial");
if(ele.style.display == "block") {
ele.style.display = "none";
}
....
You are generating several sections all with the same id of "partial" then expecting the button to determine which div to manage without a unique id of some kind via getElementById("partial")
Instead, you need to generate a unique id for each <div> and then use the same id in your javascript method for getElementById()