Validate Input is not working.The form gets submitted and the success view is displayed even when the form is posted with html tags
<b> hello </b>
Why is the cross site scripting prevention not working? It should be enabled by default right?
Razor View
<h4 style="color:purple">
<b>ID:</b> #ViewBag.ID <br />
<b>Name:</b> #ViewBag.Name <br />
</h4>
<hr />
#using (Html.BeginForm("register", "Adder", FormMethod.Post))
{
<div class="form-group">
#Html.TextArea("comments");
<input type="submit" />
</div>
}
Controller Method
[HttpPost]
public string register(string val)
{
// quickdbEntities1 ent = new quickdbEntities1();
// Player p1 = ent.Players.FirstOrDefault(p => p.Name == "name");
//// ent.Players.Add(player);
//// int res = ent.SaveChanges();
// ViewBag.id = player.PlayerId;
// ViewBag.Name = p1.Name;
return ("success");
}
Update:
I have added DataAnnotation [Required] and now uses a form like this.Still the form submits
#model Vidly.Domain.Player
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#section scripts
{
#Scripts.Render("~/bundles/jqueryval" )
}
#using (Html.BeginForm("register", "Adder", FormMethod.Post))
{
<div class="form-group">
#Html.TextBoxFor(m => m.Name,new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Name)
<input type="submit" name="submit" />
</div>
}
It is because you are accepting the parameter as string and no validation script in view page (as of we can't see if the layout page has the scripts).
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.
I have the following and am getting a 404 on submit, but from fiddler I'm getting a 500 error about not having the antiforgerytoken. Any thoughts what might be wrong?
ShareController.cs code
// creates the form
[HttpPost]
public ActionResult ShareVideoFormEmail(string vguid)
{
var shareModel = GetShareVideoFormEmailModel(vguid);
return PartialView("ShareVideoFormEmail", shareModel);
}
// handler function
[HttpPost]
[ValidateHoneyPot]
[ValidateAntiForgeryToken]
public ActionResult ProcessShareVideoFormEmail(ShareVideoEmailModel model)
{
//do stuff
return PartialView("Result");
}
ShareVideoFormEmail.cshtml
#model Gcc.GctWebsite.Areas.Forms.Models.Share.ShareVideoEmailModel
#using (Ajax.BeginForm("ProcessShareVideoFormEmail","share",null ,new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "shareVideoFormWithMyFriends",
OnBegin = "onBeginShareEmail", #* show ajaxspinner *#
OnComplete = "onCompleteShareEmail", #* hide ajaxspinner *#
OnSuccess = "onSuccessShareEmail" #* hide ajaxspinner *#
}, new { id = "shareVideoEmailModelForm" }))
{
<div class="modal-header">
<div class="modal-header-title">Share the video "#ViewBag.VideoTitle" with my friends</div>
</div>
<div class="modal-body">
<div id ="shareVideoFormWithMyFriends" class="share-form-email">
#Html.AntiForgeryToken()
#Html.HoneyPot()
#Html.HiddenFor(x => x.UpdateTargetId)
#Html.HiddenFor(x => x.OgMetaTitle)
#Html.HiddenFor(x => x.OgMetaDescription)
#Html.HiddenFor(x => x.OgMetaDefaultImage)
#Html.HiddenFor(x => x.OgMetaImage)
#Html.HiddenFor(x => x.Brand)
#Html.HiddenFor(x => x.VGuid)
#Html.HiddenFor(x => x.TripCode)
#Html.HiddenFor(x => x.EmailSubject)
<!-- big section of input fields for model properties -->
<div class="form-field">
<span class="req-lbl">* = Required</span>
</div>
<div class="form-field form-submit">
<input class="btn btn-main-theme btn-narrow btn-submit-form" value="Send Email" type="submit">
<input type="reset" class="btn btn-grey btn-reset cancel-share-Email" value="Cancel">
</div>
<script>
$(document).ready(function (e) {
$('.required-input').after("<span class=\"rqdfield\">*</span>");
loadJqueryValidationManually("#shareVideoEmailModelForm");
});
</script>
It turns out that in my model in some of the data there were some html no-no's. I had to htmlencode a couple properties before displaying the view, then it worked fine upon postback.
I discovered this by changing the input parameter of the action method to object and removing the honeypot and xsfr validation. Then I got a nice 500 error explaining I had unsafe data.
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 have a view which contains a tab layout, each tab contains a form which I am submitting through ajax.beginform. If the modelstate is not valid I return the view which is where I cannot work out how to render the view properly. Currently when I submit one of the forms it renders the whole page again within my tab, which I don't want. I thought using ajax updatetargetid I could render the div that needs replacing, but as I said it renders the whole page within my tab.
View
#model Trakman_Portal_Administration.Models.VehList
#using Trakman_Portal_Administration.Models
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
#*<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>*#
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script>
$(function () {
$("#tabs").tabs();
});
</script>
#{
ViewBag.Title = "Edit";
}
<div class="editBanner">
<div class="editor-label">
#* #{
string custCode = ViewBag.custCode;
}*#
#* <h2>#Html.Label(custCode, custCode )</h2>*#
<h2>#Html.Label(Model.Column_8, Model.Column_8 )</h2>
</div>
</div>
<h3 style="font-size:20px">Edit</h3>
<br />
#*
TAB 1 VEHICLE DATA SAVED TO VEHLIST
*#
<div id="tabs">
<ul>
<li>Vehicle</li>
<li>Page 1</li>
<li>Page 2</li>
</ul>
<div id="tabs-1">
#using (Ajax.BeginForm("Edit",null, new AjaxOptions
{
OnSuccess = "OnSuccessEditVehicle",
OnFailure = "OnFailureEditVehicle",
HttpMethod = "Post",
UpdateTargetId = "tabs-1"
}, new {id="EditVehicle"}))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>VehList</legend>
#Html.EditorForModel()
</fieldset>
<div style="position:relative;left:750px">
#Html.ActionLink("Back to List", "Index", new {custCode= ViewBag.custCode, conName = ViewBag.connectionName}) |
<input type="submit" value="Save" /></div>
}
#*
TAB 1 VEHICLE DATA SAVED TO VEHICLEDATA
*#
</div>
<div id="tabs-2">
#{
VehicleData vd = ((Trakman_Portal_Administration.Controllers.VehicleController)this.ViewContext.Controller).EditVDPartial(Model.Column_0);
}
#Html.Partial("EditVDPartial", vd)
#* <div style="position:relative;left:750px">
#Html.ActionLink("Back to List", "Index", new {custCode= ViewBag.custCode, conName = ViewBag.connectionName}) |
<input type="button" value="Save" onclick="submitVehicleDataForm()" /></div>*#
</div>
#*
TAB 3 VEHICLE DATA SAVED TO VEHICLE
*#
<div id="tabs-3">
#{
vehicle v = ((Trakman_Portal_Administration.Controllers.VehicleController)this.ViewContext.Controller).EditPartial(Model.Column_0);
}
#Html.Partial("EditPartial", v)
<div style="position:relative;left:750px">
#Html.ActionLink("Back to List", "Index", new {custCode= ViewBag.custCode, conName = ViewBag.connectionName}) |
<input type="submit" value="Save" /></div>
</div>
</div>
<br />
Controller
public ActionResult Edit(VehList vehlist)
{
tedb = new trakman_Entities(System.Web.HttpContext.Current.Session["connection"].ToString());
if (ModelState.IsValid)
{
vehlist.Column_8 = System.Web.HttpContext.Current.Session["staticCustCode"].ToString();
tedb.VehLists.Attach(vehlist);
tedb.ObjectStateManager.ChangeObjectState(vehlist, System.Data.EntityState.Modified);
tedb.SaveChanges();
var cust = tedb.customers.First(c => c.code == vehlist.Column_8);
//return RedirectToAction("Index", new { custCode = cust.code, conName = System.Web.HttpContext.Current.Session["connectionName"]});
}
ViewBag.Column_8 = new SelectList(tedb.customers, "code", "name", vehlist.Column_8);
return View(vehlist);
}
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