Convert List to Array for [WebMethod] - arrays

I understand that you cannot return a generic list in a standard .asmx webservice. However I believe you can return an array []. My problem is converting the list to an array. Can someone help?
I have a bunch of Business Object that already return a type List so I am not open to converting the original objects to Arrays...
Here is my WebMethod.
[WebMethod]
public Book[] GetBooksList()
{
List<Book> obj = new List<Book>();
BookDA dataAccess = new BookDA();
obj = dataAccess.GetBooksAll().ToArray(); //error 1 here on conversion
return obj; //error 2 here
}
Error I receive is 2 fold : Cannot implicitly convert type BookDTO.Book [] to GenericList
Cannot implicitly convert type GenericList to

Because you already declared that obj was a list, not an array. Try this instead:
[WebMethod]
public Book[] GetBooksList()
{
BookDA dataAccess = new BookDA();
List<Book> obj = dataAccess.GetBooksAll();
return obj.ToArray();
}
Or better yet:
[WebMethod]
public Book[] GetBooksList()
{
var dataAccess = new BookDA();
var obj = dataAccess.GetBooksAll().ToArray();
return obj;
}

Related

MVC Custom Validation String Array Client Side

There are examples out there of custom MVC validators that take an array parameter, but only server side - none of them show an example of implementing the client side with array parameter.
The problem is instead of outputting the array's contents in the html data- attribute, it outputs "System.String[]":
data-val-total-propertynames="System.String[]"
Here is my attribute class:
public class TotalAttribute : ValidationAttribute, IClientValidatable
{
private String[] PropertyNames { get; set; }
public TotalAttribute(String[] propertyNames)
{
PropertyNames = propertyNames;
}
protected override ValidationResult IsValid(object value, ValidationContext context)
{
float total = 0;
foreach (var propertyName in PropertyNames)
total += (float)context.ObjectInstance.GetType().GetProperty(propertyName).GetValue(context.ObjectInstance, null);
if (total != (float)value)
return new ValidationResult(FormatErrorMessage(context.DisplayName), new[] { context.MemberName });
return ValidationResult.Success;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = ErrorMessageString,
ValidationType = "total",
};
rule.ValidationParameters["propertynames"] = PropertyNames;
yield return rule;
}
}
Here it is implemented in the model:
[Total(new string[] { "SomeOtherField1", "SomeOtherField2" }, ErrorMessage = "'Line12Balance' must equal total of 'SomeOtherField1' and 'SomeOtherField2'")]
public decimal? Line12Balance { get; set; }
Here is the html data-val attribute output:
data-val-total-propertynames="System.String[]"
What am I doing wrong?
You get "System.String[]" string because the value of ValidationParameters["propertynames"] is written by calling ToString on it, so string[] variable returns "System.String[]" in this case. If you need to output specific value you need to format it by yourself in your validation attribute. For example, change
rule.ValidationParameters["propertynames"] = PropertyNames;
to
rule.ValidationParameters["propertynames"] = string.Join(",", PropertyNames);
and you will get
data-val-total-propertynames="SomeOtherField1,SomeOtherField2"
As Alexander mentioned in his answer, the issue you encountered is that string[] doesn't have its own ToString() implementation, and uses the base object.ToString() implementation, which just displays the type of the object rather than the contents of your array.
So you've got to somehow serialize your string array so that it can be stored in a string to then parse in your client-side JavaScript.
If you're already using JSON.Net in your solution (as many are), you can also do this by JSON serializing the array on the server side, then parsing the JSON client-side.
i.e. server-side:
rule.ValidationParameters["propertynames"] = JsonConvert.SerializeObject(PropertyNames);
Client-side: (
$.validator.addMethod('rule', function(value, element, params) {
var propertynames = JSON.parse(params.propertynames);
// do your validation
});
That prevents you from having to escape commas/delimiters in your parameters.

JAXB JSON array not in object

I would like to know how I can use JAXB to consume and produce a JSON array from a List without being included in an object:
[ "element1", "element2", "element3"]
Currently I have being only able to do so by including it in an object:
{ "elements" : [ "element1", "element2", "element3"] }
The code used is more or less the one below.
#XmlRootElement(name = "elements")
public class ElementListSerializerHelper
#XmlElement(name = "elements")
#JsonProperty(value = "elements")
public List<String> list;
public ElementsListSerializerHelper() {
list = new ArrayList<String>();
}
public ElementsListSerializerHelper(List<String> list) {
this.list = new ArrayList<String>(list);
}
}
Any help is more than welcome. The option I'm also thinking is generating/parsing a string based on jackson library.

Unity C#: how to convert an Array of a class into JSON [duplicate]

