Support both JSON and XML as return type in Web API 2 - asp.net-web-api2

I am trying to enable web api to support both JSON and XML as return type. While serializing complex datattype to XML I got circular reference errors, so I decorated my main class with DataContract(IsReference = true), now XML serialization is working and json serialization not working.
thanks in advance.
PS: i am able to serialize simple dto classes to both xml and json, but for complex datatypes the problem is coming.

Set the followings in App_Start/WebApiConfig.cs
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
GlobalConfiguration.Configuration.Formatters.Add(new XmlMediaTypeFormatter());
Set application/json or application/xml to Accept header in request-side.

Result will be decided based on result type formatter. Hence I wrote 2 different methods for each return type. To solve, circular reference errors while generating xml i followed below steps.
Serialize class result
Deserialize class result.
Write it to xml.
var json = JsonConvert.SerializeObject(result);
var rO = JsonConvert.DeserializeObject<TClass>(json);
return Ok(ReturnAsXml(rO), Configuration.Formatters.XmlFormatter);
protected virtual XElement ReturnAsXml<T>(T data)
{
Type t = data.GetType();
DataContractSerializer serializer = new DataContractSerializer(t);//, extraTypes);
StringWriter sw = new StringWriter();
XmlTextWriter xw = new XmlTextWriter(sw);
serializer.WriteObject(xw, data);
var o = XElement.Parse(sw.ToString());
return o;
}

Related

How can i Replace the SoapFormatter Serialize and Deserialize with .net core 2.0?

I am working on migrating an old wcf project to .net core 2.0. At some places the code uses SoapFormatter class to serialize and deserialize data in Soap format.The Soap Formatter is no more supported in .net core 2.0 so i need to replace the piece of code to start using XMLSerialization. There is already some data stored in database which is serialized using SoapFormatter so i can't migrate the already stored data. Is there any way i can serialize and deserialize the already existing data with Xml Serialization without breaking it?
The piece of code using deserialization using soapformatter is:
var buffer = Convert.FromBase64String(piqBlob);
---------
public UserQuestionAnswers Deserialize(byte[] buffer)
{
using (var stream = new MemoryStream(buffer))
{
var questionsAnswers =
Serializer.Deserialize(stream) as BusinessProcesses.Authentication.UserQuestionAnswers;
if (questionsAnswers == null) return null;
var uQuestionAnswers = new UserQuestionAnswers
{
Domain = questionsAnswers.Domain,
KeyLabel = questionsAnswers.KeyLabel,
Username = questionsAnswers.Username,
UserUid = questionsAnswers.UserUid,
QuestionAnswers = (from item in questionsAnswers.QuestionAnswers
where item != null
select new QuestionAnswer
{
QuestionId = item.QuestionId,
QuestionHash = item.QuestionHash,
AnswerHmac = item.AnswerHMAC,
QuestionText = string.Empty
}).ToArray()
};
return uQuestionAnswers;
}
}
Please let me know if you need more information on this.
I am also open to any third part library if have a good rating?

Deserialize json to object using mono touch for iPhone

