I'm having a hard time passing data to my model using viewbag.
Here is some example to enlighten you:
#model UCPBEscheatment.Models.aspnet_Membership
#{
ViewBag.Title = "AnswerForgotPassword";
}
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
<em style="font-size:small">#Html.ValidationSummary(true, "Forgot Password was unsuccessful. Please correct the errors and try again.")</em>
<fieldset style="background-color:#f0f0f0">
<legend> Forgot Password </legend>
<br />
• Second step: <em style="color:Teal"> Answer your secret question</em>
<br /><br />
<b> Secret Question:</b> #ViewBag.question
<br /><br />
<b> Secret Answer: </b>#Html.EditorFor(a => a.PasswordAnswer)
<br /><br />
#{
INPUT CODE HERE TO PASS A VALUE TO THE MODEL USING VIEWBAG LIKE:
ex.
#MODEL.USERID = VIEWBAG.USERID
}
<input type="submit" value="Submit" />
</fieldset>
}
It doesn't work that way. You can't assign to the model that is being returned in the post. I'd suggest adding the user's id to the form url and using the id on the url to find the user that needs the password secret validated.
#using (Html.BeginForm("validatepassword","account",new { id = ViewBag.UserID }))
{
...
}
Or better yet, set the user id on the model and use it from there instead of the ViewBag, but still using it in the url to post back.
Related
addMission.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Create a mission</title>
</head>
<body>
<h1>Create a Mission</h1>
<form action="/createMission" method="post">
<p>Mission title: <input type="text" required id="title" name="title" value=""></p>
<p>
<select name="agent" id="agent">
<option value="natasha">Natasha Romanova</option>
<option value="austin">Austin Powers</option>
<option value="johnny">Johnny English</option>
</select>
</p>
<h2>Enter the gadgets</h2>
<p>Gadget 1:<input type="text" required id="gadget1" name="gadget1" value=""></p>
<p>Gadget 2:<input type="text" required id="gadget2" name="gadget2" value=""></p>
<p><input type="submit" value="Create Mission!"></p>
</form>
<p> Back to home </p>
</body>
</html>
Controller Code
#PostMapping("/createMission")
public String createMission(#ModelAttribute Mission mission) {
int returnValue = database.createMission(mission);
System.out.println(returnValue);
return "view_missions";
}
createMission() method
public int createMission(Mission mission) {
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
String query = "INSERT INTO missions(agent, title, gadget1, gadget2) VALUES (:agent, :title, :gadget1, :gadget2)";
namedParameters
.addValue("agent", mission.getAgent())
.addValue("title", mission.getTitle())
.addValue("gadget1", mission.getGadget1())
.addValue("gadget2", mission.getGadget2());
int returnValue = jdbc.update(query, namedParameters);
return returnValue;
}
In the code snippets shared above, Im creating a mission using thymleaf.
When I enter the details in the textboxes and hit "Create" button I get an error 'Property or field 'empty' cannot be found on null'. Im sure this null property is coming from the dropdown list.
Is there any way I can get the value of the dropdown too along with the other values and send them to the createMission() ?
I don't see in your controller how you get back the values.
You need to add an object to your model in your "get controller" and link it to the form.
Then you can retrieve it and save it in the database.
Please have a look to this post you will get more details on how to make it
Apologies for starting another thread but I kind of solved the issue of my first thread but now I run into a different issue.
Background:
I have a portlet which takes 3 Parameters (Temperature,FromUnit,ToUnit) and passes them on to an external WebService located here:
http://www.webservicex.net/ConvertTemperature.asmx/ConvertTemp
I did not want the portlet to actually redirect to the URL of the webService and the only way to do that appeared to be AJAX using jquery which I have done now.
However I also want the response of the webService to be embedded in the same portlet that I used to call it and that's where I am having issues.
This is what I got so far, here is my portlet page:
<html>
<head>
<meta charset="utf-8" />
<title>Demo</title>
</head>
<body>
<script src="http://localhost:8080/my-greeting-portlet/jquery.js"></script>
<script type="text/javascript" src="http://localhost:8080/my-greeting-portlet/js/script.js"></script>
<%# taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%# page import="javax.portlet.PortletPreferences" %>
<portlet:defineObjects />
<%
PortletPreferences prefs = renderRequest.getPreferences();
String Temperature = (String)prefs.getValue("Temperature","Temperature");
PortletPreferences prefs2 = renderRequest.getPreferences();
String FromUnit = (String)prefs2.getValue("FromUnit", "FromUnit");
PortletPreferences prefs3 = renderRequest.getPreferences();
String ToUnit = (String)prefs3.getValue("ToUnit","ToUnit");
%>
<portlet:renderURL var="editGreetingURL">
<portlet:param name="jspPage" value="/edit.jsp" />
</portlet:renderURL>
<div id="contact_form">
<form name="callWebService" id="callWebService" action="">
<fieldset>
<label for="Temperature" id="Temperature_label">Temperature </label>
<input type="text" name="Temperature" id="Temperature" size="30" value="" class="text-input" />
<label class="error" for="Temperature" id="Temperature_error">This field is required.</label>
<br />
<label for="FromUnit" id="FromUnit_label">From unit </label>
<input type="text" name="FromUnit" id="FromUnit" size="30" value="" class="text-input" />
<label class="error" for="FromUnit" id="FromUnit_error">This field is required.</label>
<br />
<label for="ToUnit" id="ToUnit_label">To Unit </label>
<input type="text" name="ToUnit" id="ToUnit" size="30" value="" class="text-input" />
<label class="error" for="ToUnit" id="ToUnit_error">This field is required.</label>
<br />
<input type="submit" name="submit" class="button" id="submit_btn" value="submit" />
</fieldset>
</form>
</div>
</body>
</html>
And here is the jquery code:
$(function() {
$('.error').hide();
$(".button").click(function() {
// validate and process form here
var dataString = $("#callWebService").serialize();
// alert (dataString);return false;
$.ajax({
type: "POST",
url: "http://www.webservicex.net/ConvertTemperature.asmx/ConvertTemp",
data: $("#callWebService").serialize(),
success: function() {
$('#contact_form').html("<div id='message'></div>");
$('#message').html("<h2>Contact Form Submitted!</h2>")
.append("<p>We will be in touch soon.</p>")
.hide()
.fadeIn(1500, function() {
$('#message').append("<img id='checkmark' src='images/check.png' />");
});
}
});
return false;
$('.error').hide();
var Temperature = $("#Temperature").val();
if (Temperature == "") {
$("#Temperature_error").show();
$("#Temperature").focus();
return false;
}
var FromUnit = $("input#FromUnit").val();
if (FromUnit == "") {
$("label#FromUnit_error").show();
$("input#FromUnit").focus();
return false;
}
var ToUnit = $("input#ToUnit").val();
if (ToUnit == "") {
$("label#ToUnit_error").show();
$("input#ToUnit").focus();
return false;
}
});
});
Everything seems to be working, or at least I do not get errors but it seems that this part of the code is completely ignored:
success: function() {
$('#contact_form').html("<div id='message'></div>");
$('#message').html("<h2>Contact Form Submitted!</h2>")
.append("<p>We will be in touch soon.</p>")
.hide()
.fadeIn(1500, function() {
$('#message').append("<img id='checkmark' src='images/check.png' />");
});
When I press the "submit" button nothing happens. No redirection to the webservice URL (good) but also the custom message defined above does not show up (bad). The screen remains exactly as it is.
When I uncomment the "alert" in the jquery code and the parameters are definitely picked up correctly and I would assume that they are being passed to the webService URL but nothing else is happening.
Is this because the webservice URL returns a response that overwrites my message or something like that?
How can I get the webService response embedded into the portlet?
Again, many thanks for looking at this, it is much appreciated!
You ran into a Cross Domain Scripting problem.
Read this and this to resolve the problem
I have a partial view like this (simplified):
#model Portal.Models.LoginModel
<div class="login-container k-block">
<section id="login-form" class="">
#using (Html.BeginForm(actionName, controllerName, new { ReturnUrl = ViewBag.ReturnUrl }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset id="login-form-list-items">
<ol>
<li>
#Html.LabelFor(m => m.CardNumber)
#Html.TextBoxFor(m => m.CardNumber, new { #class="k-textbox"})
<div class="k-error-colored">
#Html.ValidationMessageFor(m => m.CardNumber)
</div>
</li>
<li>
#Html.LabelFor(m => m.Pin)
#Html.PasswordFor(m => m.Pin, new { #class="k-textbox"})
<div class="k-error-colored">
#Html.ValidationMessageFor(m => m.Pin)
</div>
</li>
<input id="login-input-submit" class="k-button" type="submit" value="Enter" />
</fieldset>
</div>
And in my login view I call this partial view like:
#model Portal.Models.LoginModel
#Html.Partial("_LoginFormNoRegistration", Model, new ViewDataDictionary { { "actionName", "Login" }, { "controllerName", "Account" } })
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
The problem is that when the login method in the controller adds an error like:
public ActionResult Login(LoginModel model, string returnUrl)
{
//...
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
The message is not show in the validation summary... I don't understand why... What could be the problem? Some javascript library missing?
Update
I also found that the form generated as the novalidate attribute set:
<form action="/" method="post" novalidate="novalidate">
//...
</form>
I don't know why.
I found the problem.
I was passing a new ViewData in the RenderPartial which was overriding the ViewData of the parent view, so the model state was lost, as explained here: Pass Additional ViewData to an ASP.NET MVC 4 Partial View While Propagating ModelState Errors.
Changing the main view to:
#model Portal.Models.LoginModel
#{
ViewData.Add("actionName", "Login");
ViewData.Add("controllerName", "Account");
Html.RenderPartial("_LoginFormNoRegistration", Model, ViewData);
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Did the trick!
Also, if you want to show a general error message for the model in the validationsummary, be sure to add the error with an empty string as key:
ModelState.AddModelError("error", "The user name or password provided is incorrect."); - doesn't work
ModelState.AddModelError("", "The user name or password provided is incorrect."); - works
Remove the true argument in #Html.ValidationSummary()
It could be a few different things off the top of my head. First off you may not be including the required JavaScript. You may not need all of these but i include these in almost all of my layout views.
<script src="#Url.Content("~/Scripts/jquery-1.8.3.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
Also, could you show the code for your partial view? If you are referencing values that are inside a child class in your model the validation can act a little wonky sometimes.
Lastly, this sounds silly but as you did not post the code for your login model make sure you are using the proper data annotations for the values that you want the validation to show up for.
Apologies in advance for the question, but though I found numerous suggestions here, none have worked out for me. I'm feeling crazy, so...
I have an MVC 3 application that, when it first loads up, displays table with Model data for all users. That part works fine. I have two text boxes, one for account ID and another for user that allows me to requery the database for more specific user data. When I use the submit button, I get the data back but the entire page refreshes and, while I get the form and table back with the correct data, the rest of the page is white. No graphics I had previously or anything. Another interesting thing is that if i submit the form again, from the white page, with whatever valid parameters, the AJAX DOES work. I'm baffled.
The form looks like this:
#using (Ajax.BeginForm("TaskList", "Dispatch",
new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "tblBody",
InsertionMode = InsertionMode.Replace }, new { id = "frmTaskList" }))
{
<table id="tblTaskList" class="tblTaskList">
<thead>
<tr>
<th>Ticket ID</th>
<th>Date</th>
<th>Customer Name</th>
</tr>
</thead>
<tbody id="tblBody" class="tblBody">
#{for (var ix = 0; ix < Model.Value.Count - 1; ix++)
{
<tr id="#(Model.Value[ix].TicketId)">
<td>#Model.Value[ix].TicketId</td>
<td>#Model.Value[ix].Created</td>
<td>#Model.Value[ix].ContactName</td>
</tr>
}}
</tbody>
</table>
<input type="text" id="hidAccId" name="hidAccId" value="" />
<input type="text" id="hidUserId" name="hidUserId" value="" />
<input type="submit" id="btnTaskList" value="Submit" />
}
Also the scripts I'm using, placed at the top of the page:
<script src="../../Scripts/jquery-ui-1.8.11.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery.unobtrusive-ajax.js" type="text/javascript"></script>
Side note: I have tried using #Url.Content instead of the src attribute to no avail. I've also experimented using the following, again with no different result:
<script src="#Url.Content("~/Scripts/MicrosoftAjax.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/MicrosoftMvcAjax.js")" type="text/javascript"></script>
You have jQuery and jQuery-ui referenced twice. It's not necessary. The following should be enough:
<script src="#Url.Content("~/Scripts/jquery-1.7.2.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
You obviously should ensure that jquery-1.7.2.min.js is present in the Scripts folder. Out of the box ASP.NET MVC 3 comes only with jQuery 1.5. As far as the Microsoft* scripts are concerned, forget about those, they are no longer used in ASP.NET MVC 3.
Also you don't have a submit button in your form.
This:
<input type="button" id="btnTaskList" value="Submit" />
should be:
<input type="submit" id="btnTaskList" value="Submit" />
if you expect a form submission to happen.
I have a farily straight forward form that renders personal data as a partial view in the center of the form. I can not get client side validation to work on this form.
I started chasing down the generate html and came up with the same model field rendered on a standard form and a partial view.
I noticed that the input elements are correctly populated on the first call, #html.partial, the following only happens when the partialview is reloaded via an ajax request.
First the header of my partial view, this is within a Ajax.BeginForm on the main page.
#model MvcMPAPool.ViewModels.EventRegistration
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function ()
{
$(".phoneMask").mask("(999) 999-9999");
});
</script>
#{
var nPhn = 0;
var dTotal = 0.0D;
var ajaxOpts = new AjaxOptions{ HttpMethod="Post", UpdateTargetId="idRegistrationSummary", OnSuccess="PostOnSuccess" };
Html.EnableClientValidation( true );
Html.EnableUnobtrusiveJavaScript( true );
}
Here is the razor markup from the partial view:
#Html.ValidationMessageFor(model=>Model.Player.Person.Addresses[0].PostalCode)
<table>
<tr>
<td style="width:200px;">City*</td>
<td>State</td>
<td>Zip/Postal Code</td>
</tr>
<tr>
<td>#Html.TextBoxFor(p=>Model.Player.Person.Addresses[0].CityName, new { style="width:200px;", maxlength=50 })</td>
<td>
#Html.DropDownListFor(p=> Model.Player.Person.Addresses[0].StateCode
, MPAUtils.GetStateList(Model.Player.Person.Addresses[0].StateCode))</td>
<td>
<div class="editor-field">
#Html.TextBoxFor(p=>Model.Player.Person.Addresses[0].PostalCode, new { style="width:80px;", maxlength=10 })
</div>
</td>
</tr>
</table>
Here is the rendered field from the partial view:
<td>
<div class="editor-field">
<input id="Player_Person_Addresses_0__PostalCode" maxlength="10" name="Player.Person.Addresses[0].PostalCode" style="width:80px;" type="text" value="" />
</div>
</td>
Here is the same model field rendered in a standard view:
<div class="editor-field">
<input data-val="true" data-val-length="The field Postal/Zip Code must be a string with a maximum length of 10." data-val-length-max="10" data-val-required="Postal or Zip code must be provided!" id="Person_Addresses_0__PostalCode" maxlength="10" name="Person.Addresses[0].PostalCode" title="Postal/Zip Code is required" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Person.Addresses[0].PostalCode" data-valmsg-replace="true"></span>
</div>
Notice that the partial view rendering has no data-val-xxx attributes on the input element.
Is this correct? I do not see how the client side validation could work without these attributes, or am I missing something basic here?
In order to create the unobtrusive validation attributes, a FormContext must exist. Add the following at the top of your partial view:
if (this.ViewContext.FormContext == null)
{
this.ViewContext.FormContext = new FormContext();
}
If you want the data validation tags to be there, you need to be in a FormContext. Hence, if you're dynamically generating parts of your form, you need to include the following line in your partial view:
#{ if(ViewContext.FormContext == null) {ViewContext.FormContext = new FormContext(); }}
You then need to make sure you dynamically rebind your unobtrusive validation each time you add/remove items:
$("#form").removeData("validator");
$("#form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("#form");