Solved

What to do about NullReferenceException?

Posted on 2009-05-14
5
268 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
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

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
network + 7 73
Bubble user-defined Sql RAISERROR(...) to c# exception 14 118
LINQ question 7 22
getting id from database 5 24
This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

746 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

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now