Is it possible to deserialize a JSON string to an object without using the DataContractJsonSerializer in System.ServiceModel.Web? I have the following code but I need a payed license to use it...
response = (HttpWebResponse)request.EndGetResponse(iar);
System.Runtime.Serialization.Json.DataContractJsonSerializer ser = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(Result));
Result result = (Result)ser.ReadObject(response.GetResponseStream());
I'm using RestSharp to consume my Web.API service that sends data via JSON. However, I'm using JSON.NET to deserialize it.
_client.ExecuteAsync (request, (response) => {
List<Account> data = JsonConvert.DeserializeObject<List<Account>>(response.Content);
This works just fine for me and JSON.NET is free, very quick, and kind of the de facto JSON serialization library for .NET.
http://james.newtonking.com/projects/json-net.aspx

Using JSON.NET instead of the default WebMethod serialization

In a WebMethod I am using JSON.NET to manually serialize my object to avoid the entity framework circular reference problem.
I have the following code:
Dim qry = From m In entity.Mediators _
Where m.MediatorNumber = mediatorNumber _
Select m
For Each mediator In qry
mediator.MediatorRestrictionsAvailabilities.Load()
customMediator = mediator
Next
customJson = JsonConvert.SerializeObject(customMediator, Formatting.Indented)
The problem is that the result is not well formatted JSON and cannot be parsed on the client; it looks like this:
{"d":"{\r\n \"$id\": \"1\",\r\n \"MediatorId\": 922,\r\n \"AreaCode\": \"E \",\r\n \"PFCCode\": \"840 \",\r\n \"FirstName\": \"Joe\",\r\n \"LastName\": \"Smith\",\r\n
After doing some research I have learned that this is what happens when JSON is reserialized into JSON.
How do I do my own custom serialization without the default serializer getting in the way?
I had a similar problem a while back and here are the suggestions which I was given. My solution was that I did not need to serialize the object again into json as it was already being serialized.
Good luck and hope this helps some.
For the circular reference use this approach:
string json = JsonConvert.SerializeObject(
infoToSerialize, Formatting.Indented,
new JsonSerializerSettings{ ReferenceLoopHandling =
ReferenceLoopHandling.Ignore
});

Exposing object of unknown type from a WCF service

[OperationContract]
public object GetDeserializedObject(int partyContactID)
{
PartyContact partyContact = GetPartyContactById(partyContactID);
ContactTermResultQueue resultQueue = GetContactTermResultQueueByID(partyContact.TemplateQueueID);
byte[] contactDataSetArray = resultQueue.QueryResult;
//Getting DataSet from the byte array
BinaryFormatter binaryFormatter = new BinaryFormatter();
Stream mStreamtoRead = new MemoryStream(contactDataSetArray);
object o = binaryFormatter.Deserialize(mStreamtoRead);
mStreamtoRead.Close();
object returnData=null;
if (o.GetType().IsArray)
{
object[] os = o as object[];
var value = from vs in os where (int) (vs.GetType().GetProperty("PartyID").GetValue(vs, null)) == partyContact.PartyID select vs;
if (value.Count() > 0)
{
returnData = value.First();
}
}
return returnData;
}
As I don't know what type of data we are going to have in the database, so wanted to return the object from this service, but it is giving me an exception.
Please let me know how can I achieve this?
Thanks in advance
You can't return object and expect it will work. The reason is that behind this code WCF engine uses serialization. When client receives message it must be able to deserialize it back to some object but to be able to do that it must know what type of object it received.
If you want to send "unknown" data use XElement. Client will receive just XML and it will be its responsibility to deal with it (parse it, deserialize it or whatever).
You can do certain things with the "raw" Message data type - but it's really not pretty programming...
Read about it here:
How to pass arbitrary data in a Message object using WCF
WCF : Untyped messages on WCF operations.

Returning wcf/json result from the wcf service

I Need by service contract to return the xml/json result depending on the request type.I also need a kind of helper function which will convert my result set (i am using linq to sql) so that i do not need to create the xml format for the result set by iterating through the table row many times.What is the suitable way to do that.
I need a kind of short cut method which will convert the table data to xml result.Had i been using asp.net mvc i would have been able to generate the xml data by overriding the the ExecuteResult method in the ActionResult and giving Conetnt-Type = "text/xml" as OP.But since i am using
Wcf i don't have the controller context(as controller context is the parameter that needs to be passed to Execute Result).
My present code for converting the table data to the xml format is below.
public XDocument UsersLists(string authToken)
{
bool IsAuthenticated = Authenticate(authToken);
XDocument xDoc = new XDocument();
XElement root = new XElement("Users");
if (IsAuthenticated)
{
List<User> lstUsers = _lService.UserRepository.GetUserCompanyFromAccountID(GetAccountId(authToken)).ToList();
if (lstUsers != null)
{
root.Add(new XElement("Message", "Success"));
foreach (var u in lstUsers)
{
XElement chid = new XElement("User");
root.Add(new XElement("UserId", u.UserId));
root.Add(new XElement("FirstName", u.FirstName));
root.Add(new XElement("LastName", u.LastName));
root.Add(new XElement("Email", u.Email));
root.Add(new XElement("CompanyName", u.Company.CompanyName));
root.Add(chid);
}
xDoc.Add(root);
return xDoc;
}
else
{
return ReturnFailure(xDoc, root);
}
}
else
{
return ReturnFailure(xDoc, root);
}
}
I need to eliminate this way of generating xml for each table records.
An early response is priceless.
Thanks
Technology : Windows Communication Foundation.
Implementation of single operation returning both XML or JSON differs between WCF 3.5 or WCF 4.0. For implementing this feature in WCF 3.5 check this thread. Generally you will have to create custom behavior and set the content type based on Accept header from the request. WCF 4.0 has native support for this feature. WebHttpBehavior has property AutomaticFormatSelectionEnabled. If you set this property to true it should just work out of the box.
To your second question. You don't need any custom formatting like in ASP.NET MVC. Formatting in WCF is handled by serialization. Just return collection from your operation and you will see what happens. Linq-To-Sql generated entities should be serializable by default. Just don't forget to execute query before returning from method. If you need special format of date which is not the same as Linq-To-Sql entities create custom data type which have public parameterless constructor and all required properties with getter and setter. If you want to make it clear makr that class with DataContract attribute and all properties with DataMember attribute. Return collection of that custom class instances from your operation.