Hi and good day everyone,
I am able to send XML HTTP POST Request to WCF after solving it through this topic: Handle POST request from XML HTTP in WCF
But right now, I am still trying to find right way to retrieve inner XML from the request. I send the request in XML form :
<?xml version=""1.0"" encoding=""UTF-8"" standalone= ""yes""?><AFISQuery transid=""3356434""><Request CIFNO =""1234567890123456789"" IC= ""770707-07-7777"">TEST</Request></AFISQuery>
In the AFISQuery class, I set it as:
[DataContract(Namespace = "")]
public class AFISQuery
{
public AFISQuery(string transid)
{
this.transid = transid;
}
[DataMember]
public string Request { get; set; }
[DataMember]
public string transid { get; set; }
}
As the result, I am able to get Request information ("TEST"), but could not get transid information. I tried to look around the forums but failed to find similar problems.
My question is, would it be possible to retrieve the information from the inner XML of the request? For this instance, they are CIFNo, transid and ICNo.
Thanks in advance :)
The reason you're able to retrieve Request is that Request is an XML element. XML elements map directly to DataMembers, and as a result, Request is deserialized properly to the Request DataMember on the AFISQuery data contract type.
The problem with 'transid' is that it's an attribute. Attributes are not supported with DataContractSerializer, and they cannot in any way be supported. You need to change your request XML so that it has transid as an element, just like Request is an element.
Note also that even though Request is set to a value for you right now, the attributes on the "Request" element in the XML you have are totally ignored. You may or may not be OK with this.
If you care about attributes, or if you do want to support serializable members as attributes, you may need to switch to XmlSerializer from DataContractSerializer. It's easy to do this, just decorate the services or operations you care about -- that you want to switch over to XmlSerializer -- with [XmlSerializerFormat.]
Related
I am trying to implement an IPN handler in C# and I am using ServiceStack as my backend framework. I am facing the following issue however;
I am trying to find a way to take the POST body of a request as a querystring but I fail to do so. I am using IRequest.GetRawBody(); but the POST data are returned in a formatted way to make it readable.
Is there any way to easily take the POST body as a querystring? I want something similar to PHP's $_POST so I can ecrypt the data with HMAC SHA256 but I can find a way to do it without writing a helper class with hardcoded details about the POST request body. I've tried searching online and ServiceStack's documentation but I did not find anything useful.
Any help will be very appreciated, thanks in advance!
The QueryString is on the URL not the Request Body. If you just want access to the raw Request body that's posted you can have your Request DTO implement IRequiresRequestStream which tells ServiceStack to skip deserializing the body so you can deserialize it yourself, e.g:
public class MyRequest : IRequiresRequestStream
{
public Stream RequestStream { get; set; }
}
public class MyServices : Service
{
public object Any(MyRequest request)
{
var bytes = request.RequestStream.ReadFully();
var text = bytes.FromUtf8Bytes();
...
}
}
I'm trying to use RestSharp to connect to a server. but I get HTTP Error 406 Not acceptable.
Here is the web service response:
{"metaInfo":{"ErrorString":" ","ErrorCode":" ","Result":true},"userModel":
{"UserId":"123qwe","UserName":"aaa","FirstName":"ALi","LastName":"TbT"}}
The rest service is actually a simple php file that I created for test:
<?php
$a = array("metaInfo"=>array("ErrorString"=>" ","ErrorCode"=>" ","Result"=>true),"userModel"=>array("UserId"=>"123qwe","UserName"=>"aaa","FirstName"=>"ALi","LastName"=>"TbT"));
echo json_encode($a);
?>
And Here is the RegisterResult and MetaInfo classes:
public class RegisterResult
{
public MetaInfo metaInfo { get; set; }
}
public class MetaInfo
{
public string ErrorString { get; set; }
public string ErrorCode { get; set; }
public bool Result { get; set; }
}
The code that runs the rest request is as follows:
var client = new RestClient(Configuration.PortalUri);
var request = new RestRequest(requestUri, HttpMethod.Post);
var asyncHandle = await client.Execute<RegisterResult>(request);
Could you please tell me what the problem is? I think something is wrong with headers or encoding or something like that. Am I right?
This error is specific to the way the programmers have created the service you are calling. There's nothing wrong with your code from a C# perspective, but the way the service author has chosen to implement their service doesn't like something in the service call. You will have to refer to their documentation or ask one of their programmers.
Here's an explanation of http error 406
(taken from http://www.checkupdown.com/status/E406.html):
Fixing 406 errors - general
This error occurs very infrequently in Web browsers, because most
browsers will accept any data returned from the Web server.
If the client is not a Web browser, then anyone can only investigate
the problem by looking at the Accept headers generated by the client
system
Consider these headers to modify:
•Accept: The MIME types accepted by the client. For example, a browser
may only accept back types of data (HTML files, GIF files etc.) it
knows how to process.
•Accept-Charset: The character sets accepted by
the client.
•Accept-Encoding: The data encoding accepted by the
client e.g. the file formats it understands. •Accept-Language: The
natural languages (English, German etc.) accepted by the client.
•Accept-Ranges: Whether the client accepts ranges of bytes from the
resource i.e. a portion of the resource.
For example, you may need to add this to your request:
request.AddHeader("Accept", "application/json");
I have an http client in Android sending HTTP PUT requests to a REST api implemented with C# and ASP.NET WebApi framework.
The framework should be able to magically convert (deserialize) the JSON into a model class (plain object) as long as the JSON fields match the properties in the C# class.
The problem comes when the http requests come with Chunked Transfer Encoding that makes the Content-Length = 0 (as per http://en.wikipedia.org/wiki/Chunked_transfer_encoding) and the framework is not able to map the JSON that's within the Http request message so the parameter is null.
See this simple example:
[HttpPut]
public HttpStatusCode SendData(int id, int count, [FromBody]MyData records, HttpRequestMessage requestMessage)
{
var content = requestMessage.Content;
string jsonContent = content.ReadAsStringAsync().Result; //this gets proper JSON
return HttpStatusCode.OK;
}
The problem is that records is null when the client sends the http request chunked.
As I understand, the Chunked Transfer encoding is simply a transfer property that the http client or server should not have to worry about at the application layer (transport layer's business). But it seems the framework doesn't manage it as I'd like.
I could manually retrieve the JSON from the HttpRequestMessage and de-serialize it into a MyData object, but I wouldn't be able to take advantage of the ASP.NET framework's magic. And you know the rule: the more code you add the more bugs you are likely to introduce.
Is there any way to handle Http Put requests with JSON that come as chunked transfer encoded in ASP.NET Web Api 2?
EDIT: This is the model class for this example that the framework should instantiate when de-serializing the JSON
public class MyData
{
public string NamePerson {get; set;}
public int Age {get; set;}
public string Color {get; set;}
}
I recently stumbled upon the the same issue, and managed to create a workaround for it. I took the original JsonMediaTypeFormatter class, subclassed it and updated the implementation of the ReadFromStreamAsync/ReadFromStream-method.
https://gist.github.com/cobysy/578302d0f4f5b895f459
Hope this helps.
I have this simple web service, right now it just looks to see if the part number is A123456789 and then it returns a model number. This will be replaced by logic that will be connecting into a database to check the partno against and then return the actual model number. But at this point I just need it to return some dummy JSON data. However when I use Fiddler and look at the call in the web broswer of http://localhost:PORT/Scan/Model/A123456789 it returns this
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Model: CVS-1679</string>
But when I do a GET in fiddler of the same URI I get
"Model: CVS-1679"
Only under the textview tab.
Why is it being returned in XML (in the browser and text in Fiddler) and not JSON, when I have setup my ResponseFormat to be JSON?
My Code:
[WebGet(UriTemplate = "Model/{partno}", ResponseFormat = WebMessageFormat.Json)]
public string Model(string partno)
{
if (partno == "A123456789")
{
string modelno = "CVS-1679";
return "Model: " + modelno;
}
else
{
string modelno = "CVS-1601";
return "Model: " + modelno;
}
}
ASP.NET webservice return XML / SOAP message by default. In case you want to return Json string, you would need to decorate the Webservice with [ScriptService] attribute. This inform the IIS that this service would be used by ASP.NET AJAX calls. These attribute are part of System.Web.Extensions.
You can define the web method response format by decorating the webmethod with ScriptMethod attribute.
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
However even after decorating the webservice and webmethod by these attribute, the response can still be in XML format. This behaviour happen when the client which makes the request does not set the Request Header content type as “application/json”.
Before return the method call from webmethod serialize to Json string using JavaScriptSerializer
Debugging WebService using Fiddler
It is quite easy to use fiddler to test webservice. Following figure is an example of how to call a Webservice which returns a json string. Note that the request content type is set to application/json. The parameters expected by webserivce is mentioed in the Request Body section.
Note that the request content type is set to application/json.
It is being returned in Json if you look at the format of the data you get...
key: value
or in your case
string Model = "CVS-1679"
When you view it in fiddler your seeing the raw serialization transport from one MS endpoint to the other. The serialisation & De-serialisation elements in the .NET framework take care of transporting it across the wire, so that when you get the object back into your .NET app at the calling end, you get a variable called Model with the value you expect.
If you try to send an entire class you'll see a lot of nested XML tags, but when you get the object in your code, you'll see a first class citizen in the object hierarchy.
The reason it appears in your browser is because, the browser doesn't know how to de-serialise it, and so just displays the text
So i'm trying to de-serialize the JSON returned from the Graph API OAuth Token call.
The JSON looks like this:
"[{\"access_token\":\"bunchofjsondatablahblah",\"expires\":9999}]"
I'm trying to de-serialize it (using the DataContractJsonSerializer class) into this object:
[DataContract]
internal class FacebookOAuthToken
{
[DataMember]
internal string access_token;
[DataMember]
internal string expires;
}
Here's how im (trying) to do it:
FacebookOAuthToken token;
using (Stream responseStream = (response.GetReponseStream()))
{
DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(FacebookOAuthToken));
token = (FacebookOAuthToken)json.ReadObject(responseStream);
}
This technique is based on this article from MSDN.
However, the properties of token are always null.
Whereas if i do responseStream.ReadToEnd(), it's all fine (returns the above JSON) - which means its not a problem with the actual HTTP request/response, i'm just not deserializing it properly.
What am i doing wrong?
Okay so it turns out i was using the wrong Graph API URL (so it seems).
This is the problem with the Facebook API Documentation, its all over the place and different threads (google, stack overflow) say different ways how to do things.
I changed to the URL https://graph.facebook.com/oauth/access_token?{0} instead of https://graph.facebook.com/oauth/exchange_sessions?{0} and it now returns a basic string (non-JSON).
So it doesnt need to be serialized at all.
Still, some people might have the same problem as me above, in that case im not sure how to solve.
I'm now using the method defined here.
If I interpret the JSON string correctly it represents a collection of FacebookOAuthToken items with one single instance in it and not just a single token.
Maybe that is why your deserialization did not work.