WCF Dictionary<string, object> serialization - silverlight

I have a service that has a method like this
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MyService
{
[OperationContract]
public object MyMethod(string param1, string param2, object[] myarray)
{
//do stuff
return result;
}
}
I call my method from my code like this:
public Dictionary<string, object> MyDictionary{ get; set; }
serv.MyMethodCompleted += new EventHandler<MyServiceReference.MyMethodCompletedEventArgs>(serv_MyMethodCompleted);
serv.MyMethodAsync("param1","param2", new ObservableCollection<object>(){MyDictionary});
void serv_MyMethodCompleted(object sender, MyServiceReference.MyMethodCompletedEventArgs e)
{
//Happy happy joy joy
}
Everithing craches with this error:
There was an error while trying to
serialize parameter :myarray. The
InnerException message was 'Type
'System.Collections.Generic.Dictionary`2[[System.String,
mscorlib, Version=2.0.5.0,
Culture=neutral,
PublicKeyToken=7cec85d7bea7798e],[System.Object,
mscorlib, Version=2.0.5.0,
Culture=neutral,
PublicKeyToken=7cec85d7bea7798e]]'
with data contract name
'ArrayOfKeyValueOfstringanyType:http://schemas.microsoft.com/2003/10/Serialization/Arrays'
is not expected. Add any types not
known statically to the list of known
types - for example, by using the
KnownTypeAttribute attribute or by
adding them to the list of known types
passed to DataContractSerializer.'.
Please see InnerException for more
details.
public System.IAsyncResult BeginCallMethod(string param1, string param2, System.Collections.ObjectModel.ObservableCollection<object> myarray, System.AsyncCallback callback, object asyncState) {
object[] _args = new object[3];
_args[0] = param1;
_args[1] = param2;
_args[2] = myarray;
System.IAsyncResult _result = base.BeginInvoke("MyMethod", _args, callback, asyncState); <--here it craches
return _result;
}
what did I did wrong? how can I fix this?

The myArray parameter and the return value needs to be a strongly typed and attributed with DataContract and DataMember attributes. The myArray should be collection like IEnumerable<Item> that can be serialized:
[DataContract]
class Item
{
[DataMember]
public string Name {get;set;}
[DataMember]
public double Cost {get;set;}
}

Related

Dealing with AutoFixture ConstructorInitializedMemberAssertion and a read-only property initialized inside the constructor

I want to verify a class using ConstructorInitializedMemberAssertion and a read-only property CreatedAt that is initialized to a default value inside the constructor:
public class MyClass
{
public MyClass(string name)
{
Name = name;
CreatedAt = DateTime.UtcNow;
}
public string Name { get; private set; }
public DateTime CreatedAt { get; private set; }
}
var fixture = new Fixture();
var ctorAssertion = fixture.Create<ConstructorInitializedMemberAssertion>();
ctorAssertion.Verify(typeof(MyClass));
This test throws the following exception:
AutoFixture.Idioms.ConstructorInitializedMemberException: No constructors with an argument that matches the read-only property 'CreatedAt' were found
I looked in the docs, but did not find any sample like that. I'm rather new with AutoFixture, so I may miss something.
How to exclude it from assertion or is there other way to deal with it?

Nancy.Testing exception thrown when testing POST route with Json content

