Why is my complex [FromBody] parameter null? - asp.net-web-api2

I am having trouble with the [FromBody] parameter of my method not binding.
example C#:
[Route("api/path")]
[HttpPost]
public void Post([FromBody] ComplexType param)
{
// param is null
}
public class ComplexType
{
public string name { get; set;}
}
I've checked the POST body content and content-type and it looks correct.
Why is it null despite throughly checking that the data being posted and content type all match what is expected?
N.B. This is a deliberatly vague question since I was having a lot of trouble diagnosing an issue and I couldn't find a suitable question and answer.
When I eventually found the problem I kicked myself for it, but I feel the need to share how I found the problem to hopefully spare others the pain.
As it happens there may well be nothing wrong with the example given.

In my case there was a problem with the definition of the complex type, I had a parameter marked as string while it should have been string[] and so the JSON parsed did not match the model.
The important part though is how I found this out:
When debugging any API method there is the magic ModelState property.
This property gives you information about any failures that occur while binding the data received to the expected parameters.
e.g:
here we can see the parameter (uploaded), and the property within that parameter which failed to bind correctly.
Check the definition of that property and you'll probably find an error.

Related

Checking for an optional header in a SignalR hub

In a SignalR hub method, Context.Headers provides a INameValueCollection with the request headers. INameValueCollection has just three members:
string this[string key] { get; }
string Get(string key);
IEnumerable<string> GetValues(string key);
Unfortunately, none of them are documented. If you want to get a header but not throw an exception if it doesn't exist, what do you use? I'm guessing Get, but it sure would be nice if the author had bothered to document these details.
One thing I like about the "old" Microsoft was that even if a bit verbose, its documentation covered nearly all the semantics. SignalR was a wonderful, rapid development, but it would be even better if it retained that old-school diligence.
Perhaps I'm missing something. Are the semantics documented somewhere? Or does someone know and care to document them here as a quick and dirty workaround?
Had the same problem and in the end I looked it up in the github source which takes you System.Collections.Specialized.NameValueCollection
(there are other implementation of INameValueCollection as well but the one linked seems to be used in the request)
In short:
string this[string key] { get; }
string Get(string key);
A String that contains the comma-separated list of values associated with the specified key, if found; otherwise, null.
IEnumerable<string> GetValues(string key);
A String array that contains the values associated with the specified key from the NameValueCollection, if found; otherwise, null.

WCF result deserializing to default values for value types in a list of key/value pairs

I have a WCF service and the result is a custom TimeSeries class defined as:
[DataContract]
public class TimeSeries
{
[DataMember]
public string Name { get; set; }
[DataMember]
public List<KeyValuePair<DateTime, double>> Data { get; set; }
}
My service method creates an array of these objects to return. Debugging the service method, I can see that an array containing one of these objects is created correctly (it has a name and 37 vk pairs of data). Using Fiddler, I can see that the object is being serialized and sent (the data is still correct in the HTTP response). However the problem comes when on the client I check the result object and it is incorrect. Specifically, I get a TimeSeries object with the correct name, and the correct number of of kv pairs, but they contain the default values for each DateTime and double (ie 01/01/0001 12:00AM & 0.0).
My client is Silverlight v4 and I am using an automagically generated service reference. The problem appears to be related to deserialization. Anyone have any thoughts as to why it is doing this, what I am missing, or how I can fix it?
As it is stated in Serializing a list of Key/Value pairs to XML:
KeyValuePair is not serializable, because it has read-only properties
So you need your own class, just like the answer on that page says.
An alternative rather than using your own class is to use a Dictionary<DateTime,double> instead which seems to serialize and deserialize fine.

Handling WCF Faults

I am working on a client that is consuming a WCF service. In various cases, the service simply raises a FaultException with an associated message informing of the reason behind the given fault.
Some of these faults are things that can be handled by our client application, but I'm hesitant to simply try and perform some string matching on the FaultExceptions Message or Reason to determine if it is something we can cater for or not.
I was hoping that the FaultCode on FaultException could be used to identify a specific type of Fault that we could handle, but it seems that this is purely to identify a handful of SOAP faults. Please correct me if my interpretation of this is incorrect.
I know that it could be that a FaultException could be raised, but I feel it is unrealistic to expect that a new type should be created for each reason behind a fault.
How do you handle this situation. As a contrived example. Consider a service that provides the following methods;
RecordDetails GetRecordById(string id)
void Add(RecordDetails record)
void Update(RecordDetailsUpdateRequest rdur)
Now in the example above, if you call GetRecordById with an id that doesn't exist, you receive a FaultException with a Message stating "Record cannot be found". Similarly, if you call Add for a record that already exists, or Update for a record that doesn't exist, you simply get a FaultException with a Message/Reason detailing the reason for failure. I need to know if a record exists or not to determine whether I should update or insert. As I mentioned, I'm hesitant to simply match on strings as I have no control over whether they will remain the same or not.
What would you expect in this situation (a type associated with the FaultException detailing RecordNotFoundException etc) or some generic type associated with FaultException that defines specific details relating to the error. For example, a RecordOperationExcpetion class with members Code (a constant or enum identifier of the reason for failure), along with a user friendly message.
At least this way, I could identify the error cause without having to resort to string matching.
Your thoughts are appreciated.
I would go with what you said above - a type associated with the FaultException. You can create any number of classes represented as a DataContract to handle various faults, and then assign them to the WCF Service operations.
[DataContract]
public class RecordOperationException
{
private int code;
private string message;
[DataMember]
public int Code
{
get
{
return code;
}
set
{
code = value;
}
}
[DataMember]
public string Message
{
get
{
return message;
}
set
{
message = value;
}
}
}
Then you can assign the this class as a FaultException:
[OperationContract]
[FaultContract(typeof(RecordOperationException))]
RecordDetails GetRecordById(string id)
[OperationContract]
[FaultContract(typeof(RecordOperationException))]
void Add(RecordDetails record)
[OperationContract]
[FaultContract(typeof(RecordOperationException))]
void Update(RecordDetailsUpdateRequest rdur)
You can then throw the appropriate FaultException in your methods, as desired.
This will eliminate the need to compare strings (which is a good idea, IMO).
I always use FaultExceptions and advertise them as part of the OperationContract, as your code does.
However, I think that there is more to it than this.
We all know that separation of concerns is a good thing, and the way you can achieve this with your services is by created classes that implement IErrorHandler.
These can then be used with your class and your error handling can be separated from your logic, making a cleaner way to do this. It also means that you don't have to repeat identical blocks all over your code.
This can be used with the generic FaultException as well.
A good resource is: http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ierrorhandler.aspx

