C# WCF Service not picking up properties from ajax post - c#

I have a WCF to save some data to my db. In Dev Tools I can see the request payload as below:
{"OrderId":123456,"Year":"2017","CustomerId":999999,"LicencePlates":[{"licenceNumber":"222222222222222"}]}
My WCF service interface is as below:
[OperationContract]
[WebInvoke(UriTemplate = "/SaveLicenceData", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
void SaveLicenceData(int OrderId, int Year, string CustomerId, LicencePlate[] LicencePlates);
The licence plate class is:
public class LicencePlate
{
[DataMember]
public string LicenceNumber { get; set; }
}
With a breakpoint set, I can see the OrderId getting passed, the Year getting passed and the CustomerId getting passed. However LicenceNumber I keep getting null passed.
I tried making the overall class [Serializable] but the breakpoint isn't even getting hit when I add this. I also tried changing the annotation too [DataMember(Name = "licenceNumber")] but still getting null and then changed the annotation to [JsonProperty] and still getting null.
Is there something stupid I have missed here?

I think you have a case mismatch. In your payload you have
"licenceNumber":"222222222222222"
It should be
"LicenceNumber":"222222222222222"

Related

Customize JSON output from C# Web Service

I have the following output from a C# web service:
{"CallResult":[{"CompanyId":"AAA900134-904","CompanyName":"MID"}]}
I want the output to only contain an array of JSON like the following:
[{"CompanyId":"AAA900134-904","CompanyName":"MID"}]
I'm not sure how to customize the output. Do I have to return a string and customize the JSON manually or is there another way? Thanks.
Without more information, such as actual data example (this json refers to 1 object only), here is what I can suggest:
Create 2 custom classes as follows:
public class CallResultClass
{
public List<InnerClass> CallResult { get; set; }
}
public class InnerClass
{
public string CompanyId { get; set; }
public string CompanyName { get; set; }
}
Then, along with using System.Web.Script.Serialization;, you can deserialize the json as follows:
string json = "{\"CallResult\":[{\"CompanyId\":\"AAA900134-904\",\"CompanyName\":\"MID\"}]}";
JavaScriptSerializer js = new JavaScriptSerializer();
var callres = (CallResultClass)js.Deserialize(json, typeof(CallResultClass));
var companyInfo = callres.CallResult;
If your json contains a list of CallResults, a simple modification to the code can accommodate for that. There is no scenario where modifying the json string would be viable (there is always a clean way).
For reference & examples read JavaScriptSerializer Class.
I figured out a solution.
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "/CallResult/{username}/{company}")]
CallResult_Result[] CallResult(string username, string company);
I had to change
BodyStyle = WebMessageBodyStyle.Wrapped
to
BodyStyle = WebMessageBodyStyle.Bare

POST request with Json body to MVC resful service

Trying to construct valid request to wcf restful service. But whole hour cannot do it, i dont get it why it's not work. Other APis what returns JSON works correctly, i tested them. Now need to fix request API.
I put break point to implementation of AddMeal method but she don't triggered. I think something wrong with my request or with Attributes
//Add Meal
[OperationContract]
[WebInvoke(UriTemplate = "AddMeal",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json, Method = "POST")]
bool AddMeal(string meal);
Your WCF method is expecting a string, however, the model binder will try to bind your JSON to a string which won't work. When using MVC you should use models instead, create a model that represents your JSON data e.g.
public class Meal
{
public DateTime EatedTime { get; set; }
public decimal Amount { get; set; }
public int PatientID { get; set; }
public int MealTypeID { get; set; }
...
}
Then update your signature to expect that model
bool AddMeal(Meal meal)
You should find the data is bound to the meal model.

passing user defined parameters in WCF service causing problems

I am creating a wcf self hosted service. I am using UriTemplate class to customize the urls to methods. the code snippet is given below
public interface ISelfService
{
[WebInvoke(Method = "POST", UriTemplate = "ack/{errorcode}/{uniquefileid}")]
[OperationContract]
void Ack(ErrorCode errorcode, string uniquefileid);
[WebInvoke(Method = "POST", UriTemplate = "filechanged/{metainfo}")]
[OperationContract]
void FileChanged(MetaInformation metainfo);
}
Whenever i run this program i am getting the following error
Operation 'FileChanged' in contract 'ISelfHostService' has a query
variable named 'metainfo' of type 'Natash.Common.MetaInformation',
but type 'Natash.Common.MetaInformation' is not convertible by
'QueryStringConverter'. Variables for UriTemplate query values must
have types that can be converted by 'QueryStringConverter'
Can any one tell me why is this happening?
And, I have not made any modification to the web.config file. Do i need to make any modification there?
MetaInformation is defined as follows
[DataContract]
public struct MetaInformation
{
[DataMember]
public string Author { get; set; }
[DataMember]
public string tags { get; set; }
[DataMember]
public string categories { get; set; }
[DataMember]
public string description { get; set; }
}
try this
public interface ISelfService{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/ack?errorcode={errorcode}&uniquefileid={uniquefileid}")]
void Ack(ErrorCode errorcode, string uniquefileid);
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/filechanged")]
void FileChanged(MetaInformation metainfo);}
From the message you posted it sounds like there are 2 definitions for the MetaInformation class (Gettrix.Common.MetaInformation & Natash.Common.MetaInformation).
It could be that both are in scope for WCF to see when instantiating the service. If so, it might think that the one that does not have a DataContract attribute (probably Natash.Common.MetaInformation) is what you are reffering to and therefore would not be usable for data transfer within the service.

