Different behaviour in response if Accept:application/json is specified - c#

The Http method used is GET and I'm calling the same webservice method (with same parameters).
But if I add to request an Accept header with application/json, the output differs.
The cause is a Bitmap field in my object named User, which holds an avatar image.
If i leave out the Accept application/json header, this is the simplified output (XML):
<!-- language: lang-xml -->
<ArrayOfUser xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/XTraN4ForcesFSDomain.Domain">
<User>
<Id>02ddf1e4-ad76-4778-8887-a186014939f8</Id>
<Avatar xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Drawing" i:nil="true" />
<IsActive>false</IsActive>
<LastAccess>0001-01-01T00:00:00</LastAccess>
<Username>quisquam</Username>
<!-- Other properties -->
</User>
<User>
<Id>17db833c-5008-44f0-a713-a186014c22a5</Id>
<Avatar xmlns:d3p1="http://schemas.datacontract.org/2004/07/System.Drawing">
<Data xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:base64Binary" xmlns="">iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAABGdBTUEAAK/INwWK6[...]BIJS/Wd6Pgu/mOoS/HADwfwFUI4VkJHOgAgAAAABJRU5ErkJggg==</Data>
</Avatar>
<IsActive>false</IsActive>
<LastAccess>0001-01-01T00:00:00</LastAccess>
<Username>labore</Username>
</User>
</ArrayOfUser>
Well, this is just fine! The image (Base64) is there. If I change my request to get JSON, it returns no image, just the name of the class that it represents:
<!-- language: lang-json -->
[
{
"Username": "quisquam",
"LastAccess": "0001-01-01T00:00:00",
"IsActive": false,
"Avatar": null,
"Id": "02ddf1e4-ad76-4778-8887-a186014939f8"
},
{
"Username": "reiciendis",
"LastAccess": "0001-01-01T00:00:00",
"IsActive": false,
"Avatar": "System.Drawing.Bitmap",
"Id": "17db833c-5008-44f0-a713-a186014c22a5"
},
]
The webservice mthod is
<!-- language: lang-c# -->
public IQueryable<User> Get()
{
// return stuff (no big deal here)
}
The code is the same, so why won't JSON return a base64 string like it should?

As LukeH said, converting my Bitmap to byte array solved my issues.

Related

How to render Exception.Data dictionary the same way IncludeEventProperties does for event properties in NLog?

Is it possible to get NLog using JsonLayout to write out the Exception.Data dictionary as actual JSON instead of just a single attribute serialized with its toString?
The closest I have been able to get is this:
<attribute name='data' layout='${exception:format=data}' />
which becomes
"exception": {
"type": "System.IO.InvalidDataException",
"message": "Invalid PERSON identifier: xyz",
"data": "entity: PERSON;value: xyz",
"stacktrace": "..."
}
or this
<attribute name='exception' layout='${exception:format=#}'/>
which becomes
"exception": "{\"Type\":\"System.IO.InvalidDataException\", \"Message\":\"Invalid PERSON identifier: xyz\", \"Data\":{\"entity\":\"PERSON\",\"value\":\"xyz\"}, \"TargetSite\":\"Void MoveNext()\", \"StackTrace\":\"...\", \"HResult\":-2146233087}"
Ideally I would like to see a layout configuration that yields:
"exception": {
"type": "System.IO.InvalidDataException",
"message": "Invalid PERSON identifier: xyz",
"data": {
"entity": "PERSON",
"value": "xyz",
}
"stacktrace": "..."
}
This configuration will output event properties the way I want:
<attribute name="properties" encode="false" >
<layout type='JsonLayout' includeAllProperties="true" maxRecursionLimit="10"/>
</attribute>
"properties": {
"controllerName": "Person",
"actionName": "Lookup"
}
But I haven't found a valid configuration that does the same thing for Exception.Data. Has anyone been able to accomplish this without manually adding every possible dictionary key to the configuration as an attribute using ${exceptiondata:item=entity} etc?
When using format=# then it will output in json-format, but then you have to use encode="false" to avoid encoding as string-property:
<attribute name="exception" layout="${exception:format=#}" encode="false" />
Notice that some exceptions are dangerous, where the data-dictionary enumerates an entire database. You can use RegisterObjectTransformation to override the transformation of those exceptions.
See also: https://github.com/NLog/NLog/wiki/How-to-use-structured-logging#transform-captured-properties

