VB .Net NullReferenceException work-around

18,121

Solution 1

You can use If(a, b) to coalesce a null to another value. Example:

Dim obj as String = Nothing
Dim foo as String = If(obj, "foo")

The output of foo in this example will be the string "foo". If you had a non-null string assigned to obj, then foo would also reference that string.

However, I have a strong feeling that your null reference exception could be happening not on the property, but on the object. Order or ShippingAddress could be null. Accessing properties or methods on a null reference is an error. Simply accessing a null value by storing it to a variable is not an error in and of itself.

If you are getting your exception on one of these lines

CompanyName = Order.ShippingAddress.CompanyName 
State = Order.ShippingAddress.StateOrProvince

It is because either Order or ShippingAddress is null.

Check and see if these objects could actually return as nothing. If so, you will need to apply null-checking around them prior to accessing their properties.


Your update:

There is updated code please note no exception is thrown until:

BillingCompany = If(Order.ShippingAddress.CompanyName.ToString(), "")

is executed.

This can throw because Order can be null, ShippingAddress can be null, or CompanyName can be null. It is an exception to access a property or a method on a null reference. If Order is null, you will get an error accessing ShippingAddress. Similarlu, if ShippingAddress is null, you cannot access CompanyName. If CompanyName is null, you cannot call ToString().

You have to at some point verify which object is null. I don't have confidence that any of them will not be null. Do you? Check. Step through your program and observe the object states.

If it does come down to properties like CompanyName being null, and if CompanyName is a string, omit the ToString() call.

BillingCompany = If(Order.ShippingAddress.CompanyName, "")

If CompanyName is not a string, you will simply have to compare it to Nothing before calling ToString() or accessing a property.

Solution 2

Take a look at this line:

CompanyName = Order.ShippingAddress.CompanyName

If the CompanyName property in Order.ShippingAddress.CompanyName is Nothing, that code is still perfectly legal and will not trigger a NullReferenceException. The exception is triggered because either Order.ShippingAddress or Order itself is Nothing. You get the exception because you're trying to look for a specific property on an object that doesn't exist. Based on your code sample it's easy to see why this might be the case:

Dim Order As OrderType

That line declares a variable, but it never actually gives that variable a value. Order is an object reference variable... that is not yet set to an instance of an object. Now it sounds like you may be omitting the code where an instance is set, but it's worth mentioning because if so, that's a very basic part of how this code is supposed to work and would make sense to include at least a stub for that in the sample.

Share:
18,121
Mike L.
Author by

Mike L.

Updated on June 23, 2022

