POST request with Json body to MVC resful service - c#

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.

Related

C# WCF Service not picking up properties from ajax post

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"

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

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.

Posting to WCF Service sending NULL values

I'm trying to post to my WCF Service from an iPhone app. I have the app posting to the service and trying to send data in the form of a service data contract in XML like below:
NSData *myPostData = [[NSString stringWithFormat:#"<AddMediaItem xmlns='http://www.example.com'><Item xmlns:a='http://www.example.com/MediaItem'><a:MediaType>iPhone</a:MediaType><a:Description>Description</a:Description><a:Name>Test</a:Name><a:ImageType>JPEG</a:ImageType></Item></AddMediaItem>"] dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *myMutablePostData = [NSMutableData dataWithData:myPostData];
[request setPostBody:myMutablePostData];
[request setRequestMethod:#"POST"];
[request addRequestHeader:#"Content-Type" value:#"application/xml"];
[request setDidFinishSelector:#selector(uploadFinished:)];
[request setDidFailSelector:#selector(uploadFailed:)];
[request setDelegate:self];
[request startAsynchronous];
For testing purposes, I've setup my service to return the data contract that I send to the service. However, when it returns, some of the values seem to be NULLs although from the code above, I am giving them values.
What also seems strange is that the Name data member always has a value, but the other 3 I'm sending return NULL or with the correct values based on the order they appear in the XML I post to the service.
Below is the code for my service contract:
[ServiceContract(Namespace = "http://www.example.com")]
public interface IImageDiaryService
{
[OperationContract]
[WebInvoke(UriTemplate = "AddMediaItem", Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
MediaItem AddMediaItem(MediaItem Item);
}
Below is my code for my MediaItem data contract:
[DataContract(Namespace = "http://www.example.com/MediaItem")]
public class MediaItem
{
[DataMember]
public Int32 Id { get; set; }
[DataMember]
public String Name { get; set; }
[DataMember]
public String Description { get; set; }
[DataMember]
public String ImageData { get; set; }
[DataMember]
public String ImageType { get; set; }
[DataMember]
public String MediaType { get; set; }
}
Do let me know if you need any further code.
Any help is much appreciated.
The order is important in data contracts - by default the data members are ordered alphabetically, but you can override it by using the Order property of [DataMember]. Try reordering the fields and you'll get the values populated correctly
<AddMediaItem xmlns='http://www.example.com'>
<Item xmlns:a='http://www.example.com/MediaItem'>
<a:Description>Description</a:Description>
<a:ImageType>JPEG</a:ImageType>
<a:MediaType>iPhone</a:MediaType>
<a:Name>Test</a:Name>
</Item>
</AddMediaItem>
The DataContractSerializer only deserializes in the known order. As carlosfigueira says, default is alphabetical but you can specify an order. Yours aren't alphabetical and so I would expect that you are having server-side serialization issues.
I'd suggest you log what's happening server side. Is the request deserializing correctly inside your service? This will tell you where the data is going missing.

Categories