SerializationException: type not included in serializable type set

In my Google Web Toolkit project, I got the following error:
com.google.gwt.user.client.rpc.SerializationException: Type ‘your.class.Type’ was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.
What are the possible causes of this error?
GWT keeps track of a set of types which can be serialized and sent to the client. your.class.Type apparently was not on this list. Lists like this are stored in .gwt.rpc files. These lists are generated, so editing these lists is probably useless. How these lists are generated is a bit unclear, but you can try the following things:
Make sure your.class.Type implements java.io.Serializable
Make sure your.class.Type has a public no-args constructor
Make sure the members of your.class.Type do the same
Check if your program does not contain collections of a non-serializable type, e.g. ArrayList<Object>. If such a collection contains your.class.Type and is serialized, this error will occur.
Make your.class.Type implement IsSerializable. This marker interface was specifically meant for classes that should be sent to the client. This didn't work for me, but my class also implemented Serializable, so maybe both interfaces don't work well together.
Another option is to create a dummy class with your.class.Type as a member, and add a method to your RPC interface that gets and returns the dummy. This forces the GWT compiler to add the dummy class and its members to the serialization whitelist.
I'll also add that if you want to use a nested class, use a static member class.
I.e.,
public class Pojo {
public static class Insider {
}
}
Nonstatic member classes get the SerializationException in GWT 2.4
I had the same issue in a RemoteService like this
public List<X> getX(...);
where X is an interface. The only implementation did conform to the rules, i.e. implements Serializable or IsSerializable, has a default constructor, and all its (non-transient and non-final) fields follow those rules as well.
But I kept getting that SerializationException until I changed the result type from List to X[], so
public X[] getX(...);
worked. Interestingly, the only argument being a List, Y being an interface, was no problem at all...
I have run into this problem, and if you per chance are using JPA or Hibernate, this can be a result of trying to return the query object and not creating a new object and copying your relavant fields into that new object. Check the following out, which I saw in a google group.
#SuppressWarnings("unchecked")
public static List<Article> getForUser(User user)
{
List<Article> articles = null;
PersistenceManager pm = PMF.get().getPersistenceManager();
try
{
Query query = pm.newQuery(Article.class);
query.setFilter("email == emailParam");
query.setOrdering("timeStamp desc");
query.declareParameters("String emailParam");
List<Article> results = (List<Article>) query.execute(user.getEmail
());
articles = new ArrayList<Article>();
for (Article a : results)
{
a.getEmail();
articles.add(a);
}
}
finally
{
pm.close();
}
return articles;
}
this helped me out a lot, hopefully it points others in the right direction.
Looks like this question is very similar to what IsSerializable or not in GWT?, see more links to related documentation there.
When your class has JDO annotations, then this fixed it for me (in addition to the points in bspoel's answer) : https://stackoverflow.com/a/4826778/1099376

Why am I getting this WCF Error Message?

I am getting the error below when I call my WCF service. What am I missing here?
'System.String[]' with data contract name
'ArrayOfstring: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.
{"There was an error while trying to serialize parameter
http://tempuri.org/:myEntity. The InnerException message was
'Type 'System.String[]' with data contract name
'ArrayOfstring: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."}
From what I gather, you have a WCF function that has a parameter named 'myEntity'. I'm assuming that the type of myEntity is a user-defined class and is adorned with the DataContract attribute, as it should be. I'm also assuming that the type of myEntity has a member field that is a string array. Let's assume that all of this is true (again, it'd be really helpful if you could post your code).
Ordinarily, string arrays, i.e., string[], will serialize just fine. But, in some cases (see here and here), you may have to add it to the list of known types in order for WCF to serialize everything correctly.
To do this, add the following:
[DataContract]
[KnownType(typeof(string[]))]
public class YourClassNameHere
{
}
You haven't posted the code, so my answer is based on the assumption that you have a class myEntity which you are trying to serialize. Try using a KnownTypeAttribute for the class
e.g.
[KnownType(typeof(myEntity))]
You can refer to the following MSDN link:
KnownTypeAttribute
Yes. As explained in the previous post, The issue occurs if you pass an array of a Type(which is defined as a DataContract]). you will need to define the array of this class as a seperate type and mark it as data contract.
Wont Work`
[DataContract]
Public class ABC{
}
...
SendData(ABC[])
`
What will work:
Public class Data{ public ABC[] prop{get;set;}}
...
SendData(Data);
In my case, after adding [Serializable] attribute to the MyEntity class. And then the issue came with serialization of the roles string array.
[Serializable]
[KnownType(typeof(string[]))]
public class MyEntity
{
.........
public string roles[]
.........
}
[KnownType(typeof(string[]))] worked like magic!