Parsing json into java objects with other object attribue in spring-mvc - javascript

I have an object of type element and this has an attribute of type theme. when I create a new element is represented by a theme select in the view, and the primary key is the value of the items in the select, when I send with json, spring try to create an object element and the next error is show
/element: org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.example.Theme, problem: no suitable creator method found
at [Source: org.mortbay.jetty.HttpParser$Input#dd0099; line: 1, column: 31]
this is my code in spring MVC
public class Element {
private String name;
private String type;
private Theme theme;
private String description;
// Get - Set
}
Theme Class
public class Theme {
private String name;
private String description;
// Get - Set
}
Method in the controller
#RequestMapping(method=RequestMethod.POST)
public #ResponseBody String create(#RequestBody Element element){
elementManager.saveElement(element);
return "exito";
}
and the javascript is this
$("#element").submit(function() {
var element = $(this).serializeObject();
$.postJSON("element", element, function(data) {
});
return false;
});
i hope someone can help me.

Based on your comment containing the JSON you send the server, I would say the issue is the JSON itself.
Your server is expecting a value along the lines of this:
{"name":"rooms","type":"Doc","theme":{"name":"themeName", "description":"themeDescription"},"descrip‌​tion":"They are realy big"}
You should fetch the object theme from where it is stored, and create the proper JSON. If the Theme is looked up at the client, you will need to change the Element to have a String theme attribute, and do the lookup on the client.

Related

Java Path Variable type conflicts with URL suffix added by Ajax, preventing servlet from being called

