Object Reference Not Set To An Instance Of An Object: Yelp Return Values

PKD picture PKD · Mar 3, 2014 · Viewed 8.5k times · Source

I'm making a call to Yelp, to get reviews for some addresses in an apartment finder I've written, but it looks like some of the Yelp data isn't complete, so the following code results in Ye Olde ORNSTAIOAN error:

    public IEnumerable<Review> GetReviews(Bounds searchBounds) {
        var yelp = new Y.Yelp(ConfigOptions);
        var searchOptions = GetSearchOptions(searchBounds);
        var searchTask = yelp.Search(searchOptions);
        var tasks = new Task<Y.Data.SearchResults>[GetTaskArraySize(searchTask)];

        tasks[0] = searchTask;

        for (var i = 1; i < tasks.Length; i++) {
            searchOptions.GeneralOptions.offset = i * YelpResultsLimit;
            tasks[i] = yelp.Search(searchOptions);
        }

        Task.WaitAll(tasks);

        return tasks.SelectMany(t => t.Result.businesses != null
            ? t.Result.businesses
            : null)
                    .Select(MapYelpBusinessToReview);
    }

The error hits in the return line, on "businesses", even if I try a null catch, as I am above. The error outputs as:

<Error>
    <script id="tinyhippos-injected"/>
    <Message>
        An error has occurred.
    </Message>
    <ExceptionMessage>
        Object reference not set to an instance of an object.
    </ExceptionMessage>
    <ExceptionType>
        System.NullReferenceException
    </ExceptionType>
    <StackTrace>
        at System.Linq.Enumerable.<SelectManyIterator>d__14`2.MoveNext() at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at ApartmentFinder.Infrastructure.Services.SearchEngine.<>c__DisplayClassc.<FindProperties>b__1() in c:\Development\myProject\ApartmentFinder.Infrastructure\Services\SearchEngine.cs:line 25 at System.Threading.Tasks.Task`1.InnerInvoke() at System.Threading.Tasks.Task.Execute()
    </StackTrace>
</Error>

How can I trap the missing business information, and proceed with/without it?

Update:

YelpSharp.Data.Business

namespace ApartmentFinder.Infrastructure.Models {
    /// <summary>
    /// Provides the set of properties describing a review for a property.
    /// </summary>
    public class Review {
        public string Id{ get; set; }
        public string Name{ get; set; }
        public string Address{ get; set; }
        public string City{ get; set; }
        public string State{ get; set; }
        public string ZipCode{ get; set; }
        public string PhoneNumber{ get; set; }
        public string RatingImageUrl{ get; set; }
        public int NumberOfReviews{ get; set; }
        public string Snippet{ get; set; }
        public string Url{ get; set; }
        public double Latitude{ get; set; }
        public double Longitude{ get; set; }
    }
}

Adding in the method for Review MapYelpBusinessToReview:

    /// <summary>
    /// Maps a <see cref="Y.Data.Business"/> instance to a new <see cref="Review"/>.
    /// </summary>
    /// <param name="business">Business object to map.</param>
    /// <returns>A new <see cref="Review"/> instance.</returns>
    static Review MapYelpBusinessToReview(Y.Data.Business business) {
        return new Review {
            Id = business.id,
            Name = business.name,
            Address = business.location.address[0],
            City = business.location.city,
            State = business.location.state_code,
            ZipCode = business.location.postal_code,
            PhoneNumber = business.phone,
            RatingImageUrl = business.rating_img_url,
            Snippet = business.snippet_text,
            Url = business.url,
            NumberOfReviews = business.review_count,

        };
    }

Answer

JaredPar picture JaredPar · Mar 3, 2014

The problem is that in the SelectMany call you end up returning a null value instead of an empty collection to. In the case you want no values added you must return an empty collection else SelectMany will null ref

Try the following

return tasks
  .SelectMany(t => t.Result.businesses ?? new List<Business>())
  .Select(MapYelpBusinessToReview);