DateTime property issue when using servicestack autoquery

Thanks Mythz for providing such an amazing and powerful framework. However, I encountered the DateTime property rendered like this "/Date(1543681261000-0000)/" instead of "2019-03-25T12:50:3000" by using servicestack autoquery. I couldn't find any relevant docs. Please help me.
{
"customer": [
{
"transaction_total": 0,
"text": "0067 83228780",
"transaction_time": 0,
"action": 0,
"point_collection_on_registration": false,
"id": 71,
"push_notification_id": "null",
"name": "0067",
"ic": "27668",
"type": 0,
"phone_no": "83228780",
"point": 5132,
"balance": 1621.3,
"issue_date": "/Date(1543681261000-0000)/",
"is_subscribed": true,
"is_expiry": false,
"lang_preferred": "cn",
"is_delete": false
}
],
"count_all": 120
}
ServiceStack by default uses WCF Dates for JSON, see this answer for different ways to parse WCF Dates in JavaScript.
You can choose to change how dates are serialized in JSON for any JSON Response in ServiceStack by customizing JSON Responses, e.g you can change the JSON returned by the Auto Query Service with:
?jsconfig=DateHandler:ISO8601
?jsconfig=DateHandler:ISO8601DateOnly
?jsconfig=DateHandler:ISO8601DateTime
Or use the short-hand alias notation:
?jsconfig=dh:iso8601
?jsconfig=dh:iso8601do
?jsconfig=dh:iso8601dt
Alternatively you can tell ServiceStack to always use ISO8601 dates in JSON in your AppHost.Configure() with:
JsConfig.Init(new Config {
DateHandler = DateHandler.ISO8601
});

Issue handling attributes when converting JSON to XML in C#

