XML serializer error thrown

M J 661 Reputation points
2022-01-17T23:47:35.893+00:00

I am using an xml deserializer to read the contents of an xml file. This is using a resume parsing service. It has been working great for the past year or so but today threw an error pointing to the line

FullAddress = EmployerCity + ", " + EmployerState;  

I have the following code in the controller

[ValidateAntiForgeryToken]  
[HttpPost]  
public ActionResult Index(int JobID, string FirstName, string MiddleName, string LastName, string Email, string ReferringSite, HttpPostedFileBase Resume)  
{  
	string product_code = myProduct Code;  
	string FileName = Resume.FileName;  
	string encoded = FileName;  
	string UserID = "";  
  
	if(Resume.ContentLength > 0)  
	{  
		string Address = "";  
		string City = "";  
		string State = "";  
		string Zip = "";  
		string AreaCode = "";  
		string LineNumber = "";  
		string Telephone = "";  
		string PhoneType = "";  
  
		int x = 1;  
  
		string Qualifications = "";  
		string Licenses = "";  
		string Achievements = "";  
  
		try  
		{  
			Applicant applicant = new Applicant();  
  
			//Try to save the data.  If it does not return a userid then the Application for this position has been started or completed.  
			UserID = applicant.StartApplication(FirstName, MiddleName, LastName, JobID, Email, Request.UserHostAddress, Request.UserAgent, "VA", ReferringSite);  
			UserID = UserID.Trim();  
			if (UserID.Equals("Completed", StringComparison.CurrentCultureIgnoreCase))  
			{  
				ViewBag.Message = "We have a completed application for this position on file.";  
				ViewBag.Status = "";  
				ViewBag.Started = true;  
				ViewBag.Completed = true;  
				ViewBag.Active = true;  
				return View();  
			}  
  
			if (UserID.Equals("XXXXXX", StringComparison.CurrentCultureIgnoreCase))  
			{  
				string Status = applicant.GetStatus(FirstName, MiddleName, LastName, JobID, Email).Trim();  
				UserID = applicant.GetUserID(FirstName, MiddleName, LastName, JobID, Email);  
				if (Status == "B")  
				{  
					TempData["UserID"] = UserID;  
					return RedirectToAction("AppInfo");  
				}  
				ViewBag.Message = "We have an incomplete application for this position on file. Your ID is " + UserID;  
				ViewBag.Started = true;  
				ViewBag.Completed = false;  
				ViewBag.Active = true;  
				return View();  
			}  
  
			//convert resume to base 64 string  
			using (BinaryReader br = new BinaryReader(Resume.InputStream))  
			{  
				int fileSize = Resume.ContentLength;  
				byte[] binaryStream = br.ReadBytes((int)Resume.ContentLength);  
				encoded = Convert.ToBase64String(binaryStream);  
				br.Close();  
			}  
  
			//Instantiate the web service object  
			com.resumeparser.processing.ParsingToolsService hireability = new com.resumeparser.processing.ParsingToolsService();  
			//the first empty element in the next two methods is where we would put our unique identifier.  it is not needed though.  
  
			//Send resume over for parsing and get the results  
			string results = hireability.ParseDocNew(product_code, FileName, encoded, "", "", "", "");  
  
			Configuration config = WebConfigurationManager.OpenWebConfiguration("~");  
            string NotificationEmail = ConfigurationManager.AppSettings["NotificationEmail"].ToString();  
			  
			//Sending me an email   
			bool SendXML = Convert.ToBoolean(ConfigurationManager.AppSettings["SendXML"].ToString());  
			if(SendXML)  
			{  
				SendTheEmail(NotificationEmail, UserID + " parsed resume results", results);  
			}  
  
			//remove all line breaks from the xml  
			results = results.Replace("\n", "");  
			int startpos;  
			int endpos;  
			int remove;  
			if (results.Contains("<NonXMLResume>"))  
			{  
				//Remove the text version of resume  
				startpos = results.IndexOf("<NonXMLResume>");  
				endpos = results.IndexOf("</NonXMLResume>");  
				remove = (endpos + 15) - startpos;  
				if (startpos != 0)  
				{  
					results = results.Remove(startpos, remove);  
				}  
			}  
			//Remove the comment inside the xml document  
			startpos = results.IndexOf("<!--");  
			endpos = results.IndexOf("<Results>");  
			remove = endpos - startpos;  
			if (startpos != 0)  
			{  
				results = results.Remove(startpos, remove);  
			}  
  
			var mySerializer = new XmlSerializer(typeof(Results));  
			Stream myFileStream = GenerateStreamFromString(results);  
			var obj = (Results)mySerializer.Deserialize(myFileStream);  
			int remaining = obj.HireAbilityXMLResults.remainingUsage;  
			// has Miranda been notified of   
   
			bool notified = Convert.ToBoolean(ConfigurationManager.AppSettings["Notified"].ToString());  
			/*  
			* The expiration will change when more credits are added.  We have 1 year from date credits are added to bump up and add more,   
			* otherwise they will expire.  Credits left over will roll over when new ones are added.  
			*/  
			DateTime Expiration = Convert.ToDateTime(obj.HireAbilityXMLResults.accountValidThrough);  
			DateTime ExpirationDate = Convert.ToDateTime(ConfigurationManager.AppSettings["ExpirationDate"].ToString());  
			//if expiration is greater than what we have stored then more credits have been added so update the config to show new date.                      
			if(Expiration > ExpirationDate)  
			{  
				config.AppSettings.Settings["ExpirationDate"].Value = Expiration.ToString();  
			}  
  
			//update the web.config setting so that we can easily look up how many credits are remaining.  
			config.AppSettings.Settings["RemainingUsage"].Value = remaining.ToString();  
			if (remaining < 100)  
			{  
  
				if (!notified)  
				{  
					//send an email   
					SendTheEmail(NotificationEmail, "Hireability.com resume parsing service is getting low on credits.", "The resume parsing service is down to " + remaining.ToString() + " resumes that can be parsed.");  
					//Mark as true so we don't get an email each time  
					config.AppSettings.Settings["Notified"].Value = "true";  
				}  
				else  
				{  
					if (remaining == 50 | remaining == 25)  
					{  
						//send an email, this time add Eric to the emails!  
						SendTheEmail(NotificationEmail +";"+EricEmail, "Hireability.com resume parsing service is getting low on credits.", "The resume parsing service is down to " + remaining.ToString() + " resumes that can be parsed.");  
					}  
				}  
			}  
			else  
			{  
				if (!notified)  
				{  
					//Reset so that it will notify again when it hits 100  
					config.AppSettings.Settings["Notified"].Value = "false";  
				}  
			}  
			DateTime now = DateTime.Now;  
			int remainingDays = Expiration.Subtract(now).Days;  
			if (remainingDays < 30)  
			{  
				bool ExpirationNotification = Convert.ToBoolean(ConfigurationManager.AppSettings["ExpirationNotification"].ToString());  
				if (!ExpirationNotification)  
				{  
					//Send an email about pending expiration.  
					SendTheEmail(NotificationEmail, "The hireability.com resume parsing service account expires soon.", "The resume parsing service is set to expire on " + Expiration.ToShortDateString() + ". We will need to purchase more credits before that date to keep it active.");  
					//Mark as true so we don't get an email each time  
					config.AppSettings.Settings["ExpirationNotification"].Value = "true";  
				}  
			}  
  
			if (obj.HireAbilityXMLResults.Resume != null)  
			{  
				if (obj.HireAbilityXMLResults.Resume.StructuredXMLResume != null)  
				{  
					string name = obj.HireAbilityXMLResults.Resume.StructuredXMLResume.ContactInfo.PersonName.GivenName.ToString();  
  
					var contactMethod = obj.HireAbilityXMLResults.Resume.StructuredXMLResume.ContactInfo.ContactMethod;  
					foreach (var cm in contactMethod)  
					{  
						if (cm.PostalAddress != null)  
						{  
							Address = cm.PostalAddress.DeliveryAddress.AddressLine.ToString();  
							City = cm.PostalAddress.Municipality.ToString();  
							State = cm.PostalAddress.Region.ToString();  
							Zip = cm.PostalAddress.PostalCode.ToString();  
							applicant.AddAddress(UserID, Address.LimitLength(100), City.LimitLength(35), State, Zip);  
						}  
						if (cm.Telephone != null)  
						{  
							AreaCode = cm.Telephone.AreaCityCode.ToString();  
							LineNumber = cm.Telephone.SubscriberNumber.ToString();  
							string pType = cm.Location.ToString();  
							switch (pType)  
							{  
								case "home":  
									PhoneType = "Home";  
									break;  
								case "onPerson":  
									PhoneType = "Cell";  
									break;  
								default:  
									PhoneType = "Home";  
									break;  
							}  
							Telephone = AreaCode + "-" + LineNumber;  
							//We have a phone number save it.  
							applicant.AddTelephone(UserID, Telephone, PhoneType);  
						}  
						if (cm.Mobile != null)  
						{  
							AreaCode = cm.Mobile.AreaCityCode.ToString();  
							LineNumber = cm.Mobile.SubscriberNumber.ToString();  
							Telephone = AreaCode + "-" + LineNumber;  
							applicant.AddTelephone(UserID, Telephone, "Cell");  
						}  
					}  
  
					var empHistory = obj.HireAbilityXMLResults.Resume.StructuredXMLResume.EmploymentHistory;  
					foreach (var emp in empHistory)  
					{  
						string EmployerName = "";  
						string Title = "";  
						string EmployerAddress = "";  
						string EmployerCity = "";  
						string EmployerState = "";  
						string StartDate = "";  
						string EndDate = "";  
						string Duties = "";  
						string FullAddress = "";  
						bool Current = false;  
  
  
						EmployerName = emp.EmployerOrgName.ToString();  
						if (emp.PositionHistory != null)  
						{  
							if (emp.PositionHistory.OrgInfo != null)  
							{  
								if (emp.PositionHistory.OrgInfo.PositionLocation != null)  
								{  
									if (emp.PositionHistory.OrgInfo.PositionLocation.DeliveryAddress != null)  
									{  
										EmployerAddress = emp.PositionHistory.OrgInfo.PositionLocation.DeliveryAddress.ToString();  
									}  
									if (emp.PositionHistory.OrgInfo.PositionLocation.Municipality != null)  
									{  
										EmployerCity = emp.PositionHistory.OrgInfo.PositionLocation.Municipality.ToString();  
									}  
									if (emp.PositionHistory.OrgInfo.PositionLocation.Region != null)  
									{  
										EmployerState = emp.PositionHistory.OrgInfo.PositionLocation.Region.ToString();  
									}  
									FullAddress = EmployerAddress + " " + EmployerCity + ", " + EmployerState;  
									if (FullAddress.Length > 50)  
									{  
										FullAddress = EmployerCity + ", " + EmployerState;  
									}  
								}  
							}  
							if (emp.PositionHistory.Title != null)  
							{  
								Title = emp.PositionHistory.Title.ToString();  
							}  
							if (emp.PositionHistory.Description != null)  
							{  
								Duties = emp.PositionHistory.Description.ToString();  
							}  
							StartDate = emp.PositionHistory.StartDate.AnyDate.ToString();  
							EndDate = emp.PositionHistory.EndDate.AnyDate.ToString();  
							if (EndDate == "current")  
							{  
								Current = true;  
							}  
						}  
  
						//We have some employer information.  Now save the info to database  
						Employer employer = new Employer();  
						employer.Add(UserID, EmployerName, Title.LimitLength(50), Duties.LimitLength(200), FullAddress.LimitLength(50), StartDate + " - " + EndDate, Current, x);  
						x++;  
					}  
					x = 1;  
  
					   
					//The information was saved, so rename resume and save to server.  
					string fileName = UserID + "_Resume" + Path.GetExtension(Resume.FileName);  
					string _path = Path.Combine(@"E:\WebPages\Non CRIW\OhmartVega\Application\resumes", fileName);  
					//string _path = Path.Combine(@"X:\Non CRIW\OhmartVega\Application\resumes", fileName);   //For development when on my desktop  
					Resume.SaveAs(_path);  
  
					//Save renamed resume name to database  
					applicant.AddResume(UserID, fileName);  
  
					TempData["UserID"] = UserID;  
					TempData["Email"] = Email;  
					return RedirectToAction("AppInfo");  
  
				}  
			}  
			else  
			{  
			   
				//Send an email  
				SendTheEmail(NotificationEmail, "Hireability.com resume parsing service error thrown", results);  
				//Since there was an error delete the record  
				applicant.Delete(UserID);  
  
				string err = obj.HireAbilityXMLResults.processingErrors.Error.ErrorCode.ToString();                         
				   
				//snipped for brevity  
				ViewBag.Started = false;  
				ViewBag.Completed = false;  
				ViewBag.Active = false;  
				return View();  
			}  
		}  
		catch (Exception ex)  
		{  
			Errors.ErrorOccured(ex);  
		}  
	}  
	else  
	{  
		ViewBag.Message = "No resume was selected to upload.";  
		return View();  
	}  
	ViewBag.Active = true;  
	ViewBag.Message = "Your resume cannot be parsed.";  
	ViewBag.Started = false;  
	ViewBag.Completed = false;  
	ViewBag.Active = false;  
	return View();  
  
}  

