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?