I'm working on a service in which I pass a JSON request, I need to convert it to XML and them compare it to some XML schemas and then do something with it.
My problem is with the attributes. For example, my JSON request is:
{
"BookingSearch_IN": {
"MsgHeader": {
"MessageID": "ABC010101",
"ContextRecord": {
"ContextInfo": {
"ItineraryDetails": {
"ItinerarySeqNmbr": "1",
"StartDate": "2017-04-01",
"EndDate": "2017-04-14",
"LocationStart": {
"LocationContext": "AIRPORT",
"LocationCode": "MIA"
},
"LocationEnd": {
"LocationContext": "AIRPORT",
"LocationCode": "MIA"
}
},
"ExtraInfoList": {
"ExtraInfo": {
"Category": "CRUISE",
"Item": {
"Code": "SHIP_CODE",
"Value": "MAGIC"
}
}
},
"_ResType": "Vacation"
}
}
},
"_xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"_xmlns:cs": "http://MyCompany.com",
"_version": "6.66",
"__prefix": "cs"
}
}
I'm using: XmlDocument doc = JsonConvert.DeserializeXmlNode(jsonObject); to convert it to XML. The xml result is:
<BookingSearch_IN>
<MsgHeader>
<MessageID>ABC010101</MessageID>
<ContextRecord>
<ContextInfo>
<ItineraryDetails>
<ItinerarySeqNmbr>1</ItinerarySeqNmbr>
<StartDate>2017-04-01</StartDate>
<EndDate>2017-04-14</EndDate>
<LocationStart>
<LocationContext>AIRPORT</LocationContext>
<LocationCode>MIA</LocationCode>
</LocationStart>
<LocationEnd>
<LocationContext>AIRPORT</LocationContext>
<LocationCode>MIA</LocationCode>
</LocationEnd>
</ItineraryDetails>
<ExtraInfoList>
<ExtraInfo>
<Category>CRUISE</Category>
<Item>
<Code>SHIP_CODE</Code>
<Value>MAGIC</Value>
</Item>
</ExtraInfo>
</ExtraInfoList>
<_ResType>Vacation</_ResType>
</ContextInfo>
</ContextRecord>
</MsgHeader>
<xsi>http://www.w3.org/2001/XMLSchema-instance</xsi><cs>http://MyCompany.com</cs><_version>6.66</_version><__prefix>cs</__prefix>
</BookingSearch_IN>
The result XML has the attributes of the root element at the end of the document, as another elements (between </MsgHeader> and </BookingSearch_IN>). My problem is that the service that validates this XML against other customers' XML checks these attributes in the root element. Here is how the code expects the XML to be:
<?xml version="1.0" encoding="UTF-8"?>
<cs:BookingSearch_IN xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cs="http://MyCompany.com" version="6.66">
<MsgHeader>
<MessageID>ABC010101</MessageID>
<ContextRecord>
<ContextInfo ResType="Vacation">
<ItineraryDetails>
<ItinerarySeqNmbr>1</ItinerarySeqNmbr>
<StartDate>2017-04-01</StartDate>
<EndDate>2017-04-14</EndDate>
<LocationStart>
<LocationContext>AIRPORT</LocationContext>
<LocationCode>MIA</LocationCode>
</LocationStart>
<LocationEnd>
<LocationContext>AIRPORT</LocationContext>
<LocationCode>MIA</LocationCode>
</LocationEnd>
</ItineraryDetails>
<ExtraInfoList>
<ExtraInfo>
<Category>CRUISE</Category>
<Item>
<Code>SHIP_CODE</Code>
<Value>MAGIC</Value>
</Item>
</ExtraInfo>
</ExtraInfoList>
</ContextInfo>
</ContextRecord>
</MsgHeader>
</cs:BookingSearch_IN>
The code fails because it expect the root element to be <cs:BookingSearch_IN xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cs="http://MyCompany.com" version="5.22">
.... any advise on how to handle this situation? or how to put those attributes back to where they belong in the root element?
NewtonSoft expects attributes to be prefixed with #, not _ or __, and expects prefixes to just be baked into the names. For example, if you can get your JSON to look like this:
{
"cs:BookingSearch_IN": {
"#xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"#xmlns:cs": "http://MyCompany.com",
"#version": "6.66",
"MsgHeader": {
"MessageID": "ABC010101",
"ContextRecord": {
"ContextInfo": {
"#ResType": "Vacation",
"ItineraryDetails": {
"ItinerarySeqNmbr": "1",
"StartDate": "2017-04-01",
"EndDate": "2017-04-14",
"LocationStart": {
"LocationContext": "AIRPORT",
"LocationCode": "MIA"
},
"LocationEnd": {
"LocationContext": "AIRPORT",
"LocationCode": "MIA"
}
},
"ExtraInfoList": {
"ExtraInfo": {
"Category": "CRUISE",
"Item": {
"Code": "SHIP_CODE",
"Value": "MAGIC"
}
}
}
}
}
}
}
}
It will work correctly (note that you have to move those XMLNS's up to the top - if they stay where they are at the bottom, it drops the prefix for some reason).
If that's not possible, you'll either have to use a different serializer or write some custom logic to pre/post process your JSON or XML.

How to update Issue status as done through rest api?

i want to update the issue status as done or true from the rest api, i tried some links and documentations but it failed and not worked, my json data and url is following, please have a look and let me know where i am wrong.
i followed this link to update the issue status as done.
jQuery.ajax({
url :'https://myurl.com/rest/api/latest/issue/10635',
type: 'PUT',
beforeSend : function(xhr) {
xhr.setRequestHeader("Authorization", "Basic " + 'QXNjiYIklOZvcxlxhZ3NodXNldA==');
},
data: JSON.stringify({"status":{"id":"10635","name":"done"}}}),
dataType: 'json',
contentType:'application/json; charset=utf8',
success: function(data){
console.log(data);
}
})
My json is following
{"status":{"id":"10635","name":"done"}}}
i checked the response on fiddler but i got the following error in fiddler response.
{"errorMessages":["one of 'fields' or 'update' required"],"errors":{}}
after that i changed my json data as following and that also not worked,
{"update":{"status":{"id":"10635","name":"done"}}}
and then i seen the error in fiddle as following.
{"errorMessages":["Can not deserialize instance of java.util.ArrayList out of START_OBJECT token\n at [Source: org.apache.catalina.connector.CoyoteInputStream#19d2e36; line: 1, column: 12] (through reference chain: com.atlassian.jira.rest.v2.issue.IssueUpdateBean[\"update\"])"]}
it killed my 2.5 hours approx, kindly help where i am wrong ?
I was using the wrong approach, for setting the status as done of the Jira issue you have to send two requests to the server (1) Get request which will return the transaction id for the issue. (2) Post request to the server with the help of transaction id you can make the issue as done, i try to demonstrate following.
(1) Send Get Request to the JIRA server with following url (same url will use for POST request).
https://mycompany.com/rest/api/2/issue/{issueidORkey}/transitions?expand=expand.fields
it will return the following type of details into json mode.
{
"expand": "transitions",
"transitions": [
{
"id": "25",
"name": "Start Progress",
"to": {
"self": "https://mycompany.com/rest/api/2/status/3",
"description": "This issue is being actively worked on at the moment by the assignee.",
"iconUrl": "https://mycomapny.com/images/icons/statuses/inprogress.png",
"name": "In Progress",
"id": "3",
"statusCategory": {
"self": "https://mycompany.com/rest/api/2/statuscategory/4",
"id": 4,
"key": "indeterminate",
"colorName": "yellow",
"name": "In Progress"
}
}
}
}
as above you can see there is the transition --> id=25, this id will be use for the POST request, for me i created the JSON as following and now
(2) send the POST request through same url as i used above.
{
"update": {
"comment": [{
"add": {
"body": "Comment body"
}
}]
},
"fields": {},
"transition": {
"id": "25"
}
}
for me fields property was not required so i am able to update the issue status as done.
:)

