I need to receive an XML post then process all the data, and do whatever I need to do with the data. I could be receiving anywhere from 60 to 100 values. I know what all the elements are going to be, and all except one is mandatory. For billing, it could either be credit card info or checking info, so I need to check the first child's name to see what the billing type is.
Here is a cut-down example:
<XmlData>
<FirstName>FirstName</FirstName>
<LastName>LastName</LastName>
<Address>666 S st.</Address>
<Email>[email protected]</Email>
<City>Beverly Hills</City>
<Zip>90210</Zip>
<PhoneNumber>5555555555</PhoneNumber>
<!-- 14more nodes -->
<Billing>
<CCType>Visa</CCType>
<CCNumber>55554443332221</CCNumber>
<! -- 8 More Nodes for billing -->
</Billing>
</XmlData>
Now, here is how I am handling processing the data. In my Page_Load
, I am first calling a method that will verify the XML is well formatted and not null(not posting this code). Next, I call a method that will read all the data and assign it private fields using LINQ to XML.
private string firstName = string.Empty;
private string lastName = string.Empty;
private string address = string.Empty;
private string email= string.Empty;
private string city= string.Empty;
private string zip = string.Empty;
private Int64 phoneNumber;
private string billingMethod = string.Empty;
private string ccType = string.Empty;
private Int64 ccNumber;
private void ReadXml(){
using (StringReader sr = new StringReader(payload)) {
xd = XDocument.Load(sr);
}
var node = xd.Root;
//lets just make sure all the nodes we need are present, then continue
//this is where billingMethod is assigned; after validating the Billing
//node is present, it will check if I am getting credit card info or check
//info, then assign "credit" or "check" to billingMethod
ValidateNeededNodesPresent(node);
if (errors.Count > 0) {
Response();
return;
}
//verify the nodes are not null, and assign them
firstName= VerifyString(node.Element(XmlKey.FirstName).Value, XmlKey.FirstName);
lastName= VerifyString(node.Element(XmlKey.LastName).Value, XmlKey.LastName);
zip = ValidateStringMax(node.Element(XmlKey.Zip).Value, XmlKey.Zip, 5);
email = VerifyString(node.Element(XmlKey.Email).Value, XmlKey.Email);
address= VerifyString(node.Element(XmlKey.Address).Value, XmlKey.Address);
city= ValidateData(node.Element(XmlKey.City).Value, XmlKey.City);
phoneNumber = VerifyInt64(node.Element(XmlKey.PhoneNumber).Value, XmlKey.PhoneNumber);
if(billingMethod == "credit")
{
ccNumber = VerifyInt64(node.Element(XmlKey.Billing).Element(XmlKey.CCNumber).Value, XmlKey.CCdNumber);
ccType = VerifyString(
node.Element(XmlKey.Billing).Element(XmlKey.CCType).Value, XmlKey.CCType);
}
}
Now, here is my list of verify classes that check to make sure the data is not null and in the correct format (int
, int64
, DateTime
, etc.). If it is not in the correct format, it will add an error to errors. The way is grabs errors is by getting the error string from a dictionary, where the key is the XML node name, and the value is the error message:
public Int64 VerifyInt64(string data, string element)
{
Int64 number = 0L;
if (!Int64.TryParse(data, out number) || String.IsNullOrEmpty(data))
{
errors.Add(ErrorDictionary.Errors[element]);
}
return number;
}
public string VerifyString(string data, string element)
{
if (String.IsNullOrEmpty(data) || String.IsNullOrEmpty(data))
{
errorMessages.Add(ErrorDictionary.Errors[element]);
}
return data;
}
public string VerifyStringMax(string data, string element, int lengthMax)
{
if (data.Length > lengthMax || String.IsNullOrEmpty(data))
{
errors.Add(ErrorDictionary.Errors[element]);
}
return data;
}
The code works fine, but I cant help but think that I did more than I needed to. I'm strictly speaking about how I'm reading the XML, validating data, and assigning values in this case.
Is this code efficient? Is there a better way I can go about reading XML data and assigning values while validating the data?