Context:
The following editAppointment() method displays a form for editing appointment details.
Of note, a #PathVariable of type Integer is used:
#RequestMapping(value = "/clinician/my_clinician_schedule/edit/{appointmentId}", method = RequestMethod.GET)
public ModelAndView editAppointment(#PathVariable("appointmentId") Integer appointmentId, #RequestParam(required = false) String date, #RequestParam(required = false) String time) {
Problem:
On the form, I'm attempting to use .Ajax to control the options displayed in one dropdown (clinicians) depending on another dropdown value (time). I have a Servlet class that I am trying to call with this code:
$.ajax({
url: "AjaxAppointment",
Instead of calling the Servlet class, the .Ajax code is changing the URL to:
/clinician/my_clinician_schedule/edit/AjaxAppointment
and causing the following error:
Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; nested exception is java.lang.NumberFormatException: For input string: "AjaxAppointment"]
In other words, instead of calling my Servlet class (shown below), it is calling the above editAppointment() method, which is throwing an error because it sees the String "AjaxAppointment" in place of the Integer PathVariable. Would anyone have a recommendation for how I can use a .Ajax to call my servlet in this case?
It is important to pass the appointmentId variable.
The servlet class is not getting called, but here is what that looks like:
#WebServlet(name = "AjaxAppointment", urlPatterns = "/AjaxAppointment")
public class AjaxAppointment extends HttpServlet {

Send complex object from view to MVC action as none ajax call

I'm working on an ASP.NET MVC web application.
There is a view with a bunch of search filters and there is also a grid in the middle of the page that represents the result of the search.
End-user set value for the search filter and when search button clicked an ajax call returns the values that will rebind the gird.
every row in the grid represents 'ItemId' and 'version' which could be selected by the checkbox.
At the end when the user clicks on "Detail report" we need to redirect the user to another page(view).
I need to pass the selected search filters and the grid selected rows values as an array like this (ItemIds[] and Versions[]) to the "Detail" action.
So, to make the question clear. I need to pass the below values to the action :
search filters
ItemId array
Version array
Unfortunately, I can not pass the parameters to the action. I got null
I can not call the action as ajax call When i use
View (Index.cshtml)
function prepareSelectedInfos() {
var formValues = $('#form').serializeFormToObject();
var gridValues = GetGridSelectedValues();
var dto = {
FormFilters: formValues,
ItemIds : gridValues.ItemIds,
Versions : gridValues.Versions
}
return dto;
}
$('#lnkDetailReport').click(function () {
var gridValues = GetGridSelectedValues();
var url = '/Report/Controller/Detail/';
var dto = prepareSelectedInfos();
window.open(url + dto, '_blank');
});
Controller
public ActionResult Detail(ModelVersionStatisticalDetailDto data)
{
//create a ViewModel according to the incoming data
var viewModel = ;
return View(viewModel);
}
Model
public class ModelVersionStatisticalDetailDto
{
public ModelVersionStatisticalReportDto FormFilters { get; set; }
public int [] ItemIds { get; set; }
public string[] Versions { get; set; }
}
I need to have the view prepared values in the Detail action
To the best of my recollection, it is not possible to perform a redirect after having post a complex object in ajax call (with the same posted parameters).
In order to perform your desired operation, you can choose a solution from below.
Use query strings in your Detail action and perform a simple post action instead of ajax call
Try to replace the response of Detail action with Partial View
If you are seeking a client side solution, you can assist from localStorage object (a tricky solution). You can store the required data in a localStorage object and pass the key to the controller. In the target page, use the key in order to fetch the data stored in storage. Do not forget to clear it after the process. https://blog.logrocket.com/the-complete-guide-to-using-localstorage-in-javascript-apps-ba44edb53a36/

How do I get a JavaScript array of an array of strings into a C# data structure?

I've been trying for the past hour and can't get it. At this point my controller looks like
public ActionResult GenerateMasterLink (string assetsJSON)
{
...
}
and I've confirmed that it is being passed a string like
[["Microsoft","Azure","roman_column.png"],["Microsoft","Azure","runphp.cmd"],["Microsoft","Azure","runphp.cmd"],["Microsoft","Azure","Picture1.png"],["Microsoft","Azure","vertical-align-scrnsht.png"],["Microsoft","Azure","vertical-align-scrnsht.png"]]
The only question I have is how I get the damned stuff out of it!
I've tried creating a class
public class ThreePartKey
{
public string organizationName { get; set; }
public string categoryName { get; set; }
public string fileName { get; set; }
}
and then done
ThreePartKey [] assetList = new JavaScriptSerializer().Deserialize<ThreePartKey []>(assetsJSON);
which gives me
Failed to load resource: the server responded with a status of 500
(Internal Server Error)
in my browser's console some of the time, and other times gives me
Additional information: Type
'AllyPortal.Controllers.SurfaceAssetsController+ThreePartKey' is not
supported for deserialization of an array.
as a Visual Studio error.
I've experimented with a million things and can't get this right. All I want is to have the JSON in some C# data structure where I can actually use it in my controller. Any suggestions?
You are trying to deserialize to incompatible model. You string input can be deserialized into string[][] variable but in order to allow deserializations into an ThreePartKey you need to name those values per property:
[[organizationName: "Microsoft",...]]
This will copy right value to your model
The problem is that your target datatype doesn't match the source datatype.
If you are converting an array of array of strings, you must deserialize into another array of array of strings, only them, you'll be able to convert it into whatever you want:
In short, replace
ThreePartKey [] assetList = new JavaScriptSerializer().Deserialize<ThreePartKey []>(assetsJSON);
for
ThreePartKey[] assetList = new JavaScriptSerializer().Deserialize<string[][]>(assetsJSON)
.Select(el => new ThreePartKey() {organizationName = el[0], categoryName = el[1], fileName = el[2]})
.ToArray();

Getting data with Breeze that is "Ignore"d in the database

I am building a SPA and are using BreezeJS for data management. Now I want to be able to set processed data on my model class that are not present in the database and send it up the client. The problem is that breeze also ignores these properties.
public class MyModel{
public int Id{get; set;}
public string Name{get; set;}
public string ProcessedData{get; set;}
}
...
Ignore(model=> model.ProcessedData);
I realize that Breeze uses the same metadata as my datacontext, but there should be a way to override it.
The ignored properties is sent by the controller as json, it's just a matter of making breeze parse it as I need it to.
I haven't confirmed this but I think that if your are sure that the data is being returned from the server then you can add "unmapped" properties with the correct names to the Breeze client and it will materialize these as well. See the "unmapped" discussion here: http://www.breezejs.com/documentation/extending-entities .
Or you could try this ( I haven't actually tested this) AFTER the metadata has already been returned.
var dp = new breeze.DataProperty( {
nameOnServer: "ProcessedData",
dataType: "String",
isUnmapped: true
});
myEntityManager.metadataStore.getEntityType("MyModel").addProperty(dp);
and then try your query.
Note: only "unmapped" properties can be added to the EntityType after the EntityType has been itself added to a MetadataStore.

Application settings in Windows phone 8, using javascript

I'm developing an app for WP8 using HTML5/JavaScript.
I gather user settings in array variable in JavaScript, and would very much like to save these for future use. And save them in roaming settings to be more precise.
After some research, it seems that this is impossible straight from js. The API calls I found to perform this task in Windows 8 does not work under WP8. So only work-around I can come up is structure:
1) When I want to save data, from js I make
window.external.notify("LaunchSaveProcess");
to send notification to browser.
2) In XAML file
<phone:WebBrowser ScriptNotify="Catch_Script_Notification" />
to deliver notifications from browser to c#
3) In c# catch the notification
private void Catch_Script_Notification(object sender, NotifyEventArgs e)
{ if (e.Value.StartsWith("LaunchSaveProcess")) {
//"important function"
} }
4) The "important function" calls a method in JavaScript, which returns the array of user settings, then proceeds to save the data using
var userSettings = Browser.InvokeScript("getSettings()");
var roamingSettings = Windows.Storage.ApplicationData.Current.RoamingSettings;
roamingSettings.Values["settings"] = userSettings;
Now few questions.
Is this model right, or is there a easier way to do it? Can you pass parameters straight from JavaScript to c# somehow while making notification event?
Can I save array straight into roamingSettings, or do I need to chop it down and save everything separate?
For clarification the usersettings array is 1-dimensional array, where I push objects with "key" and "value" pairs. So I can easily access content within loop using
userSettings[i].key and .value syntax.
Another alternative to calling back into JavaScript from C# is to pass all the data in your notification string in one go.
From your JavaScript side, it is very easy to generate a JSON representation of your data. From the C# side however you would have to declare the DataContract that DataContractJsonSerializer would need to interpret this data, which is a bit more work.
JavaScript helper function which takes in your 1D array of key/value pairs:
function saveUserSettings(valuesToSave) {
var notifyObject = { command: "saveUserSettings", values: valuesToSave };
var notifyObjectString = JSON.stringify(notifyObject);
window.external.notify(notifyObjectString);
}
// call it like this...
saveUserSettings([{ key: "key1", value: "value1" },
{ key: "key2", value: "value2" }]);
C# contracts:
using System.Runtime.Serialization;
[DataContract]
public class JsonScriptData
{
[DataMember(Name = "command")]
public string Command { get; set; }
[DataMember(Name = "values")]
public JsonUserSetting[] Values { get; set; }
}
[DataContract]
public class JsonUserSetting
{
[DataMember(Name = "key")]
public string Key{ get; set; }
[DataMember(Name = "value")]
public object Value { get; set; }
}
and your browser script notify becomes:
private void BrowserOnScriptNotify(object sender, NotifyEventArgs notifyEventArgs)
{
var str = notifyEventArgs.Value;
var serializer = new DataContractJsonSerializer(typeof(JsonScriptData));
var bytes = Encoding.UTF8.GetBytes(str);
JsonScriptData commandData;
using (var memoryStream = new MemoryStream(bytes))
{
commandData = (JsonScriptData)serializer.ReadObject(memoryStream);
}
// save out to application settings dictionary
var applicationSettings = IsolatedStorageSettings.ApplicationSettings;
foreach (var value in commandData.Values)
{
applicationSettings[value.Key] = value.Value;
}
applicationSettings.Save();
}
Of course you could save the whole user settings JSON string from JS as a single value into IsolatedStorageSettings which then means C# wouldn't even need to parse it.
Windows.Storage.ApplicationData.Current.RoamingSettings is not supported on Windows Phone 8, but is supported in Windows Phone 8.1. Instead, you can just use the Isolated Storage.
You can use the Coding4Fun.Toolkit.Storage package from NuGet and simply call Serialize.Save("PATH", objectToSave) to save an item and var result = Serialize.Open<TypeOfObject>("PATH") to get the data back.
NOTE: Starting with the next release of the toolkit, Serialize will be Serializer. Just an FYI.

Categories