Can't load JSON into a jstree from WCF service (or How to find what's wrong when jstree stays on "loading...")

I am trying to get jStree (jQuery tree control) working in my ASP.NET (C#) page. I'm using a WCF service to return a test string of JSON.
Opening the WCF service URL in the browser works fine - If I go to the URL (http://localhost/website/GetTree) I get the JSON (looks just like opening XML in browser, with syntax highlighting and collapsible tab thingys)
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">{"attr": { "id": 2, "rel": "default" }, "data": "A node", "children": [ { "data": "Child 1", "attr": { "id": 43, "rel": "document" } }, {"data": "Child 2", "attr": { "id": 25, "rel": "document"} } ] }</string>
jstree itself works fine - if I put the same JSON in "manually" in my document.ready like so:
"json_data": {
"data":
[{
"attr": { "id": 2, "rel": "default" },
"data": "A node",
"children":
[{
"data": "Child 1", "attr": { "id": 43, "rel": "document" }
},{
"data": "Child 2", "attr": { "id": 25, "rel": "document"}
}]},{
"attr": { "id": "li.node.id", "rel": "document" },
"data": {
"title": "Long format demo",
"attr": { "href": "#" }
}}]},
I get the tree appearing with those nodes in it.
But, combining the two:
"json_data": {
"ajax": {
"url": "GetTree",
"data": function (n) {
return {
};
}
}
},
...fails. The jstree shows up as just the word "loading..." and an animated loading gif. And it does hit a breakpoint inside the WCF service method (just like browsing to it does).
A: An idea where I've gone wrong?
B: An idea how I find out what's wrong? jstree documentation was no help, and I can't see any error messages.
Thanks.
Update: solved
Thanks to Mikael Eliasson for pointing out that my service must be returning XML and not JSON.
WCF service code-behind:
// this responseformat bit below fixed it
[WebGet(UriTemplate = "GetTesto", ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
public Testo GetTesto()
{
return new Testo();
}
Might be a stupid question but you have enabled the json_data plugin, right? As akonsu said inspecting the response in a tool like Firebug.
It seems to me that you WCF service is not returning JSON but rather a XML response. I think that is your problem. The best thing is probably to change the service to return JSON. If you can't do that you could add the success function and transform the string to JSON with the function $.parseJSON()
I hope that helps. But again you really should start using Firebug or something similar because there are lot of times when you need to inspect the response or debug javascript.

Categories