I'm attempting to write tests for my Nancy module, and it's not going too well so far.
Attempting to test two separate actions, one GET which is working just fine and a POST with application/json content in the request.
I'm slightly stabbing in the dark as to how the test for the POST should be written, but have come up with the following:
using NUnit.Framework;
[TestFixture]
public class MyModuleTests
{
Browser browser;
[SetUp]
public void SetUp()
{
browser = new Browser(with =>
{
with.Module<MyModule>();
with.EnableAutoRegistration();
});
}
[Test]
public void Can_Get_View()
{
// When
var result = browser.Get("/View", with => with.HttpRequest());
// Then
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); // this works
}
[Test]
public void Can_Post_to_EvaluateDocument()
{
var testData = new List<FakeInputValue>(){new FakeInputValue()
{
Name = "a",
Value = 0.35
}};
// When
var result = browser.Post("/Evaluate", with => //the exception is thrown on this line
{
with.HttpRequest();
with.JsonBody<IList<FakeInputValue>>(testData);
});
// Then
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode);
}
}
class FakeInputValue
{
public string Name { get; set; }
public double Value { get; set; }
}
Unfortunately this throws the following juicy error
1) Test Error : MyModuleTests.Can_Post_to_EvaluateDocument
System.Exception : ConfigurableBootstrapper Exception
----> Nancy.RequestExecutionException : Oh noes!
----> System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
----> System.MissingMethodException : No parameterless constructor defined for this object.
at Nancy.Testing.PassThroughStatusCodeHandler.Handle(HttpStatusCode statusCode, NancyContext context)
at Nancy.NancyEngine.CheckStatusCodeHandler(NancyContext context)
at Nancy.NancyEngine.<>c__DisplayClass8.<HandleRequestInternal>b__6(Task`1 completeTask)
at Nancy.NancyEngine.HandleRequestInternal(Request request, Func`2 preRequest)
at Nancy.NancyEngine.HandleRequest(Request request, Func`2 preRequest)
at Nancy.Testing.Browser.HandleRequest(String method, String path, Action`1 browserContext)
at MyModuleTests.Can_Post_to_EvaluateDocument() in line 49
--RequestExecutionException
at Nancy.NancyEngine.InvokeOnErrorHook(NancyContext context, ErrorPipeline pipeline, Exception ex)
--TargetInvocationException
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Nancy.ModelBinding.DefaultBodyDeserializers.JsonBodyDeserializer.Deserialize(String contentType, Stream bodyStream, BindingContext context)
at Nancy.ModelBinding.DefaultBinder.Bind(NancyContext context, Type modelType, Object instance, BindingConfig configuration, String[] blackList)
at Nancy.ModelBinding.DynamicModelBinderAdapter.TryConvert(ConvertBinder binder, Object& result)
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at MyModule.<.ctor>b__9(Object parameters)
at CallSite.Target(Closure , CallSite , Func`2 , Object )
at Nancy.Routing.Route.<>c__DisplayClass4.<Wrap>b__3(Object parameters, CancellationToken context)
--MissingMethodException
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at Nancy.Json.JavaScriptSerializer.ConvertToObject(IDictionary`2 dict, Type type)
at Nancy.Json.JavaScriptSerializer.ConvertToList(ArrayList col, Type type)
at Nancy.Json.JavaScriptSerializer.ConvertToType[T](Object obj)
Any help as to (a) how I might better test POST routes with application/json content in Nancy or (b) resolve this particular error!
edit 1
My module is as follows:
public class MyModule : NancyModule
{
public MyModule()
{
Get["/View"] = parameters =>
{
return View["myView"];
};
Post["/Evaluate"] = parameters =>
{
this.inputs = this.Bind<List<InputValue>>();
var evaluator = new Evaluator(inputs);
return Response.AsJson<List<Evaluation>>(evaluator.Evaluate());
};
}
}
After a lot of debugging and frustrated outputting to Console, I've tracked down the cause of the bug. The issue was with the lack of public setters in my InputValue class.
The buggy class was written as so:
public class InputValue
{
private readonly string _name;
private readonly double _value;
public InputValue(string inputName, double inputValue)
{
this._name = inputName;
this._value = inputValue;
}
public string Name
{
get
{
return this._name;
}
}
public double Value
{
get
{
return this._value;
}
}
}
I resolved the issue quite simply by allowing the properties to be set, as so:
public class InputValue
{
public string Name
{
get;
set;
}
public double Value
{
get;
set;
}
}

Mixin annotation not getting honored when passed as a parameter

I have a third party class SpecialObject as:
public class SpecialObject {
private String name;
private Integer id;
private Date date;
public String getFoo() {return "foo";} //Outlier
public String getName() { return name;}
public Integer getId() {return id;}
public Date getDate() {return date;}
public void setName(String name) {this.name = name;}
public void setId(Integer id) {this.id = id;}
public void setDate(Date date) {this.date = date;}
}
I wish to only project out name and date properties when serializing it. Using the magic of MixinAnnotation from Jackson, I created a Mixin interface as:
#JsonAutoDetect(getterVisibility = Visibility.NONE)
public interface SpecialObjectMixin {
#JsonProperty
public String getName();
#JsonProperty
public Date getDate();
}
In order to facilitate handling of this SpecialObject as parameter, I have also defined a SpecialObjectHandler which implements the fromString() method.
#Override
public SpecialObject fromString(String json) {
try {
return objectMapper.readValue(json, SpecialObject.class);
} catch (IOException exception) {
throw new IllegalArgumentException("Unable to write JSON output",
exception);
}
}
When the deserializer invokes this method, the objectMapper throws an error as
Caused by: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "foo" (Class com.kilo.SpecialObject), not marked as ignorable
at [Source: java.io.StringReader#2d2217da; line: 1, column: 60] (through reference chain: com.kilo.SpecialObject["foo"])
at org.codehaus.jackson.map.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:53)
at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:267)
at org.codehaus.jackson.map.deser.std.StdDeserializer.reportUnknownProperty(StdDeserializer.java:673)
at org.codehaus.jackson.map.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:659)
at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty(BeanDeserializer.java:1365)
at org.codehaus.jackson.map.deser.BeanDeserializer._handleUnknown(BeanDeserializer.java:725)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:703)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:580)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2732)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1863)
at com.kilo.SpecialObjectHandler.fromString(SpecialObjectHandler.java:34)
My question is that is there a way that I can have the objectMapper (org.codehaus.jackson.map.ObjectMapper) also honor annotations from the Mixin where I had configured it to only deal with name and date? Feel free to point out something elementary that I may have overlooked. Thanks in advance!
It was a problem with configuration. The mixin was only set on the serialization config and not on the deserialization config causing the issue. Setting it on both configs solves the problem.

