I'm currently working on an application through WPF and wonder what's the better option in my case. I have a web based API that originally prints it's own XML and fills in the elements with it's data, but since this'll eventually be on a live server I thought it might seem a bit more convenient if the executable creates an XML file and parses API data into it.
If my option seems better, how do I write designated data to XML elements? I'm sorry if my question is a bit vague.
My JSON classes
[DataContract]
public class ShipmentDetails
{
[DataMember(Name="salutationCode")]
public string salutationCode { get; set; }
[DataMember(Name="firstName")]
public string firstName { get; set; }
[DataMember(Name="surName")]
public string surName { get; set; }
[DataMember(Name="streetName")]
public string streetName { get; set; }
[DataMember(Name="houseNumber")]
public string houseNumber { get; set; }
[DataMember(Name="zipCode")]
public string zipCode { get; set; }
[DataMember(Name="city")]
public string city { get; set; }
[DataMember(Name="countryCode")]
public string countryCode { get; set; }
[DataMember(Name="email")]
public string email { get; set; }
[DataMember(Name="language")]
public string language { get; set; }
}
[DataContract]
public class BillingDetails
{
[DataMember(Name="salutationCode")]
public string salutationCode { get; set; }
[DataMember(Name="firstName")]
public string firstName { get; set; }
[DataMember(Name="surName")]
public string surName { get; set; }
[DataMember(Name="streetName")]
public string streetName { get; set; }
[DataMember(Name="houseNumber")]
public string houseNumber { get; set; }
[DataMember(Name="zipCode")]
public string zipCode { get; set; }
[DataMember(Name="city")]
public string city { get; set; }
[DataMember(Name="countryCode")]
public string countryCode { get; set; }
[DataMember(Name="email")]
public string email { get; set; }
}
[DataContract]
public class CustomerDetails
{
[DataMember(Name="shipmentDetails")]
public ShipmentDetails shipmentDetails { get; set; }
[DataMember(Name="billingDetails")]
public BillingDetails billingDetails { get; set; }
}
[DataContract]
public class OrderItem
{
[DataMember(Name="orderItemId")]
public string orderItemId { get; set; }
[DataMember(Name="offerReference")]
public string offerReference { get; set; }
[DataMember(Name="ean")]
public string ean { get; set; }
[DataMember(Name="title")]
public string title { get; set; }
[DataMember(Name="quantity")]
public int quantity { get; set; }
[DataMember(Name="offerPrice")]
public double offerPrice { get; set; }
[DataMember(Name="offerId")]
public string offerId { get; set; }
[DataMember(Name="transactionFee")]
public double transactionFee { get; set; }
[DataMember(Name="latestDeliveryDate")]
public string latestDeliveryDate { get; set; }
[DataMember(Name="expiryDate")]
public string expiryDate { get; set; }
[DataMember(Name="offerCondition")]
public string offerCondition { get; set; }
[DataMember(Name="cancelRequest")]
public bool cancelRequest { get; set; }
[DataMember(Name="fulfilmentMethod")]
public string fulfilmentMethod { get; set; }
}
[DataContract]
public class Example
{
[DataMember(Name="orderId")]
public string orderId { get; set; }
[DataMember(Name="pickUpPoint")]
public bool pickUpPoint { get; set; }
[DataMember(Name="dateTimeOrderPlaced")]
public DateTime dateTimeOrderPlaced { get; set; }
[DataMember(Name="customerDetails")]
public CustomerDetails customerDetails { get; set; }
[DataMember(Name="orderItems")]
public IList<OrderItem> orderItems { get; set; }
}
My XML
using (XmlWriter writer = XmlWriter.Create("Orders.xml"))
{
writer.WriteStartElement("start");
writer.WriteElementString("customer_id", "935933");
writer.WriteStartElement("orders");
writer.WriteStartElement("order");
writer.WriteElementString("order_id", "");
writer.WriteElementString("order_ref", "");
writer.WriteElementString("order_dropshipment", "");
writer.WriteElementString("order_dlv_adr_name", "");
writer.WriteElementString("order_dlv_adr_street", "");
writer.WriteElementString("order_dlv_adr_housenr", "");
writer.WriteElementString("order_dlv_adr_zipcode", "");
writer.WriteElementString("order_dlv_adr_city", "");
writer.WriteElementString("order_dlv_adr_email", "");
writer.WriteElementString("order_dlv_adr_phone", "");
writer.WriteElementString("order_dlv_adr_country_isocode", "");
writer.WriteStartElement("orderrows");
writer.WriteStartElement("orderrow");
writer.WriteElementString("orderrow_sku", "");
writer.WriteElementString("orderrow_qty", "");
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndElement();
writer.Flush();
}
XML mapping in PHP
$order->addChild('order_id',$info['orderId']);
$order->addChild('order_ref',$info['orderId']);// order_ref is usually the same as the order_id
$order->addChild('order_dropshipment',"Y"); // Yes and No if there's no dropshipment needed
$order->addChild('order_dlv_adr_name',$info['customerDetails']['shipmentDetails']['firstName'].' '.$info['customerDetails']['shipmentDetails']['surName']);
$order->addChild('order_dlv_adr_street',$info['customerDetails']['shipmentDetails']['streetName']);
$order->addChild('order_dlv_adr_housenr',$info['customerDetails']['shipmentDetails']['houseNumber']);
$order->addChild('order_dlv_adr_zipcode',$info['customerDetails']['shipmentDetails']['zipCode']);
$order->addChild('order_dlv_adr_city',$info['customerDetails']['shipmentDetails']['city']);
$order->addChild('order_dlv_adr_email',COMPANY_EMAIL);
$order->addChild('order_dlv_adr_phone',COMPANY_PHONE);
$order->addChild('order_dlv_adr_country_isocode',$info['customerDetails']['shipmentDetails']['countryCode']);
Desired output
<start>
<customer_id>935933</customer_id>
<orders>
<order>
<order_id>11864523</order_id>
<order_ref>11864523</order_ref>
<order_dropshipment>Y</order_dropshipment>
<order_dlv_adr_name>Fred Bellens</order_dlv_adr_name>
<order_dlv_adr_street>Elisabetaelaan</order_dlv_adr_street>
<order_dlv_adr_housenr>2</order_dlv_adr_housenr>
<order_dlv_adr_zipcode>3200</order_dlv_adr_zipcode>
<order_dlv_adr_city>Aarschot</order_dlv_adr_city>
<order_dlv_adr_email>*our mail*</order_dlv_adr_email>
<order_dlv_adr_phone>077 396 814</order_dlv_adr_phone>
<order_dlv_adr_country_isocode>BE</order_dlv_adr_country_isocode>
<orderrows>
<orderrow>
<orderrow_sku>KA0 14315 21_122</orderrow_sku>
<orderrow_qty>1</orderrow_qty>
</orderrow>
</orderrows>
</order>
</orders>
</start>
There are several ways how you can achieve that desired XML.
Let me show you two different ways:
XElement
Instead of relying on the XmlWriter we can construct the desired structure with XElement.
In your case the initialization of the tree could look similar to this:
var order = //...;
var shipment = order.customerDetails.billingDetails;
var xml = new XElement("start",
new XElement("customer_id", 935933),
new XElement("orders",
new XElement("order",
new XElement("order_id", order.orderId),
new XElement("order_ref", order.orderId),
new XElement("order_dropshipment", "Y"),
new XElement("order_dlv_adr_name", $"{shipment.firstName} {shipment.surName}"),
new XElement("order_dlv_adr_street", shipment.streetName),
new XElement("order_dlv_adr_housenr", shipment.houseNumber),
new XElement("order_dlv_adr_zipcode", shipment.zipCode),
new XElement("order_dlv_adr_city", shipment.city),
new XElement("order_dlv_adr_email", "TBD"),
new XElement("order_dlv_adr_phone", "TBD"),
new XElement("order_dlv_adr_country_isocode", shipment.countryCode)
)));
Then the persistence logic would look like this:
using var sampleXml = new FileStream("sample.xml", FileMode.CreateNew, FileAccess.Write);
using var fileWriter = new StreamWriter(sampleXml);
fileWriter.Write(xml.ToString());
fileWriter.Flush();
And that's it.
JsonConvert
As an alternative if you already have the desired structure in json then you can easily convert it to XML via JsonConvert's DeserializeXmlNode:
var orderInJson = JsonConvert.SerializeObject(data);
XmlDocument orderInXml = JsonConvert.DeserializeXmlNode(orderInJson);
And here is the persistence logic:
using var sampleXml = new XmlTextWriter("sample2.xml", Encoding.UTF8);
using var fileWriter = XmlWriter.Create(sampleXml);
orderInXml.WriteTo(fileWriter);
fileWriter.Flush();
Related
I'm trying to use XDocument to read in XML and deserialize it to objects.
I want to take the following XML:
<r25:spaces xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xl="http://www.w3.org/1999/xlink" xmlns:r25="http://www.collegenet.com/r25" pubdate="2019-07-15T14:51:16-07:00" engine="accl">
<r25:space crc="00000022" status="est" xl:href="space.xml?space_id=200">
<r25:space_id>200</r25:space_id>
<r25:space_name>LRN 0001</r25:space_name>
<r25:formal_name>Learning Commons -Test Scheduling Room</r25:formal_name>
<r25:partition_id xl:href="rmpart.xml?partition_id=2">2</r25:partition_id>
<r25:last_mod_dt>2019-07-11T08:01:00-07:00</r25:last_mod_dt>
</r25:space>
</r25:spaces>
and deserialize it to a List of spaces (where Space has the following definition):
public class Space
{
public long space_id { get; set; }
public string space_name { get; set; }
public string formal_name { get; set; }
public long partition_id { get ; set; }
public DateTime last_mod_dt { get; set; }
}
I've only gotten so far as to get the XElement. It dies on the serializer
var doc = XDocument.Parse(result.Content);
XNamespace ns = "http://www.collegenet.com/r25";
XElement el = doc.Element(ns + "spaces");
foreach (var space in el.Elements())
{
var serializer = new XmlSerializer(typeof(Space));
var s = (Space)serializer.Deserialize(space.CreateReader());
}
You can simply use LINQ to XML here. e.g.
using System;
using System.Linq;
using System.Xml.Linq;
namespace ConsoleApp22
{
public class Space
{
public long space_id { get; set; }
public string space_name { get; set; }
public string formal_name { get; set; }
public long partition_id { get; set; }
public DateTime last_mod { get; set; }
}
class Program
{
static void Main(string[] args)
{
var xml = #"
<r25:spaces xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xl=""http://www.w3.org/1999/xlink"" xmlns:r25=""http://www.collegenet.com/r25"" pubdate=""2019-07-15T14:51:16-07:00"" engine=""accl"">
<r25:space crc=""00000022"" status=""est"" xl:href=""space.xml?space_id=200"">
<r25:space_id>200</r25:space_id>
<r25:space_name>LRN 0001</r25:space_name>
<r25:formal_name>Learning Commons -Test Scheduling Room</r25:formal_name>
<r25:partition_id xl:href=""rmpart.xml?partition_id=2"">2</r25:partition_id>
<r25:last_mod_dt>2019-07-11T08:01:00-07:00</r25:last_mod_dt>
</r25:space>
</r25:spaces>
";
var doc = XDocument.Parse(xml);
XNamespace ns = "http://www.collegenet.com/r25";
var q = from e in doc.Element(ns + "spaces").Elements()
select new Space
{
space_id = (int)e.Element(ns + "space_id"),
space_name = (string)e.Element(ns + "space_name"),
formal_name = (string)e.Element(ns + "formal_name"),
partition_id = (long)e.Element(ns + "partition_id"),
last_mod = (DateTime)e.Element(ns + "last_mod_dt")
};
var space = q.First();
}
}
}
You can add the XmlRoot to your class to declare the namespace for that element:
[XmlRoot("space", Namespace = "http://www.collegenet.com/r25")]
public class Space
{
public long space_id { get; set; }
public string space_name { get; set; }
public string formal_name { get; set; }
public long partition_id { get; set; }
public DateTime last_mod { get; set; }
}
The deserializer will now correctly read the XML as an object.
Use the the XSD tool to generate the class and then use XmlSerializer to populate the class. Like this.
MyClass myClass;
using (var stream = new FileStream("myClass.xml", FileMode.Open))
{
var serializer = new XmlSerializer(typeof(MyClass));
myClass = serializer.Deserialize(stream);
}
I found a website that will take XML and create the proper deserialization classes. Xml2CSharp, which created the following classes that allowed the deserialization to work:
[XmlRoot(ElementName="partition_id", Namespace="http://www.collegenet.com/r25")]
public class Partition_id {
[XmlAttribute(AttributeName="href", Namespace="http://www.w3.org/1999/xlink")]
public string Href { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName="space", Namespace="http://www.collegenet.com/r25")]
public class Space {
[XmlElement(ElementName="space_id", Namespace="http://www.collegenet.com/r25")]
public string Space_id { get; set; }
[XmlElement(ElementName="space_name", Namespace="http://www.collegenet.com/r25")]
public string Space_name { get; set; }
[XmlElement(ElementName="formal_name", Namespace="http://www.collegenet.com/r25")]
public string Formal_name { get; set; }
[XmlElement(ElementName="partition_id", Namespace="http://www.collegenet.com/r25")]
public Partition_id Partition_id { get; set; }
[XmlElement(ElementName="last_mod_dt", Namespace="http://www.collegenet.com/r25")]
public string Last_mod_dt { get; set; }
[XmlAttribute(AttributeName="crc")]
public string Crc { get; set; }
[XmlAttribute(AttributeName="status")]
public string Status { get; set; }
[XmlAttribute(AttributeName="href", Namespace="http://www.w3.org/1999/xlink")]
public string Href { get; set; }
}
[XmlRoot(ElementName="spaces", Namespace="http://www.collegenet.com/r25")]
public class Spaces {
[XmlElement(ElementName="space", Namespace="http://www.collegenet.com/r25")]
public Space Space { get; set; }
[XmlAttribute(AttributeName="xsi", Namespace="http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName="xl", Namespace="http://www.w3.org/2000/xmlns/")]
public string Xl { get; set; }
[XmlAttribute(AttributeName="r25", Namespace="http://www.w3.org/2000/xmlns/")]
public string R25 { get; set; }
[XmlAttribute(AttributeName="pubdate")]
public string Pubdate { get; set; }
[XmlAttribute(AttributeName="engine")]
public string Engine { get; set; }
}
I have some problems parsing huge xml in c#, mostly because I returned from apex to c# after a long time. So far I cant get working even this
private void read_Click(object sender, EventArgs e)
{
XElement xmlDoc = XElement.Load(#"D:\\AOI\\Samples\\Error\\60A84130868D_20180428035150_AOI-mek1.xml");
var loaded_File =
from fileInfo in xmlDoc.Descendants("result_file")
select new File
{
filename = fileInfo.Element("designator").Value,
supplier = fileInfo.Element("supplier").Value,
date_created = fileInfo.Element("date").Value,
station_ID = fileInfo.Element("station_ID").Value,
operator_ID = fileInfo.Element("operator_ID").Value,
program = fileInfo.Element("program").Value,
side_variant = fileInfo.Element("side_variant").Value
};
foreach(var item in loaded_File) {
System.Diagnostics.Debug.WriteLine(item.ToString());
}
}
Xml file looks as follows with multiple good_no and error_no, can someone navigate me how to load the file properly? I need it afterwards to insert it into database, but that should be just fine.
<result_file>
<filename>60Axxxxxek1</filename>
<supplier>Maxxxxz</supplier>
<date>20xxxx5150</date>
<station_ID>Axxxx1</station_ID>
<operator_ID></operator_ID>
<program>Xxxx01</program>
<side_variant>A</side_variant>
<pcbs_in_panel>0</pcbs_in_panel>
<serial>60xxxxxx8D</serial>
<status>GOOD</status>
<starttime>20180xxxxxx150</starttime>
<lot_no></lot_no>
<info>
<window_no>354</window_no>
<packs_no>343</packs_no>
<error_total>1</error_total>
<error_conf>0</error_conf>
<inspection_time>5</inspection_time>
<panel_image>AOxxxxx_A.jpg</panel_image>
<panel_image_location>x:\xml</panel_image_location>
<ng_image_location>x:\xml\Xxxxx0428</ng_image_location>
<repaired>0</repaired>
</info>
<errors>
<error_no name="1">
<designator></designator>
<pin></pin>
<stamp_name>Bridge:Short</stamp_name>
<package_name></package_name>
<errortype>-</errortype>
<error_contents></error_contents>
<pcb_no></pcb_no>
<feeder_no></feeder_no>
<pos_x>8760</pos_x>
<pos_y>4600</pos_y>
<window>-313</window>
<ng_message></ng_message>
<comment>(* *){Bridge:Short}</comment>
<ng_image>Xxxxxx13.jpg</ng_image>
</error_no>
</errors>
<goods>
<good_no name="1">
<designator>Ixxx1</designator>
<pin>Ixxx1</pin>
<stamp_name>Ixxxxrat</stamp_name>
<package_name>Ixxxx1</package_name>
<pcb_no></pcb_no>
<feeder_no></feeder_no>
<pos_x>3082</pos_x>
<pos_y>3202</pos_y>
<window>+1</window>
<comment>(* *){Ixxxxat}</comment>
</good_no>
</goods>
</result_file>
Thanks for advices.
EDIT:
I have also prepared classes for that
public class File
{
public string name { get; set; }
public string filename { get; set; }
public string supplier { get; set; }
public string date_created { get; set; }
public string station_ID { get; set; }
public string operator_ID { get; set; }
public string program { get; set; }
public string side_variant { get; set; }
public string pcbs_in_panel { get; set; }
public string serial { get; set; }
public string status { get; set; }
public string starttime { get; set; }
public string lot_no { get; set; }
public string window_no { get; set; }
public string packs_no { get; set; }
public string error_total { get; set; }
public string error_conf { get; set; }
public string inspection_time { get; set; }
public string panel_image { get; set; }
public string panel_image_location { get; set; }
public string ng_image_location { get; set; }
public string repaired { get; set; }
public List<Good> Goods = new List<Good>();
public List<Error> Errors = new List<Error>();
}
public class Good
{
public List<Good_no> Good_ones = new List<Good_no>();
}
public class Error
{
public List<Error_no> Error_ones = new List<Error_no>();
}
public class Good_no
{
public string name { get; set; }
public string designator { get; set; }
public string pin { get; set; }
public string stamp_name { get; set; }
public string package_name { get; set; }
public string pcb_no { get; set; }
public string feeder_no { get; set; }
public string pos_x { get; set; }
public string pos_y { get; set; }
public string window { get; set; }
public string comment { get; set; }
}
public class Error_no
{
public string name { get; set; }
public string designator { get; set; }
public string pin { get; set; }
public string stamp_name { get; set; }
public string package_name { get; set; }
public string errortype { get; set; }
public string error_contents { get; set; }
public string pcb_no { get; set; }
public string feeder_no { get; set; }
public string pos_x { get; set; }
public string pos_y { get; set; }
public string window { get; set; }
public string ng_message { get; set; }
public string comment { get; set; }
public string ng_image { get; set; }
}
You should simplify the class structure:
public class File
{
public string Filename { get; set; }
public string Supplier { get; set; }
// ...
public List<Good> Goods { get; set; }
public List<Error> Errors { get; set; }
}
public class Good
{
public string Name { get; set; }
public string Designator { get; set; }
public string Pin { get; set; }
// ...
}
public class Error
{
public string Name { get; set; }
public string Designator { get; set; }
// ...
}
Then the reading would look like this:
var xmlDoc = XElement.Load("test.xml");
var loadedFile = new File
{
Filename = xmlDoc.Element("filename").Value,
Supplier = xmlDoc.Element("supplier").Value,
// ...
Goods = (from good in xmlDoc.Element("goods").Elements("good_no")
select new Good
{
Name = good.Attribute("name").Value,
Designator = good.Element("designator").Value,
Pin = good.Element("pin").Value
// ...
})
.ToList()
};
If you want to read the XML-File, I recommmend you to deserialize the XML-files.
For this, your class-definition isn't complete. In Visual Studio is a tool, called xsd.exe. With this tool you can transform your XML-File first in a XSD-Schema. From the XSD-Schema you can generate the required classes.
To transform to XSD-Schema: xsd.exe {Filename.xml}
To transform to C#-Classes: xsd.exe /c {Filename.xsd}
XSD have many more options (see: https://msdn.microsoft.com/de-de/library/x6c1kb0s(v=vs.120).aspx)
If you have the correct classes you can read the XML-File with the XMLSerializer (see: https://msdn.microsoft.com/de-de/library/tz8csy73(v=vs.110).aspx)
I am working on an ASP.NET MVC application. Basically right now I'am trying to do the following: I created an API helper class that deserializes JSON data returned from Google Books API. In my Create.cshtml I only want to pass the ISBN of the book I am trying to add, however, as I discovered in debugger, ModelState.Is valid is false and therefore the new book does not get created. As far as I can see in the debugger, all the data gets pulled from the API correctly into the dictionary, however for some reason I can't store it my DB.
I know that there is probably a more elegant solution for this, but any kind of advice is more than welcome. Thank you for your time.
Here are the code files that might help:
APIHelper : deserializes JSON data and stores it in a Dictionary.
namespace APIHelper
{
public class IndustryIdentifier
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("identifier")]
public string Identifier { get; set; }
}
public class ReadingModes
{
[JsonProperty("text")]
public bool Text { get; set; }
[JsonProperty("image")]
public bool Image { get; set; }
}
public class ImageLinks
{
[JsonProperty("smallThumbnail")]
public string SmallThumbnail { get; set; }
[JsonProperty("thumbnail")]
public string Thumbnail { get; set; }
}
public class VolumeInfo
{
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("subtitle")]
public string Subtitle { get; set; }
[JsonProperty("authors")]
public IList<string> Authors { get; set; }
[JsonProperty("publisher")]
public string Publisher { get; set; }
[JsonProperty("publishedDate")]
public string PublishedDate { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("industryIdentifiers")]
public IList<IndustryIdentifier> IndustryIdentifiers { get; set; }
[JsonProperty("readingModes")]
public ReadingModes ReadingModes { get; set; }
[JsonProperty("pageCount")]
public int PageCount { get; set; }
[JsonProperty("printType")]
public string PrintType { get; set; }
[JsonProperty("categories")]
public IList<string> Categories { get; set; }
[JsonProperty("maturityRating")]
public string MaturityRating { get; set; }
[JsonProperty("allowAnonLogging")]
public bool AllowAnonLogging { get; set; }
[JsonProperty("contentVersion")]
public string ContentVersion { get; set; }
[JsonProperty("imageLinks")]
public ImageLinks ImageLinks { get; set; }
[JsonProperty("language")]
public string Language { get; set; }
[JsonProperty("previewLink")]
public string PreviewLink { get; set; }
[JsonProperty("infoLink")]
public string InfoLink { get; set; }
[JsonProperty("canonicalVolumeLink")]
public string CanonicalVolumeLink { get; set; }
}
public class SaleInfo
{
[JsonProperty("country")]
public string Country { get; set; }
[JsonProperty("saleability")]
public string Saleability { get; set; }
[JsonProperty("isEbook")]
public bool IsEbook { get; set; }
}
public class Epub
{
[JsonProperty("isAvailable")]
public bool IsAvailable { get; set; }
}
public class Pdf
{
[JsonProperty("isAvailable")]
public bool IsAvailable { get; set; }
}
public class AccessInfo
{
[JsonProperty("country")]
public string Country { get; set; }
[JsonProperty("viewability")]
public string Viewability { get; set; }
[JsonProperty("embeddable")]
public bool Embeddable { get; set; }
[JsonProperty("publicDomain")]
public bool PublicDomain { get; set; }
[JsonProperty("textToSpeechPermission")]
public string TextToSpeechPermission { get; set; }
[JsonProperty("epub")]
public Epub Epub { get; set; }
[JsonProperty("pdf")]
public Pdf Pdf { get; set; }
[JsonProperty("webReaderLink")]
public string WebReaderLink { get; set; }
[JsonProperty("accessViewStatus")]
public string AccessViewStatus { get; set; }
[JsonProperty("quoteSharingAllowed")]
public bool QuoteSharingAllowed { get; set; }
}
public class SearchInfo
{
[JsonProperty("textSnippet")]
public string TextSnippet { get; set; }
}
public class Item
{
[JsonProperty("kind")]
public string Kind { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("etag")]
public string Etag { get; set; }
[JsonProperty("selfLink")]
public string SelfLink { get; set; }
[JsonProperty("volumeInfo")]
public VolumeInfo VolumeInfo { get; set; }
[JsonProperty("saleInfo")]
public SaleInfo SaleInfo { get; set; }
[JsonProperty("accessInfo")]
public AccessInfo AccessInfo { get; set; }
[JsonProperty("searchInfo")]
public SearchInfo SearchInfo { get; set; }
}
public class RootObject
{
[JsonProperty("kind")]
public string Kind { get; set; }
[JsonProperty("totalItems")]
public int TotalItems { get; set; }
[JsonProperty("items")]
public IList<Item> Items { get; set; }
}
public class APIHelper
{
public string Get(string uri)
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(uri);
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
public Dictionary<string, string> DictionaryReturnData(string isbn)
{
string path = "https://www.googleapis.com/books/v1/volumes?q=isbn:" + isbn;
string json = Get(path);
Dictionary<string, string> responses = new Dictionary<string, string>();
var rootObject = JsonConvert.DeserializeObject<RootObject>(json);
foreach (var obj in rootObject.Items )
{
responses.Add("Title", obj.VolumeInfo.Title);
responses.Add("Description", obj.VolumeInfo.Description);
responses.Add("Image", obj.VolumeInfo.ImageLinks.Thumbnail);
responses.Add("Authors", string.Join(",", obj.VolumeInfo.Authors)); //list of strings
responses.Add("Genre", string.Join(",", obj.VolumeInfo.Categories)); //list of strings
responses.Add("Isbn", isbn);
responses.Add("Publisher", obj.VolumeInfo.Publisher);
responses.Add("PublishedDate", obj.VolumeInfo.PublishedDate);
responses.Add("PageCount", obj.VolumeInfo.PageCount.ToString());
}
return responses;
}
}
}
My Book class:
namespace BookstoreWeb.Models
{
public class Book
{
public int Id { get; set; }
[Required]
public string Isbn { get; set; }
[Required]
public string Title { get; set; }
public string Author { get; set; }
public double Price { get; set; }
[Required]
public string Description { get; set; }
public string Publisher { get; set; }
public string PublishedDate { get; set; }
public string PageCount { get; set; }
public string Thumbnail { get; set; }
public string Genre { get; set; }
}
}
Create Action
[HttpPost]
public IActionResult Create(Book model)
{
APIHelper.APIHelper helper = new APIHelper.APIHelper();
var responses = helper.DictionaryReturnData(model.Isbn);
model.Author = responses["Authors"];
model.Genre = responses["Genre"];
model.Isbn = responses["Isbn"];
model.Price = 10.00;
model.Title = responses["Title"];
model.Description = responses["Description"];
model.Publisher = responses["Publisher"];
model.PublishedDate = responses["PublishedDate"];
model.PageCount = responses["PageCount"];
model.Thumbnail = responses["Image"];
if (ModelState.IsValid) //check for validation
{
var newBook = new Book
{
Author = model.Author,
Genre = model.Genre,
Isbn = model.Isbn,
Price = model.Price,
Title = model.Title,
Description = model.Description,
Publisher = model.Publisher,
PublishedDate = model.PublishedDate,
PageCount = model.PageCount,
Thumbnail = model.Thumbnail,
};
newBook = _bookstoreData.Add(newBook);
_bookstoreData.Commit();
return RedirectToAction("Details", new {id = newBook.Id});
}
Removing the annotations [Required] from Book class seems to have solved the issue.
I have a XML as below. I want to convert this to c# object . I tried modyfying but could not get it working.
<SLVGeoZone-array>
<SLVGeoZone>
<id>19</id>
<type>geozone</type>
<name>60_OLC_SC</name>
<namesPath>GeoZones/60_OLC_SC</namesPath>
<idsPath>1/19</idsPath>
<childrenCount>0</childrenCount>
</SLVGeoZone>
</SLVGeoZone-array>
I have a written a sample c# code and it doesn't work:
[Serializable]
public class SLVGeoZone
{
[XmlElement("id")]
public string id { get; set; }
[XmlElement("type")]
public string type { get; set; }
[XmlElement("name")]
public string name { get; set; }
[XmlElement("namespath")]
public string namespath { get; set; }
[XmlElement("idspath")]
public string idspath { get; set; }
[XmlElement("childrencount")]
public string childrencount { get; set; }
}
[Serializable]
[XmlRoot("SLVGeoZone-array")]
public class SLVGeoZone-array
{
[XmlArray("SLVGeoZone-array")]
[XmlArrayItem("SLVGeoZone", typeof(SLVGeoZone))]
public SLVGeoZone[] Car { get; set; }
}
And in the form:
XmlSerializer serializer = new XmlSerializer(typeof(CarCollection));
StreamReader reader = new StreamReader(path);
cars = (CarCollection)serializer.Deserialize(reader);
reader.Close();
Can someone suggest what am i doing wrong?
SLVGeoZone-array is not a valid class name in C#
[Serializable()]
[XmlRoot("SLVGeoZone-array")]
public class SLVGeoZones
{
[XmlElement("SLVGeoZone")]
public SLVGeoZone[] Cars { get; set; }
}
XmlElement attribute values have to be exactly the same as element names in XML file. Yours are not.
[Serializable()]
public class SLVGeoZone
{
[XmlElement("id")]
public string id { get; set; }
[XmlElement("type")]
public string type { get; set; }
[XmlElement("name")]
public string name { get; set; }
[XmlElement("namesPath")]
public string namespath { get; set; }
[XmlElement("idsPath")]
public string idspath { get; set; }
[XmlElement("childrenCount")]
public string childrencount { get; set; }
}
What is CarCollection and why are you trying to deserialize your XML as CarCollection instead of classes you've shown here?
XmlSerializer serializer = new XmlSerializer(typeof(SLVGeoZones));
StreamReader reader = new StreamReader("Input.txt");
var items = (SLVGeoZones)serializer.Deserialize(reader);
reader.Close();
I am trying to deserialize the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<jobInfo
xmlns="http://www.force.com/2009/06/asyncapi/dataload">
<id>750x0000000005LAAQ</id>
<operation>insert</operation>
<object>Contact</object>
<createdById>005x0000000wPWdAAM</createdById>
<createdDate>2009-09-01T16:42:46.000Z</createdDate>
<systemModstamp>2009-09-01T16:42:46.000Z</systemModstamp>
<state>Open</state>
<concurrencyMode>Parallel</concurrencyMode>
<contentType>CSV</contentType>
<numberBatchesQueued>0</numberBatchesQueued>
<numberBatchesInProgress>0</numberBatchesInProgress>
<numberBatchesCompleted>0</numberBatchesCompleted>
<numberBatchesFailed>0</numberBatchesFailed>
<numberBatchesTotal>0</numberBatchesTotal>
<numberRecordsProcessed>0</numberRecordsProcessed>
<numberRetries>0</numberRetries>
<apiVersion>28.0</apiVersion>
</jobInfo>
I have created this object:
public class JobInfo
{
public string xmlns { get; set; }
public string id { get; set; }
public string operation { get; set; }
public string #object { get; set; }
public string createdById { get; set; }
public string createdDate { get; set; }
public string systemModstamp { get; set; }
public string state { get; set; }
public string concurrencyMode { get; set; }
public string contentType { get; set; }
public string numberBatchesQueued { get; set; }
public string numberBatchesInProgress { get; set; }
public string numberBatchesCompleted { get; set; }
public string numberBatchesFailed { get; set; }
public string numberBatchesTotal { get; set; }
public string numberRecordsProcessed { get; set; }
public string numberRetries { get; set; }
public string apiVersion { get; set; }
}
public class RootObject
{
public JobInfo jobInfo { get; set; }
}
And, I am using this code:
XmlSerializer serializer = new XmlSerializer(typeof(RootObject));
StringReader rdr = new StringReader(response);
RootObject resultingMessage = (RootObject)serializer.Deserialize(rdr);
However, I get this error:
There is an error in XML document (1, 40).
{"<jobInfo xmlns='http://www.force.com/2009/06/asyncapi/dataload'> was not expected."}
How can I account for the xmlns attribute? My code has it as a property (thus, it fails)...
Currently your code is expecting the xmlns as element, not the attribute.
You should add the XmlSerialization attributes to your class, like this:
[XmlRoot("jobInfo", Namespace="http://www.force.com/2009/06/asyncapi/dataload"]
public class JobInfo
{
[XmlAttribute]
public string xmlns { get; set; }
[XmlElement(ElementName = "id")]
public string id { get; set; }
....
}
You can find more information in MSDN articles:
Controlling XML Serialization Using Attributes
Examples of XML Serialization
Try using the XmlRootAttribute to specify the Namespace.
[XmlRoot("jobInfo", Namespace = "http://www.force.com/2009/06/asyncapi/dataload")]
public class JobInfo
{
[XmlElement("id")]
public string Id { get; set; }
[XmlElement("operation")]
public string Operation { get; set; }
[XmlElement("object")]
public string Object { get; set; }
[XmlElement("createdById")]
public string CreatedById { get; set; }
[XmlElement("createdDate")]
public DateTime CreatedDate { get; set; }
[XmlElement("systemModstamp")]
public DateTime SystemModstamp { get; set; }
[XmlElement("state")]
public string State { get; set; }
[XmlElement("concurrencyMode")]
public string ConcurrencyMode { get; set; }
[XmlElement("contentType")]
public string ContentType { get; set; }
[XmlElement("numberBatchesQueued")]
public string NumberBatchesQueued { get; set; }
[XmlElement("numberBatchesInProgress")]
public string NumberBatchesInProgress { get; set; }
[XmlElement("numberBatchesCompleted")]
public string NumberBatchesCompleted { get; set; }
[XmlElement("numberBatchesFailed")]
public string NumberBatchesFailed { get; set; }
[XmlElement("numberBatchesTotal")]
public string NumberBatchesTotal { get; set; }
[XmlElement("numberRecordsProcessed")]
public string numberRecordsProcessed { get; set; }
[XmlElement("numberRetries")]
public string NumberRetries { get; set; }
[XmlElement("apiVersion")]
public string ApiVersion { get; set; }
}
Code:
var xml = #"<?xml version=""1.0"" encoding=""UTF-8""?>
<jobInfo xmlns=""http://www.force.com/2009/06/asyncapi/dataload"">
<id>750x0000000005LAAQ</id>
<operation>insert</operation>
<object>Contact</object>
<createdById>005x0000000wPWdAAM</createdById>
<createdDate>2009-09-01T16:42:46.000Z</createdDate>
<systemModstamp>2009-09-01T16:42:46.000Z</systemModstamp>
<state>Open</state>
<concurrencyMode>Parallel</concurrencyMode>
<contentType>CSV</contentType>
<numberBatchesQueued>0</numberBatchesQueued>
<numberBatchesInProgress>0</numberBatchesInProgress>
<numberBatchesCompleted>0</numberBatchesCompleted>
<numberBatchesFailed>0</numberBatchesFailed>
<numberBatchesTotal>0</numberBatchesTotal>
<numberRecordsProcessed>0</numberRecordsProcessed>
<numberRetries>0</numberRetries>
<apiVersion>28.0</apiVersion>
</jobInfo>";
var serializer = new XmlSerializer(typeof(JobInfo));
JobInfo jobInfo;
using(var stream = new StringReader(xml))
using(var reader = XmlReader.Create(stream))
{
jobInfo = (JobInfo)serializer.Deserialize(reader);
}
Add the namespace
[XmlRoot("jobInfo",Namespace = "http://www.force.com/2009/06/asyncapi/dataload")]
public class JobInfo
{
// get rid of the xmlns property
// other properties stay
}
// there is no rootobject, JobInfo is your root
XmlSerializer serializer = new XmlSerializer(typeof(JobInfo));
StringReader rdr = new StringReader(response);
JobInfo resultingMessage = (JobInfo)serializer.Deserialize(rdr);