I am trying to submit a form as a JSON object because I want to create a REST API with play.
The issue that I have is that Play tells me that is not a valid JSON.
My FORM code:
#(form : Form[Product]) #main("Create Form"){
#helper.form(routes.Products.createProduct, 'enctype -> "application/json"){
#helper.inputText(form("name"))
<button>Commit</button>
} }
Controller Code:
// Read JSON an tell if it has a name Path
#BodyParser.Of(BodyParser.TolerantJson.class)
public static Result createProduct() {
JsonNode json = request().body().asJson();
String name = json.findPath("name").textValue();
if (name == null) {
return badRequest("Not JSON");
} else {
return ok(name);
}
}
Whats the best way to do this? a read about submitting with Ajax but because I am new with play I don´t figure it out the way to do this with Play´s form syntax.
You can do it easily with jQuery (so make sure you have jQuery included in your head) and formAsJson() function based on serializeObject function.
#helper.form(routes.Products.createProduct(), 'id -> "myform") {
#helper.inputText(jsonForm("name"))
<button>Commit</button>
}
<script>
$.fn.formAsJson = function(){
var o = {};
var a = this.serializeArray();
$.each(a, function () {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return JSON.stringify(o)
};
var $myform = $("#myform");
$myform.on('submit', function () {
$.ajax({
url: $myform.attr('action'),
type: $myform.attr('method'),
contentType: "application/json",
data: $myform.formAsJson(),
success:function(){
alert("Great! Everything's OK!");
},
error: function(){
alert("Booo, something wrong :(");
}
});
return false;
});
</script>
and your createProduct() action could look just like:
public static Result createProduct() {
JsonNode json = request().body().asJson();
String name = json.findPath("name").textValue();
if (json==null || name==null || ("").equals(name.trim())){
return badRequest();
}
return ok();
}
Related
I am trying to have save changes on my script and I just need an update from my table. So far if I clicked the button, the alert success will not pop and can't see any error either. I also tried to verify to my table if the changes is made but the result is nothing happened
Here is the call function from my save button:
<script>
var op = '';
var op_dif = '';
$('#btnSave').click(function () {
op = $('#op').val();
op_dif = $('#op_difficulty').val();
alert(op + " " + op_dif); // I can see the value here
$.post("/Home/UpdateOP", {
'data': JSON.stringify([{
'op': op,
'opDiff': Op_dif
}])
}, function (data) {
var resp = JSON.parse(data);
if (resp["status"] == "SUCCESS") {
alert('Data has been successfully updated');
location.reload();
}
else {
alert('Error!!');
}
});
});
</script>
My view where my update query is located:
public string UpdateOpsDiff(operation[] ops)
{
string res = "";
foreach(var op in ops)
{
string updatetQuery = "update sys.OP_difficulty set op_difficulty = #diff where op = #op;";
MySqlCommand updateCommand = new MySqlCommand(updatetQuery);
updateCommand.Connection = myConnection;
updateCommand.Parameters.AddWithValue("#diff", op.op_dif);
updateCommand.Parameters.AddWithValue("#op", op.op);
myConnection.Open();
int updatedRowNum = 0;
try
{
updatedRowNum = updateCommand.ExecuteNonQuery();
}
catch(MySqlException)
{
updatedRowNum = updateCommand.ExecuteNonQuery();
}
finally
{
myConnection.Close();
}
res = "{status:SUCCESS, updatedRowNum:" + updatedRowNum + "}";
}
return res;
}
Controller where it reads the view query:
public string UpdateOp()
{
string data = Request.Form["data"];
IQA sys = new MysqlSys();
try
{
var rows = JsonConvert.DeserializeObject<operation[]>(data);
return sys.UpdateOpsDiff(rows);
}
catch (JsonSerializationException je)
{
Console.WriteLine(je.Message);
return "{status:'DATA_FORMAT_ERROR'}";
}
}
Is there any missing items that I need. It already working using the query from my controller but this time I need to store my query from my view.
Any suggestions or comments. TIA
Since you're using AJAX callback, you should change return type to ActionResult and mark the action method with [HttpPost] attribute, also you should use return Content() or return Json() depending on returned type from UpdateOpsDiff() (string or object, respectively). Here is an example of proper setup:
[HttpPost]
public ActionResult UpdateOp(string data)
{
IQA sys = new MysqlSys();
try
{
var rows = JsonConvert.DeserializeObject<operation[]>(data);
string result = sys.UpdateOpsDiff(rows);
// return JSON-formatted string should use 'Content()', see https://stackoverflow.com/q/9777731
return Content(result, "application/json");
}
catch (JsonSerializationException je)
{
// do something
return Json(new { status = "DATA_FORMAT_ERROR"});
}
}
Then set the AJAX callback to pass JSON string into action method mentioned above:
$('#btnSave').click(function () {
op = $('#op').val();
op_dif = $('#op_difficulty').val();
var values = { op: op, opDiff: op_dif };
$.post("/Home/UpdateOP", { data: JSON.stringify(values) }, function (data) {
var resp = JSON.parse(data);
if (resp["status"] == "SUCCESS") {
alert('Data has been successfully updated');
location.reload();
}
else {
alert('Error!!');
}
});
});
Note:
The JSON-formatted string should be presented in key-value pairs to be returned as content, as shown in example below:
res = string.Format(#"{""status"": ""SUCCESS"", ""updatedRowNum"": ""{0}""}", updatedRowNum);
I have 2 arrays in my Razor view. The first one checked checkboxes and the second is for unchecked. I can send one of them but I don't know how to send both of them. This is my jQuery code:
$(document).ready(function() {
$("#checkAll").click(function() {
$(".checkBox").prop('checked', $(this).prop('checked'));
});
$("#confrim").click(function() {
var selectedIDs = new Array();
var unseletedeIDs = new Array();
$('input:checkbox.checkBox').each(function() {
if ($(this).prop('checked')) {
selectedIDs.push($(this).val());
} else {
unseletedeIDs.push($(this).val());
}
});
var options = {};
options.url = "/Parts/ConfrimAll";
options.type = "POST";
options.data = JSON.stringify(selectedIDs);
options.contentType = "application/json";
options.dataType = "json";
options.success = function(msg) {
alert(msg);
};
options.error = function() {
alert("Error!");
};
$.ajax(options);
});
});
This is the action:
public ActionResult ConfrimAll(int?[] selectedIDs, int?[] unSelectedIDs)
{
if (selectedIDs!=null)
{
foreach (int id in selectedIDs)
{
Part obj = db.Parts.Find(id);
obj.IsOk = true;
db.Entry(obj).State = EntityState.Modified;
}
}
if (unSelectedIDs!=null)
{
foreach (int id in unSelectedIDs)
{
Part objs = db.Parts.Find(id);
db.Parts.Remove(objs);
}
}
db.SaveChanges();
return Json("yes");
}
Have you tried this?
JSON.stringify({ selectedIDs: selectedIDs, unseletedeIDs: unseletedeIDs });
You should have the two parameters selectedIDs and unseletedeIDs in the Action filled with this.
You can provide both array as part of an object to the data parameter of the $.ajax call. Try this:
$("#confrim").click(function() {
var data = {
SelectedIDs: [],
UnSelectedIDs: [],
}
$('input:checkbox.checkBox').each(function() {
data[this.checked ? 'SelectedIDs' : 'UnSelectedIDs'].push(this.value);
});
$.ajax({
url: '/Parts/ConfrimAll',
type: 'POST',
data: data,
success: function(msg) {
console.log(msg);
},
error: function(x, s, e) {
console.log('Error!');
console.log(x, s, e);
}
});
});
Note that it's much better practice to provide an object to the data parameter as jQuery will then encode it for you to the required format, escaping any special characters as it does it.
When a form is submitted I capture it in javascript. I do some validation and create a json object and pass that to $.post(). In my controller I have an object defined with the same definition as the json object. I'm finding if I don't access the json object in javascript then it's null when it gets to the controller. If I do an alert on it's fields then the controller has the values filled in. Any idea why this is happening?
$(function(){
$("#VideoForm").submit(function () {
var video = $("#txtVideo").val();
var val = getVideoID(video);
if (val.ID == -1) {
event.preventDefault();
alert("Invalid url. Only Vimeo and YouTube are supported.")
$("#txtVideo").val("")
return false;
}
// if this is commented out then my controller parameter object is null
// if this is uncommented then my controller parameter object is filled in
//alert(val.ID);
//alert(val.Source);
$.post('/Home/Index', val, function (data) {
});
});
function getVideoID(videolink){
var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
var match = videolink.match(regExp);
if (match && match[7].length == 11)
{
//alert("youtube video id : "+ match[7]);
alert("Youtube match");
return { ID: match[7], Source: "youtube" };
}
regExp = "vimeo\\.com/(?:.*#|.*/videos/)?([0-9]+)";
match = videolink.match(regExp);
if(match)
{
var videoid = videolink.split('/')[videolink.split('/').length - 1];
alert("Vimeo match");
//alert("vimeo video id :"+videoid);
return { ID: videoid, Source: "vimeo" };
}
else
{
return { ID: -1, Source: "" };
}
};
on my view page , i am passing some values to controller by ajax request , on controller action, after checking , redirecting message value to view's controller.Adding message to model and pasisng model to view again with new model value.On second time( postback) model values passed to view as Json but new model value(which is message) cannot be catch by javascript.In my code it is Model.INFO
$.ajax({
type: "POST",
url: '#Url.Action("TeamSaveChanges", "Administrator")',
data: {
ID: '#Model.ID',
doctorID: doctorValue,
nurseID:nurseValue,
driverID:driverValue,
technicianID: technicianValue
},
dataType: "text",
success: function () { alert("#Model.INFO")},
error: function () { alert("Error occured!!!") }
});
Controller
public ActionResult TeamSaveChanges(Guid ID, Guid? doctorID, Guid? nurseID, Guid? driverID, Guid? technicianID)
{
try
{
using (var client = SoapProxyFactory.CreateDSrvGDSoapClient())
{
var emptyTeam = Guid.Empty;
var ambID = client.getAmbulanceIDbyTeamID(ID);
var baseresult = client.checkAmblanceTeamsforDuplicateMembers(ambID, ID);
if (doctorID == emptyTeam && nurseID == emptyTeam && driverID == emptyTeam && technicianID == emptyTeam )
{
var result = client.EditTeamMembers(ID, doctorID, nurseID, driverID, technicianID);
if (result)
throw new Exception("saved");
}
else
{
foreach (var item in baseresult)
{
if(item.DOCTORCODE == doctorID && item.NURSECODE == nurseID && item.DRIVERCODE == driverID && item.TECHNICIANCODE == technicianID)
throw new Exception("The team with Same Members is exist." + "<p>(" + item.TEAMCODE + ")</p>");
}
var result = client.EditTeamMembers(ID, doctorID, nurseID, driverID, technicianID);
if (result)
throw new Exception("saved");
}
catch (Exception exp)
{
string message = exp.Message;
return RedirectToAction("TeamMembers", "Administrator", new { ID = ID, message = message });
}
[OutputCache(Location = System.Web.UI.OutputCacheLocation.None)]
public ActionResult TeamMembers(Guid? ID,string message)
{
try
{
if (!ID.HasValue())
return RedirectToAction("Ambulance");
using (var client = SoapProxyFactory.CreateDSrvALLSoapClient())
{
Guid id = ID.Value;
var clientGD = SoapProxyFactory.CreateDSrvGDSoapClient();
var result = client.GetTeamMembers(id);
result.INFO = message;
if (message != null)
{
result.INFO = message;
return Json(result,JsonRequestBehavior.AllowGet);
}
return View(result);
}
}
This line:
success: function () { alert("#Model.INFO")},
Will only pull in the INFO of the model once because it renders the server value in the client. If you are expecting it to change, then you have to pass the result back to success, and accept the new value as such:
success: function (d) { alert(d); },
To return a value to it you have to return from the action:
return Content("SOMEVAL"); // or PartialView or something that is string data
However, redirecting to action isn't going to return a response to the caller, and may not be handled properly through AJAX, so I'm not 100% sure what the question is...
Why would you use AJAX for this? What is happening is your script is firing a request off to your controller, which sends the response back as data, not a redirect to a new webpage.
Just create a form that POSTs those variables to your controller in typical MVC fashion, you'll get the result you want.
I have this code in my ActionResult
public ActionResult Copy( int bvVariableid ) {
var iReturn = _bvRepository.CopyBenefitVariable( bvVariableid, CurrentHealthPlanId, CurrentControlPlanId, _bvRepository.GetSecInfo( ).UserId, IsNascoUser());
if (iReturn == -999)
return new JavaScriptResult() { Script = "alert(Unique variable name could not be created');" };
if( iReturn != -1 )
return Json( new { RedirectUrl = string.Format( "/BvIndex/Index/{0}?bvIndex-mode=select", iReturn ) } );
return RedirectToRoute( "Error" );
}
This is the code i have in my View.
CopyBenefitVariable = function (bvId, bvName) {
if (confirm('Are you sure you want to copy from the Benefit Variable ' + bvName + ' ?')) {
$.post(
"/BvIndex/Copy/",
{ bvVariableid: bvId },
function (data) {
window.location = data.RedirectUrl;
}, "json");
}
};
When IReturn is -999 I am not getting the JavaScriptResult alert box on my page.
is that something I am doing wrong here?
Can any body help me out.
Thanks
I thing, there is a bug in this line:
return new JavaScriptResult() { Script = "alert(Unique variable name could not be created');" };
Corrected :
return new JavaScriptResult() { Script = "alert('Unique variable name could not be created');" };
Your problem is likely stemming from your client-side JavaScript. The .post() method in ajax is actually a shortcut for:
$.ajax({
type: 'POST',
url: url,
data: data,
success: success,
dataType: dataType
});
So your client-side code is telling jQuery to interpret the result as a json object (even though you sent back a script).
$.post(
"/BvIndex/Copy/", // url
{ bvVariableid: bvId }, // data
function (data) {
window.location = data.RedirectUrl; // success
},
"json" // dataType
);
I would change your code to look like this:
public ActionResult Copy( int bvVariableid ) {
var iReturn = _bvRepository.CopyBenefitVariable( bvVariableid, CurrentHealthPlanId, CurrentControlPlanId, _bvRepository.GetSecInfo( ).UserId, IsNascoUser());
if (iReturn == -999)
return new Json(new { type = "msg", data = "Unique variable name could not be created" });
if( iReturn != -1 )
return Json( new { type = "url", data = string.Format( "/BvIndex/Index/{0}?bvIndex-mode=select", iReturn ) } );
return RedirectToRoute( "Error" );
}
And your view code should look like this:
CopyBenefitVariable = function (bvId, bvName) {
if (confirm('Are you sure you want to copy from the Benefit Variable ' + bvName + ' ?')) {
$.post(
"/BvIndex/Copy/",
{ bvVariableid: bvId },
function (data) {
if (data.type == "url") {
window.location = data.RedirectUrl;
} else if (data.type == "msg") {
alert(data.data);
}
}, "json");
}
};
You can mark down my answer if you like, but it is generally accepted that the JavaScriptResult was a bad move on the ASP.NET MVC team's part. That being said, your sample already returns a Json Action Result for one of your conditions. You could do the same for both items. If you altered your JSON object like:
return Json( new { success = bool, RedirectUrl = value } );
Then you could change your client function to something like:
function (data) {
if(data.success === true) {
window.location = data.RedirectUrl;
} else {
alert('Unique variable name could not be created');
}
}
I know it doesn't directly address the issue with JavaScriptResult, but it should get the intended result of the code.