Access Arrays inside Java Objects

How do I obtain values of an array that is located inside a java object in a jsp page?
I have set an object attribute so that in the jsp page I can call the object like so
${obj.property}
My question is how would I obtain property String [] example from Object obj?
<c:forEach var="prop" items="${obj.example}">
<td>${prop}</td>
</c:forEach>
I get Errors that tell me the class obj.Obj does not have the property property 'example'
and obviously I don't get the data out.
Actual errors:
org.apache.jasper.JasperException: javax.el.PropertyNotFoundException: The class 'roommate.Roommate' does not have the property 'favProfessors'.
javax.el.PropertyNotFoundException: The class 'roommate.Roommate' does not have the property 'favProfessors'
And my actual class:
package roommate;
public class Roommate{
public String firstname;
public String lastname;
public String gender;
public String place;
public String[] favProfessors;
public Roommate(String fname, String lname, String roommateGender, String hangout,String[] professors) {
firstname= fname;
lastname= lname;
gender= roommateGender;
place= hangout;
favProfessors= professors;
}
public String getFirstname()
{
return firstname;
}
public void setFirstname(String newFirstname)
{
this.firstname = newFirstname;
}
public String getLastname()
{
return lastname;
}
public void setLastname(String newLastname)
{
this.lastname = newLastname;
}
public String getGender()
{
return gender;
}
public void setGender(String newGender)
{
this.gender = newGender;
}
public String getHangout()
{
return place;
}
public void setHangout(String newPlace)
{
this.place = newPlace;
}
public String[] getProfessors()
{
return favProfessors;
}
public void setProfessors(final String[] newfavProfessors)
{
this.favProfessors = newfavProfessors;
}
public void addRoommate(String fname, String lname, String roommateGender, String hangout,String[] professors)
{
}
}
I create the object in my servlet as well ass the Atrribute
String [] profArray = request.getParameterValues("professor");
Roommate roommate= new Roommate(
session.getAttribute("fname").toString(),
session.getAttribute("lname").toString(),
session.getAttribute("gender").toString(),
session.getAttribute("hangout").toString(),
profArray);
session.setAttribute("roommate",roommate);
I asked this earlier but did not receive a clear answer. I think my issue is in pulling the data out in the jsp alone in my forEach that I mentioned at the top
javax.el.PropertyNotFoundException: The class 'roommate.Roommate' does not have the property 'favProfessors'
Java is right. You do not have a getFavProfessors() method in that class. It's instead the following:
public String[] getProfessors()
{
return favProfessors;
}
You have 2 options: use ${roommate.professors} instead, or fix the getter method name to be getFavProfessors().
In contrary to what most starters think, EL does not access private properties directly. EL just calls the public getter/setter methods according the Javabeans specification. The real private property behind it can have a completely different name or even not exist at all.

Why can't I add attributes when serializing ObservableCollection<T>?

I'm trying to extend an ObservableCollection with a few custom properties and have it serialize. However, I can't seem to get it to serialize these properties. I'm using .NET 4.0 where they fixed the serialization issues of ObservableCollection, but am still having problems. My hunch is that GetObjectData is being called on the base class and not mine. Any ideas?
[Serializable]
[XmlRoot(ElementName = "MyCollection")]
public class MyCollection : ObservableCollection<MyItem>, ISerializable
{
private string name;
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", Name);
}
private MyCollection()
{
Name = string.Empty;
}
public MyCollection(string name)
{
Name = name;
}
public MyCollection(SerializationInfo info, StreamingContext context)
{
Name = (string)info.GetValue("Name", typeof(string));
}
[XmlAttribute]
public string Name
{
get { return name; }
protected set
{
string originalName = name;
name = value;
if (originalName != name)
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
public void SaveToFile(string path)
{
string directory = Path.GetDirectoryName(path);
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
XmlSerializer serializer = new XmlSerializer(typeof(MyCollection));
using (TextWriter textWriter = new StreamWriter(path))
{
serializer.Serialize(textWriter, this);
textWriter.Close();
}
}
public static MyCollection LoadFromFile(string path)
{
XmlSerializer deserializer = new XmlSerializer(typeof(MyCollection));
using (TextReader textReader = new StreamReader(path))
{
MyCollection myCollection = (MyCollection)deserializer.Deserialize(textReader);
textReader.Close();
return myCollection;
}
}
}
XML Serialization does not support this scenario. You simply cannot add anything to a class implementing ICollection.
If you require this, then you will have to implement IXmlSerializable and do the work yourself.
Note that you may be confusing XML Serialization with runtime serialization. XML Serialization doesn't care about the [Serializable] attribute or GetObjectData, etc.

Resources