JQuery Posting to WCF Service

Receiving the error "Object reference not set to an instance of an object" when posting JSON data to the below WCF Service.
My guess is the employee object isn't initialised but I'm unsure where that should be done as when I used a string a test it worked just fine.
Any suggestions are greatly appreciated.
Interface (IAccount.cs):
[ServiceContract(Namespace = "AccountService")]
public interface IAccountService
{
[OperationContract, WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
string CreateAccount(Employee employee);
}
[DataContract]
public class Employee
{
[DataMember]
public string firstName { get; set; }
[DataMember]
public string lastName {get; set;}
}
Implementation (AccountService.svc)
AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class AccountService: IAccountService
{
public string CreateAccount(Employee employee)
{
string test = employee.firstName;
return test;
}
}
JSON Post Data:
{"firstName":"Test","lastName":"User"}
OK finally sorted this out, hopefully this helps someone with the same issue.
My initial JSON looked correct but doesn't work:{"firstName":"Test","lastName":"User"}. But by looking at the server trace you can see the inbuilt XML DeSerializer cannot map the elements to the object in the WCF Service method (employee object in my case) and this is the cause of the null reference error.
Putting the form attributes inside an object that matches the name of the service parameter however did the trick: {"employee":{"firstName":"test"}}
By default, WebGet's RequestFormat is set to XML. Set it to Json.

Null values for object properties de-serialized by WCF

I have a WCF web service that used to work fine. Somewhere down the line it stopped and I cant tell why. The code and the interface never changed nor did the web.config (at least not in relation to the web services section). I have a class:
[DataContract]
public class QuizServiceArgs
{
[DataMember(IsRequired = true, Order = 1)]
public int Category1 { get; set; }
[DataMember(IsRequired = true, Order = 2)]
public int Category2 { get; set; }
[DataMember(IsRequired = true, Order = 3)]
public int Category3 { get; set; }
[DataMember(IsRequired = true, Order = 4)]
public int Category4 { get; set; }
}
And the service interface is simple:
public interface IQuizService
{
[OperationContract]
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json)]
ServiceResult Save(QuizServiceArgs answers, string strvalue, int intvalue);
}
The second two params strvalue and intvalue were added only for troubleshooting to see if those were getting deserialized -- and they are. When I hit the service, I get an error saying that I'm missing the Category1 parameter from the request but as you can see this Fiddler screenshot, the values are there.
I can get primitive values to pass in but objects seem to all be instantiated with null or default values. What am I doing wrong?
UPDATE
I never actually got my original question answered which sucks, but Sixto suggested that I switch my serialization to JSON. JSON was the original design but got nixed when I was having trouble with it. After I successfully switched back to JSON, everything was serializing and deserializing properly. Now I am just waiting for this to break for no explanation so I can switch back to XML....
You have a namespace issue. By default, when you create an interface for the servicecontract, it assigns it a namespace. Namespace is like scope for the SOAP xml elements, and if it doesn't fall under the same scope, it thinks it doesn't exist. Chances are the code that posts stoppped providing the namespace(?). You have to refer by it when posting the XML - but I'm not entirely sure what it assigns(something server specific), so it is good practice to always define a namespace, like so:
[ServiceContract(Namespace = "your namespace")]
public interface IQuizService
{
[OperationContract]
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json)]
ServiceResult Save(QuizServiceArgs answers, string strvalue,
int intvalue);
}
And then the posts should have the namespace in the SOAP request.
<Save xmlns="your namespace">.....</Save>
The namespace should also match your service declaration in web.config.
Also need it in the datacontract
[DataContract(Namespace = "your namespace")]
The DataMember IsRequired attribute tells the WCF deserializer to expected an element in the message XML with that name (at least it does for soap deserialization). It sounds like the client code that is generating the message request is no longer sending all the Category... elements. It doesn't mean you can't send a null value for a DataMember marked IsRequired, it just means the element needs to exist in the message.
UPDATE: looking at the XML more closely, shouldn't there be a QuizServiceArgs element in the XML?

Categories