I have attached the serialization class165775-resultscs.txt

In this user's resume there was an employer shown where it did not have this node
emp.PositionHistory.OrgInfo and from what I can tell that is what caused the null object reference

I thought this would check if the object was there
if (emp.PositionHistory.OrgInfo != null)

So how do I check if the reference is null if this is not the correct way to do so?

ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,239 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Lan Huang-MSFT 25,231 Reputation points Microsoft Vendor
    2022-01-18T06:30:47.75+00:00

    Hi @M J ,

    but today threw an error pointing to the line

    Maybe you can provide detailed error message.
    The problem you said is because the reference object is empty, it is recommended that you debug the breakpoint check code.
    I think only FullAddress.Length > 50 will trigger the error line.
    Regarding the issue of empty object references, I suggest that you can do some exception handling when the reference is empty.

     FullAddress = EmployerAddress + " " + EmployerCity + ", " + EmployerState;  
      if (FullAddress.Length > 50)  
      {  
             FullAddress = EmployerCity + ", " + EmployerState;  
      }  
    

    Edit:
    You can try the XmlNode.SelectSingleNode method to select the first XmlNode that matches the XPath expression.
    https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmlnode.selectsinglenode?view=net-6.0

    var idNode = doc.SelectSingleNode("/*[local-name()='Bookstore']");  
    if(idNode != null)  
    {  
         Console.WriteLine(idNode.InnerText);  
    }  
    

    Best regards,
    Lan Huang


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.