Comments

  • Mike L.
    Mike L. almost 2 years

    This should be simple, but I am having problems. Using the eBay .Net library, sometimes certain fields in a response are Nothing and sometimes contain a value. When they are Nothing they could simple be represented as an empty string, but the developers chose to return them as Nothing so when I try to set a String to the value (when nothing is there) I get a NullReferenceException, see below

    Imports System
    Imports System.Configuration.ConfigurationManager
    Imports System.Globalization
    Imports System.Threading
    Imports System.Xml
    
    Imports eBay.Service.Core.Soap
    Imports eBay.Service.Core.Sdk
    Imports eBay.Service.Call
    Imports eBay.Service.Util
    
    Public Class eBayOrderImportService
    Private Sub ServiceWorkerThread(ByVal state As Object)
        ' Periodically check if the service is stopping.
        Do While Not Me.stopping
            ' Perform main service function here...
            GetLastTime()
            Dim apiContext As ApiContext = GetApiContext()
    
            Dim apiCall As GetOrdersCall = New GetOrdersCall(apiContext)
            Dim orders As New OrderTypeCollection
    
            Dim timeFilter As New TimeFilter
            timeFilter.TimeFrom = lastUpdate
            timeFilter.TimeTo = Date.Now
    
    
            Dim lastTime As Boolean = SetLastTime()
            apiCall.IncludeFinalValueFee = True
            orders = apiCall.GetOrders(timeFilter, TradingRoleCodeType.Seller, OrderStatusCodeType.Completed)
    
            Dim order As OrderType
    
            For Each order In orders
                'do order-wide stuff here
                LogOrder(order)
    
            Next
            Thread.Sleep(30 * 1000)  ' Simulate some lengthy operations.
    
        Loop
    
        ' Signal the stopped event.
        Me.stoppedEvent.Set()
    End Sub
    
    Private Sub LogOrder(ByVal Order As OrderType)
    
        Dim OrderID, AccountID, BillingFirstName, BillingLastName, _
            BillingCompany, BillingEmailAddress, BillingPhone, _
            BillingAddress1, BillingAddress2, BillingCity, _
            BillingStateProvidence, BillingPostalCode, _
            BillingCountry, ShippingFirstName, ShippingLastName, _
            ShippingCompany, ShippingEmailAddress, ShippingPhone, _
            ShippingAddress1, ShippingAddress2, ShippingCity, _
            ShippingStateProvidence, ShippingPostalCode, _
            ShippingCountry, OrderStatus, BillingStatus, _
            OrderDate, ShippingMethod, SalesTax, _
            PreShippingCharge, OrderDiscount, OrderTotalCharged, _
            PaymentMethod, RepeatOrder, GiftCode, CouponCode, RID, _
            OrderNotes, OrderChannel, IsPrinted, IsShipped, PrintDate, _
            ShipDate, ActualShipCharge, DaysInTransit, DeliveryDate, _
            TrackingNumber, ShippedMethod As String
    
    
        OrderID = Order.OrderID
    
        AccountID = ""
    
        Dim name As String = If(Order.ShippingAddress.Name.ToString(), "None Given")
    
        BillingFirstName = name.Substring(0, name.IndexOf(" "))
        BillingLastName = name.Substring(name.IndexOf(" ") + 1)
        BillingCompany = If(Order.ShippingAddress.CompanyName.ToString(), "")
        BillingEmailAddress = If(Order.TransactionArray(0).Buyer.Email.ToString(), "")
        BillingPhone = If(Order.ShippingAddress.Phone.ToString(), "")
        BillingAddress1 = If(Order.ShippingAddress.Street1.ToString(), "")
        BillingAddress2 = If(Order.ShippingAddress.Street2.ToString(), "")
        BillingCity = If(Order.ShippingAddress.CityName.ToString(), "")
        BillingStateProvidence = If(Order.ShippingAddress.StateOrProvince.ToString(), "")
        BillingPostalCode = If(Order.ShippingAddress.PostalCode.ToString(), "")
        BillingCountry = If(Order.ShippingAddress.CountryName.ToString(), "")
        ShippingFirstName = If(BillingFirstName, "")
        ShippingLastName = If(BillingLastName, "")
        ShippingCompany = If(Order.ShippingAddress.CompanyName.ToString(), "")
        ShippingEmailAddress = If(Order.TransactionArray(0).Buyer.Email.ToString(), "")
        ShippingPhone = If(Order.ShippingAddress.Phone.ToString(), "")
        ShippingAddress1 = If(Order.ShippingAddress.Street1.ToString(), "")
        ShippingAddress2 = If(Order.ShippingAddress.Street2.ToString(), "")
        ShippingCity = If(Order.ShippingAddress.CityName.ToString(), "")
        ShippingStateProvidence = If(Order.ShippingAddress.StateOrProvince.ToString(), "")
        ShippingPostalCode = If(Order.ShippingAddress.PostalCode.ToString(), "")
        ShippingCountry = If(Order.ShippingAddress.CountryName.ToString(), "")
        OrderStatus = If(Order.OrderStatus.ToString(), "")
        BillingStatus = If(Order.OrderStatus.ToString(), "")
        OrderDate = If(Order.CreatedTime.ToString("MM/DD/yyyy"), "")
        If Order.TransactionArray(0).Taxes IsNot Nothing Then
            Dim tmpTax As Double = 0.0
            Dim tmpTrans As TransactionType
            For Each tmpTrans In Order.TransactionArray
                tmpTax = tmpTax + tmpTrans.Taxes.TotalTaxAmount.Value
            Next
            SalesTax = tmpTax.ToString()
    
        Else
            SalesTax = "0.0"
        End If
    
    
        ShippingMethod = If(Order.ShippingServiceSelected.ShippingService.ToString(), "")
        ShippingMethod = ShippingMethod & ":" & If(Order.ShippingServiceSelected.ShippingServicePriority.ToString(), "")
    
        OrderTotalCharged = If(Order.Total.Value.ToString(), "")
        OrderChannel = "eBay"
        comm = New OdbcCommand
        comm.CommandText = _
               "INSERT INTO Orders (OrderID, AccountID, BillingFirstName, BillingLastName, " & _
               "BillingCompany, BillingEmailAddress, BillingPhone, BillingAddress1, " & _
               "BillingAddress2, BillingCity, BillingStateProvidence, BillingPostalCode, " & _
               "BillingCountry, ShippingFirstName, ShippingLastName, ShippingCompany, " & _
               "ShippingEmailAddress, ShippingPhone, ShippingAddress1, ShippingAddress2, " & _
               "ShippingCity, ShippingStateProvidence, ShippingPostalCode, ShippingCountry, " & _
               "OrderStatus, BillingStatus, OrderDate, SalesTax, ShippingMethod, OrderTotalCharged, OrderChannel) " & _
               "VALUES('" & OrderID & "', '" & AccountID & "', '" & BillingFirstName & "', '" & _
               BillingLastName & "', '" & BillingCompany & "', '" & BillingEmailAddress & "', '" & _
               BillingPhone & "', '" & BillingAddress1 & "', '" & BillingAddress2 & "', '" & BillingCity & "', '" & _
               BillingStateProvidence & "', '" & BillingPostalCode & "', '" & BillingCountry & "', '" & _
               ShippingFirstName & "', '" & ShippingLastName & "', '" & ShippingCompany & "', '" & _
               ShippingEmailAddress & "', '" & ShippingPhone & "', '" & ShippingAddress1 & "', '" & _
               ShippingAddress2 & "', '" & ShippingCity & "', '" & ShippingStateProvidence & "', '" & _
               ShippingPostalCode & "', '" & ShippingCountry & "', '" & OrderStatus & "', '" & _
               BillingStatus & "', '" & OrderDate & "', '" & SalesTax & "', '" & ShippingMethod & "', '" & _
               OrderTotalCharged & "', '" & OrderChannel & "')"
        ' Dim orderResult As Integer = comm.ExecuteNonQuery()
        sysLog.WriteEntry(comm.CommandText)
    End Sub
    End Class
    

    There is updated code please note no exception is thrown until: BillingCompany = If(Order.ShippingAddress.CompanyName.ToString(), "") is executed. The Name property has a value which successfully stored into its variable, while Order.ShippingAddress.CompanyName is set to Nothing (this property does exist, and can sometimes have a value). I updated the code to include Anthony Pegram's answer which did not help.

    Everything is declared properly, to shorten the code I just showed a relevant example. Consider this inside of a loop for each order returned from a GetOrders() call, sometimes the Order.ShippingAddress.CompanyName will be nothing, at these times is it possible to handle it as an empty string? I tried the ToString() method. In other languages I could $CompanyName = this || that;

    Anything similar in VB .Net?

  • Mike L.
    Mike L. over 12 years
    I updated the code, please see the For/Next loop which ?should? be setting the value of Order as it iterates, and this Order is passed to another sub routine to actually process it. Properties that are not set to nothing have no problem.
  • Anthony Pegram
    Anthony Pegram over 12 years
    @MikeL, you have completely changed the code in the question. That generally makes the answers you have already received not useful. Generally speaking, don't do that. Start a new question if you have to.
  • Anthony Pegram
    Anthony Pegram over 12 years
    That being said, it still looks like you need to heed the advice of the answers. Either Order or Order.ShippingAddress could be null. Other objects could be null. Or it could indeed be the string properties that are null, and you are calling ToString() on them, getting the exception. This completely nullifies the safety of If(a, b). If a is null, If(a.ToString(), b) will throw. You haven't highlighted where the error is occuring, so we're left to guess. Have you stepped through the code?
  • Anthony Pegram
    Anthony Pegram over 12 years
    Please, put a breakpoint where the NRE is happening. Examing all of the object references on that line. See which one is null, and add appropriate null checks. Continue stepping through the code until you have verified that anything that could possibly be null is accounted for. And don't call methods or properties on null references.
  • Andrew Morton
    Andrew Morton over 2 years
    Please make sure that VB.NET code you post on Stack Overflow compiles with Option Strict On. Also, you should explain the code and, in this case, explain what you're adding that the previous answer did not.
  • cursorrux
    cursorrux over 2 years
    Please add further details to expand on your answer, such as working code or documentation citations.
  • Suhaib Janjua
    Suhaib Janjua over 2 years
    This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker.