I have a 2d javascript array like this
[[2,3],[13,4],[1,19]]
and I want to pass it to my .Net controller
My controller header looks like this
public async Task<ActionResult> UpdateOrder(int[,] order)
My put call looks like this
updateOrder(order: number[][]): Observable<any> {
return this.http.put(this.baseUrl + 'members/edit/set-order/' + order, {});
}
but I'm getting an error when I hit the controller saying:
'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Int32[,]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.\nTo fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.\nPath '', line 1, position 2.'
I think you might need to use List<List<int>> type instead of int[,] in c# from default c# JSON serializer
public async Task<ActionResult> UpdateOrder(List<List<int>> order)
You don't need to go through (manual) de/serialization and you don't need a List<List<int>>. I'm able to pass a 2d array of ints with a payload like [[1,2],[3,4],[5,6]] and the below API interface.
public async Task<IActionResult> Test(int [,] ints)
Isn't it your url in the request? You treat the order like a string to cat to the url and the body is empty. And when the body is empty, you see that error you're getting. I think what you need is:
return this.http.put('yourUrl', order, {});
See put. (assuming Angular)
Related
Can I pass the entire model as a parameter to Url.Action orsimilar?
Actually, I pass a parameter to the controller and I load the model, but I would like to pass entire model.
window.location.replace('#Url.Action("Search", "Search", new { idSong = Model.IDSong })');
Can you. Yes.
You can pass a simple model containing only properties which are values types or string using the overload that accepts object as the 3rd parameter
#Url.Action("Search", "Search", Model)
Would you want to? No.
Internally the method will create a Dictionary based on each properties name and .ToString() value and convert that to a query string. Not only will the resulting url be ugly, if you have a lot of properties, or the values of the properties contain long strings, you could exceed the query string limit and throw an exception. But the main issue is that any properties which are complex objects or collections will cause binding to fail because, for example, a property which is List<string> will generate ..?somePropertyName=System.Collections.Generic.List[string]&....
Pass just the model's ID as your doing now, and get the model again from the repository in your controller.
You can try passing a ViewBag instead:
Url.Action("Search", "Song", new { songId = ViewBag.SongId, songName = ViewBag.SongName})
Controller:
[HttpGet]
public PartialViewResult Search(string songId, string songName)
{
}
Given the following object
Friend Class GetLocationsResult
Public Property X1 As String
Public Property X2 As String
Public Property X3 As String
Public Property X4 As String
Public Property X5 As String
Public Property X6 As Double
Public Property X7 As Double
End Class
And it is declared and instantiated thusly:
Dim objList as List(of GetLocationsResults) = new List(of GetLocationsResults)
And objList is populated via an iterator that churns through a collection of objects/aggregate classes. The iterator just shoves values into a new GetLocationsResult object and then adds it to the list.
And given the NewtonSoft JSONConvert.SerializeObject(objList) results:
{"d":"[{\"X1\":\"Store Name\",\"X2\":\"Address\",\"X3\":\"City\",\"X4\":\"State\",\"X5\":\"Zip\",\"X6\":Coord1,\"X7\":Coord2}]"}
This point has been addressed and is no longer an issue
There are several issues with this result set. First, for whatever odd
reason, the object being named "d" is not acceptable.
How can I specify something other than "d" for the "name" of the json array?
When I attempt to JSON.parse the response, it needs to be in the following format in order to actually get to the data:
resultSet = JSON.parse(data.d);
console.warn(resultSet[0].X1);
Having to say resultSet[0] is, of course, not acceptable.
How do I cause the 'JSONConvert.Serialize' method to not wrap the response in such a way that I have to refer to the first index of the
resulting JSON data so that I can say resultSet.X1 instead of
resultSet[0].X1?
As requested, here is some more detailed information that may be relevant to the issue at hand.
The data is being returned from a WCF service. The exposed method is decorated thusly:
<WebInvoke(Method:="GET", ResponseFormat:=WebMessageFormat.Json)>
and returns type String. The service is being consumed by a desktop application and a mobile platform. The desktop website can have its own method and, in fact, does because we don't want to deal with X1, X2, etc while the mobile platform devs have declared that as necessary. As noted, the method returns a number of results in the form of a custom, aggregate class which is then shoved into a class object which is only a collection of properties. The return statement is thus:
Return JsonConvert.SerializeObject(retVal)
where retVal is a List(of GetLocationsResult)
So while having to access the data via index may be fine for the website, it is not acceptable for the mobile platform. Because each will run their own methods, it is possible to have a unique solution for both if needed.
Three things.
It sounds like you're returning that back through an ASP.NET ASMX
ScriptService or ASPX [WebMethod]. When using one of those
endpoints, you don't need to (and shouldn't) manually serialize the
object into JSON. ASP.NET will do that for you automatically. You don't need to use JSONConvert at all; just return your object as the result. That's why you're seeing all that escaped data after the .d. It's JSON serialized twice.
As WhiteHat mentioned, the .d is a good thing in some situations. It's introduced by default in these ASP.NET JSON services and can't easily be removed on the server-side, but is easy to account for when you parse the response on the client-side.
You are returning a List(of GetLocationResults), which maps to a JavaScript array. That's why you need to use resultSet[0].X1 to access a value in the result. If you want to access that value via resultSet.X1, you need to be sure to return only a single GetLocationResults object instead of a List of them.
Does that help? If you could update your question with a more complete example of your server-side and client-side code, I could give you an example of how to address the preceding three issues.
I made a ajax call from my jsp to servlet. when I want to return string then it is working fine. But I want to send response as a String array then its not working. Is it possible that I can send string array from servlet as a ajax response.
String[] roleAccess=null;
response.setContentType("text/html");
try{
roleAccess=new String[23];
roleAccess[0]="";
roleAccess[1]="checked";
roleAccess[2]="";
response.getWriter().write(roleAccess.toString());---this part I need to change.
Send the ajax response in json format by encoding the array in json and return it.
You can use Gson and then encode your array like:
String jsonRoleAccess = new Gson().toJson(roleAccess, roleAccess.class);
response.getWriter().write(jsonRoleAccess);
// OR do a one liner:
response.getWriter().write(new Gson().toJson(roleAccess, roleAccess.class));
And on the Javascript end, you can access it as a json object
// Assuming you've read the ajax response into var roleAccess
var checked = roleAccess[1];
You want to marshall the array as a JSON data type. The format returned by Java's array class is not in a format that JavaScript understands.
You should also wrap your array inside of an Object because of a security issue of passing top-level arrays back as JSON.
See Why are top level json arrays a security risk
Write it out to JSON instead. Javascript can't understand the result of a Java array's toString() method ([Ljava.lang.String;#5527f4f9), but I know it can understand JSON.
If you're only ever going to be using a string array and you don't want to use any more libraries:
public static String toJSON(String[] array)
{
String json = "[\"";
for (String s : array)
{
json += s + "\",\"";
}
return json.substring(0, json.length() - 2) + "]";
}
Depending on what Javascript framework you're using on your client-side, your JSON will be available as the xmlHttpRequestObject.responseText. AngularJS stores it in the $http.get().success method's first data parameter. jQuery stores it in the $.ajax({success}) method's first data parameter. Angular and jQuery automatically validate and eval it to an [object Object] for you, but xmlHttpRequestObject.responseText doesn't.
I'm getting encoded data from the server, which is encoded using .NETs WebUtility.HtmlEncode.
This data is then displayed and needs to be sent back to the server for some operations. During this time, it is converted to JSON before being sent over using JSON.stringify. All works fine so far.
However, once this reaches the server, it is rejected due to being potentially dangerous. The object that is converted to JSON can have strings with special chars such as -
"This is John's account" originally "This is John's account"
Or "John earns in ¥" originally "John earns in ¥"
My belief is that these encoded string values are interfering with the JSON being properly formed.
Is there any way in Javascript that I can JSONify HTML encoded strings?
EDIT: In case it's not clear, the data is already encoded when i do JSON.stringify(data).
An example of my data -
row[0] = {column1, column2, column3}
Where each column is an HTML encoded string such as "This is John's account"
Considering that a JSON object with a string would look like this
{ 'member1' : 'some string with ¥' }
I don't believe it's the JSON at fault. It is far more likely that you are passing the JSON object to a method via GET instead of POST.
As a particular example, the Microsoft MVC3 framework will throw an error about it being unsafe if you submit JSON via a GET method and don't specify to allow GET behavior.
The reason for this can be seen in this answer.
I think you can achieve this functionality in three steps:
Create a partial view.
Call this partial view by passing your string values in it and perform action there.
Return your partial view via JSON and replace it with old one.
But returning the partial view via JSON is bit tricky, I mean you cannot just return the partial view via JSON. First you need to convert the partial view in string and the return this string. Below method will you how to achieve this:
public string RenderRazorViewToString(string viewName, object model)
{
ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
This method will convert the partial view in string and return it back to server via JSON. You need to pass to parameter in it, first is the partial view name and second is model. Hope you will get solution of your problem by this.
The solution in the end, was more of a hack, I added an annotation -
[ValidateInput(false)]
to my function on the back-end, so that it wouldn't try to validate my JSON string.
I'm trying to pass data to my controller using Ajax and JSON.
I've got an HTML table and I've got to send multiple coordinates of that table to my controller. So I made a Javascript array containing anonymous objects of this kind :
{
DAY: someIndex,
HOUR: someOtherIndex
}
and let this array be called coordinates, I serialized it like this:
JSON.stringify(coordinates)
so then in an ajax call (type: POST) I used data: JSON.stringify(coordinates).
In my document ready I used :
$.ajaxSetup({
headers : {
Accept : "application/json; charset=utf-8"
}
});
And my controller looks like this:
#RequestMapping(value = "/{id}", method = RequestMethod.POST)
public #ResponseBody
String update(#PathVariable int id, #RequestBody String coordinates, HttpServletResponse response) {
// Do something here to convert it in my complex structure
}
However I don't know what the type should be for the parameter coordinates.
I'm using GSON. And I wasn't able to deserialize it easily. I tried using this solution, but it wouldn't work. (Kept asking to cast types for some reason.)
Since I didn't think it'd be possible to deserialize this correctly, I tried to serialize the coordinates as another format (just a JSON array of strings where the coordinates are split by a token (;) here
So my array the javascript objects are created like this in a foreach:
coordinates.push( someIndex.toString() + ";" + someOtherIndex.toString() );
And I kept the stringify part.
So now when I POST the data to my controller, I output the value with System.out.println(coordinates) and the output looks weird.
%5B%220%3B8%22%5D=
for this object in the Javascript console : ["0;8"].
So my questions :
Is this a good approach?
Is it possible to deserialize a JSON array into some java types? Such as List<Coordinate> ? ( I've tried using this type instead of String in my controller, but it would give me an error 415 - Unsupported media type)
If I'm using the String approach, is there a way to translate that gibberish into something I want?
You get %5B%220%3B8%22%5D= on server side, cause jQuery by default serializes data to query string.
You need to set the content type of the request to application/json using contentType jQuery option.
Then you'll probably want to take a look at some implementation of GsonHttpMessageConverter for simpler RequestBody conversion. Here is one and it looks like there's one in spring for android so maybe you can use that.