This question already has answers here:
Serialize and Deserialize Json and Json Array in Unity
(9 answers)
Closed 5 years ago.
I need to save multiple player's data. I am doing it by making an array of PlayersInfo class and trying to convert the array into JSON. here is my code
PlayerInfo[] allPlayersArray = new PlayerInfo[1];
allPlayersArray[0] = new PlayerInfo();
allPlayersArray[0].playerName = "name 0";
string allPlayersArrayJson = JsonUtility.ToJson(allPlayersArray);
print(allPlayersArrayJson);
PlayerPrefs.SetString("allPlayersArrayJson", allPlayersArrayJson);
string newJson = PlayerPrefs.GetString("allPlayersArrayJson");
print(newJson);
PlayerInfo[] newArray = new PlayerInfo[1];
newArray = JsonUtility.FromJson<PlayerInfo[]>(newJson);
print(newArray[0].playerName);
First two print statements returns "{}" and 3rd one gives null reference error. TIA
Like I said in my comment, there is no direct support. Helper class is needed. This is only reason I am making this answer is because you are still having problems even after reading the link I provided.
Create a new script called JsonHelper. Copy and paste the code below inside it.
using UnityEngine;
using System.Collections;
using System;
public class JsonHelper
{
public static T[] FromJson<T>(string json)
{
Wrapper<T> wrapper = UnityEngine.JsonUtility.FromJson<Wrapper<T>>(json);
return wrapper.Items;
}
public static string ToJson<T>(T[] array)
{
Wrapper<T> wrapper = new Wrapper<T>();
wrapper.Items = array;
return UnityEngine.JsonUtility.ToJson(wrapper);
}
[Serializable]
private class Wrapper<T>
{
public T[] Items;
}
}
The code in your question should now work. All you have to do is to replace all JsonUtility words with JsonHelper. I did that for you below:
void Start()
{
PlayerInfo[] allPlayersArray = new PlayerInfo[1];
allPlayersArray[0] = new PlayerInfo();
allPlayersArray[0].playerName = "name 0";
string allPlayersArrayJson = JsonHelper.ToJson(allPlayersArray);
print(allPlayersArrayJson);
PlayerPrefs.SetString("allPlayersArrayJson", allPlayersArrayJson);
string newJson = PlayerPrefs.GetString("allPlayersArrayJson");
print(newJson);
PlayerInfo[] newArray = new PlayerInfo[1];
newArray = JsonHelper.FromJson<PlayerInfo>(newJson);
print(newArray[0].playerName);
}
Based on the JsonUtility documentation, naked arrays are not supported. Put the array inside a class.
Internally, this method uses the Unity serializer; therefore the
object you pass in must be supported by the serializer: it must be a
MonoBehaviour, ScriptableObject, or plain class/struct with the
Serializable attribute applied.
In general, you'll use this to serialize MonoBehaviour objects, or a custom class/struct with the Serializable attribute.
YES! It is not supported currently but there is always a work around. Use this class :
public static class JsonHelper
{
public static T[] getJsonArray<T>(string json)
{
try
{
string newJson = "{ \"array\": " + json + "}";
Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>> (newJson);
return wrapper.array;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
[Serializable]
private class Wrapper<T>
{
public T[] array = null;
}
}
I would use Json.NET
PlayerInfo[] allPlayersArray = new PlayerInfo[] { p1, p2, p3 };
string json = JsonConvert.SerializeObject(allPlayersArray);
More On SerializeObject
(Code example not yet tested)

How can I convert to int array to dictionary?

Do you have any idea how I can do it?
public override IDictionary<int, DateTime> GetList()
{
var AdList = new Dictionary<int, DateTime>();
AdList = client.GetAdList(loginTicket); //it returns int array.
// I've also tried AdList =client.GetAdList(loginTicket).ToDictionary<int, DateTime>(); it doesn't work..
return AdList;
}
Well, don't have information about how you're going to get dates, or where do you get em from, but i can suggest some code:
public static IDictionary<int, DateTime> GetList()
{
var AdList = new Dictionary<int, DateTime>();
var intArr = GetAdList(); //get your int[] array or List<int>
//if method GetAdList() returns List<int> use this line
intArr.ForEach(a => AdList.Add(a, DateTime.Now));
//otherwise if method returns int[] array use this line
Array.ForEach(intArr, a => AdList.Add(a, DateTime.Now)); //populate dictionary with array elements as keys and DateTime.Now as values
return AdList;
}

Silverlight: Webservice method returning ObservableCollection instead of Generic List

I have a webservice that calls a method that returns a generic list of class BodyPartUrls like so:
public List<BodyPartUrls> getCharacterClassBody(int characterClassID)
{
var bpulst = new List<BodyPartUrls>();
var iqcb = ydc.ClassBodies.Where(cb => cb.characterClassID == characterClassID);
foreach (var icb in iqcb)
{
var bpu = new BodyPartUrls();
bpu.bodyPartName = icb.BodyPart.bodyPartName;
bpu.bodyName = icb.Body.bodyName;
bpu.puppetID = characterClassID;
bpulst.Add(bpu);
}
return bpulst;
}
BodyPartUrls only consists of string and integer properties, note that ydc is refering to a datacontext. This the code in the webservice :
[WebMethod]
public List<BodyPartUrls> getCharacterClassBody(int characterClassID)
{
return b.getCharacterClassBody(characterClassID);
}
Now to call the method in silverlight I utalised the following code :
public void initialiseBodiesSoapClientClient()
{
string webServiceUrl = pu.GetUrlForResource("Bodies.asmx");
System.ServiceModel.BasicHttpBinding binding = new System.ServiceModel.BasicHttpBinding();
EndpointAddress endpoint = new EndpointAddress(webServiceUrl);
bsc = new BodiesRef.BodiesSoapClient(binding, endpoint);
bsc.getCharacterClassBodyCompleted += new EventHandler<Yambushi.BodiesRef.getCharacterClassBodyCompletedEventArgs>(bsc_getCharacterClassBodyCompleted);
}
The method pu.GetUrlForResource get's the url of where the webservice is hosted, the following is method bsc_getCharacterClassBodyCompleted :
void bsc_getCharacterClassBodyCompleted(object sender, Yambushi.BodiesRef.getCharacterClassBodyCompletedEventArgs e)
{
bpulist = e.Result;
}
bpulist is a generic list of BodyPartUrls, for some reason e.Result is returning ObservableCollection instead of the generic list. I have similar code to retreive other generic lists that work fine so I really can't understand why this is acting differently.
Click Configure Service Reference. Under the Data Type section you can select what type you want collections or dictionaries to return as.

Resources