Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

What to do about NullReferenceException?

Posted on 2009-05-14
5
Medium Priority
?
312 Views
Last Modified: 2012-05-07
Hey everyone,

I'm reading an XML document, and assigning the attribute values to various textboxes.  This works perfectly fine so long as the attributes are there, if they aren't I get a NullReference exception.  

As my code is like the following:
 txtPostalName.Text = nodeCorAdd.Attributes.GetNamedItem("postalname").Value;

What can I do if the attribute isn't in the XML document?  I really don't want to have go:
if(nodeCorAdd.Attributes.GetNamedItem("postalname").Value != null) for each attribute.  
0
Comment
Question by:angus_young_acdc
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
5 Comments
 
LVL 11

Expert Comment

by:William
ID: 24385118
if you perform a loop for all your items and test for null - you can set them to string.empty if they are null, then when populating your textboxes it will not bomb on yu
0
 
LVL 12

Expert Comment

by:GuitarRich
ID: 24385204
you could write a routine to convert to NonNullableString like this:
private string ToNonNullableString(object value)
{
    string result = string.empty;
    if (value != null)
    {
        result = value.ToString();
    }
    return result;
}
 
// Then call it like this:
txtPostalName.Text = ToNonNullableString(nodeCorAdd.Attributes.GetNamedItem("postalname").Value);

Open in new window

0
 
LVL 16

Expert Comment

by:ToddBeaulieu
ID: 24385239
Actually, I think your example check is checking the value of the item for null, but if the attribute doesn't exist, won't THAT check fail because the object reference is NULL, thereby preventing checking its value. I assume that's how GetNamedItem works ... by returning a null if it's not found.

Anyway, why not create a small wrapper function that does both checks. Then you just call the wrapper, once for each field.

Off the top of my head, I don't know the Class names returned by these, so I'll use "var" as a placeholder...

MyWrapperToSetFieldValue(txtPostalName, "postalname");

private void MyWrapperToSetFieldValue(Control ctl, string fieldName)
{
    var node = nodeCorAdd.Attributes.GetNamedItem(fieldName);
    if (var != null && var.Value != null)
    {
        ctl.Text = var.Value;
    }
    else {
       ctl.Text = string.empty; // can also use TextBox as the type, if they're all text boxes. and make wrapper classes for each type (overloading) or determnine type of control in here.
    }
}
0
 
LVL 9

Expert Comment

by:tculler
ID: 24385369
Well, which part is returning null--GetNamedItem, or the Value property of the returned item? Also, to clean up your code, you can use the "Coalesce" operator, written as "??". It works like this:

System.String someString = stringValuePossiblyNull ?? "Fallback if the value to the left is null";

The compiler, in this case, will check the value of "stringValuePossiblyNull"; if it is null, it will assign the vaule to the right of the coalesce operator. If it is not null, it will assign the value as usual.

Another option is to use an XML schema in which you require certain attributes. There are quite a few ways of going about your problem, but really, I hate to say it, but you're being lazy here. There's no reason you can't check for something as necessary as this--not everything can be just seamlessly built in and magically done FOR you.

Anyways, a more specific solution is provided in the following code snippet. If my thoughts are correct, it will still throw a NullReferenceException because I think you're checking the wrong value for "null", but we'll see :)

Hope it helps,
Nate
txtPostalName.Text = nodeCorAdd.Attributes.GetNamedItem("postalname").Value ?? System.String.Empty;
 
// If this doesn't work, and you're worried about too many lines, of code, you could use the following,
// assuming the returned item is null (which I'm thinking it is)
 
txtPostalName.Text = (nodeCorAdd.Attributes.GetNamedItem("postalname") != null) ?nodeCorAdd.Attributes.GetNamedItem("postalname").Value ?? System.String.Empty : System.String.Empty;
 
// This performs a check for both fields that may be null.

Open in new window

0
 
LVL 15

Accepted Solution

by:
angus_young_acdc earned 0 total points
ID: 24394089
Hey everyone, I solved my problem yesterday (but didn't have the chance to close the thread).  It isn't the most pretty solution, but it works.  What I ended up doing (similar to what was suggested after I done it) was to add a tag to each control, this tag was the attribute name.  Then when I attempt to get the data it will only pull back the attributes which exist, to do this I use the following:

 XmlNodeList listSecAdd = document.SelectNodes(_node);
                XmlNode nodeSecAdd;
                for (int i = 0; i < listSecAdd.Count; i++)
                {
                    nodeSecAdd = listSecAdd[i];
                    foreach (XmlAttribute att in nodeSecAdd.Attributes)
                    {
                        string theAttribute = att.Name.ToString();
                        foreach (Control secControl in tabAddress.Controls)
                        {
                            if (secControl.Name.Contains("txt")
                                && string.IsNullOrEmpty(secControl.Text))
                            {
                                if (secControl.Tag.ToString() == theAttribute)
                                {
                                    secControl.Text = nodeSecAdd.Attributes.GetNamedItem(theAttribute).Value;
                                    secControl.Enabled = true;
                                }
                                else
                                {
                                    secControl.Enabled = false;
                                }
                            }
                        }
                    }
                }

The reasoning behind disabling the control is so that the user won't enter data thinking it will be saved, so that only enabled text boxes (which are attributes in the XML) can be updated.  This means I can use the following to update:
 XmlNodeList securityList = document.SelectNodes(_node);
                XmlNode security;
                for (int i = 0; i < securityList.Count; i++)
                {
                    security = securityList[i];
                    foreach (Control secCont in tabAddress.Controls)
                    {
                        if (secCont.Enabled)
                        {
                            security.Attributes.GetNamedItem(secCont.Tag.ToString()).Value = secCont.Text;
                        }
                    }
                }
                document.Save(_xmlLocation);

tculler I wouldn't exactly call it lazy, more an attempt at code reduction and future proofing.  Currently there are over 110 different attributes which can be in the XML, these can be in any combination.  So, assuming that for the considerable future this throw away style app will have 110 controls, is it beneficial doing the == null check?  It seems like it may be an unnecessary amount of code to check if an attribute exists before populating or saving.  

I'm not overly sure if the method I have created is actually efficient, or potential pitfalls that may happen, so any advice would be great.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
This article aims to explain the working of CircularLogArchiver. This tool was designed to solve the buildup of log file in cases where systems do not support circular logging or where circular logging is not enabled
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…

721 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question