-2

I'm new to C# and a bit baffled by this, mainly because everything has worked perfectly with this web app for the last several months, and this issue just started, seemingly with no changes having been made to the code in months. I've read several posts here related to this error, but all of the answers are a little general for my knowledge-level.

The error that is thrown is:

An exception of type 'System.ArgumentNullException' occurred in System.Core.dll but was not handled in user code

Additional information: Value cannot be null.

The code is:

[Route("ajax/addOrUpdateSource")]
[HttpPost]
public JsonResult AddOrUpdateSource(Source source, string html)
{
    var htmlDoc = new HtmlAgilityPack.HtmlDocument();
    htmlDoc.LoadHtml(html);

    var response = new Dictionary<string, object>();
    var labels = htmlDoc.DocumentNode.SelectNodes("//label");
    List<string> categories = new List<string>();
    string[] vals = new string[] { };

     for(int n = 1; n < labels.Count(); n++)
    {
        var label = labels[n].Attributes[0].Value;

        if (label.Contains( "btn") && label.Contains("btn-primary"))
            categories.Add(labels[n].InnerText.Trim());
    }

    response.Add("source", null);

    try
    {
        string catValues = String.Join(", ", categories.ToArray());

        source.LastUpdateDateTime = DateTimeOffset.UtcNow;
        source.LastUpdateUser = User.Identity.Name;
        source.ProductCategory = catValues;

        // save the source
        var updatedSource = _taskService.AddOrUpdateSource(source);

        // prepare the response
        response["source"] = updatedSource;
    }
    catch(Exception exc)
    {
        response.Add("error", exc.Message);
    }

    return Json(response);

See the screenshot below to see exactly where Visual Studio attaches the error to during debug. (the line containing "n < label.Count()")

How can I fix this? I don't expect I'll be able to figure out why everything was ok, and suddenly this started happening, but if I can fix it, I'll be able to move forward.

enter image description here

Updates

EDIT 1 - after all of the very helpful input below, it has become clear that what I truly need to figure out is why the app is suddenly reporting NULL for the label nodes. I am able to prevent the error from being thrown now, but before this phantom change took place, the label nodes were never NULL, and the execution accomplished what it was designed to.

EDIT 2 - per guidance from @mjwills here is the code for the function that sends the data:

$scope.performSaveSource = function () {
        GlobalService.togglePleaseWait(true);

        $scope.source.SourceStatusId = $scope.source.SelectedSourceStatus.SourceStatusId;
        $scope.source.SourceStatus = $scope.source.SelectedSourceStatus.SourceStatusId;
        $scope.source.DataTypeId = $scope.source.SelectedDataType.DataTypeId;

        // pass the source and activity to be saved
        $http({
            url: "/ajax/addorupdatesource",
            method: "POST",
            data: {
                source: $scope.source,
                html: $('html').context.all["143"].innerHTML
            }
        })
        .then(function (response) {
            GlobalService.togglePleaseWait(false);

            if (response.status == 200) {
                if (response.data.error != null) {
                    alert(response.data.error);
                    return;
                }

                // update our local copies
                $scope.setSource(response.data.source);
            }
        });
    };
halfer
  • 19,824
  • 17
  • 99
  • 186
Stpete111
  • 3,109
  • 4
  • 34
  • 74
  • 1
    well its telling you that labels in null. Seems like you dont have the right nodes in the HTML. Did somebody change it? You should test for null after the SelectNodes call anyway – pm100 Jun 22 '17 at 20:38
  • 1
    Seems like a very clear error message, there are no matches on `SelectNodes("//label")` so you can't call `Count()`. – Igor Jun 22 '17 at 20:41
  • 1
    In addition to what the others have said, you may want to check for the existence of an instance before proceeding and fail gracefully. Since it is possible that `SelectNodes()` returns null, it is prudent to check for that using `if(labels == null) // fail gracefully` If you are on one of the newer versions of .NET, you can use `labels?.Count()` which will do the check for you and return not execute the loop if labels was null. – Fabulous Jun 22 '17 at 20:52
  • @pm100 unless someone's been in the code without my knowledge, no one has changed it. That's the strangest part. – Stpete111 Jun 22 '17 at 21:22
  • @Igor ok, that certainly makes sense. This is the path I'll go down to try and solve it. – Stpete111 Jun 22 '17 at 21:23
  • @Fabulous I'm on VS 2015 Community with .NET 4.5. Other than that, I wish I knew what you meant by "fail gracefully.:" I'm that much of a beginner. – Stpete111 Jun 22 '17 at 21:24
  • 2
    Change the line of code to `var labels = htmlDoc.DocumentNode.SelectNodes("//label") ?? Enumerable.Empty();` _This will ensure it returns an empty enumerable rather than null._ – mjwills Jun 22 '17 at 21:38
  • To fail gracefully refers to handling exception scenarios without having your application crash or display an error message. For instance, if a file you required was missing, it is better to display a message that the file is missing than to leave it like that and have your program crash out leaving your user confused. In this case, you can define a behavior for what happens when labels is null. You may also want to put a breakpoint at this line `var labels = htmlDoc.DocumentNode.SelectNodes("//label");` and inspect the `DocumentNode` property for what it contains. Label might be misspelt – Fabulous Jun 22 '17 at 21:38
  • Can you update your question with the contents of the `html` variable? – mjwills Jun 22 '17 at 21:39
  • @Stpete111 look at the comment from mjwills, that is an example of failing gracefully. If `SelectNodes` returns null, set labels to an empty list. When it gets to the for loop, it won't throw but will skip that part because there's nothing to loop through. – Fabulous Jun 22 '17 at 21:41
  • I've edited the post to point out that the true issue now, which I've discovered with all of your help, is not the error itself, but the fact that label nodes are suddenly being reported as NULL. This should not be the case at all, and is what I need to figure out. – Stpete111 Jun 22 '17 at 22:09
  • @mjwills which part of the source code should I post to address your request on posting the contents of the html variable? – Stpete111 Jun 22 '17 at 22:12
  • @Fabulous, I'm inspecting the DocumentNode property at the breakpoint on the line you've specified, but I have no idea what I'm looking for? – Stpete111 Jun 22 '17 at 22:34
  • You should find it's properties listed there, including one that shows it's children. It normally has "Expanding will enumerate the ...". If you expand that you will see everything it contains and should be able to see if it exists, and if you are spelling it correctly. – Fabulous Jun 22 '17 at 22:42
  • @Fabulous ok, I've looked and I see nothing even close to "label" in there. I guess this is what we would expect given the error, if not for it being misspelled? I'm truly confused. How did this suddenly stop working. – Stpete111 Jun 22 '17 at 22:48
  • In the Immediate window type in `?html` and share with us the results. https://msdn.microsoft.com/en-us/library/f177hahy.aspx – mjwills Jun 22 '17 at 23:01
  • @mjwills The result is simply "Word." – Stpete111 Jun 22 '17 at 23:06
  • 1
    Well there is your problem. :) You need to find out why `Word` is being sent to that method. – mjwills Jun 22 '17 at 23:24
  • Ok. I'm really lost here. I may need to pay someone to help me figure this out. – Stpete111 Jun 22 '17 at 23:27
  • 1
    To be 100% clear - the bug is **not** in the code you are showing us. It is in the caller - the thing that **sends** the data to `AddOrUpdateSource`. – mjwills Jun 22 '17 at 23:44
  • @mjwills - ok thanks for that. I've added that code to my main post as Edit #2. Let me know if this helps you help me any further. – Stpete111 Jun 22 '17 at 23:59
  • Helpful feedback: when editing posts to add new information, sometimes it can just be merged into the question as if you'd asked it like that first time around. However, if you think that would confuse existing readers, please add it at the end of your post - adding it at the start is really confusing for new readers who see the post in the future. – halfer Jun 26 '17 at 20:59
  • 1
    @halfer ok thanks for the tip – Stpete111 Jun 26 '17 at 21:03

1 Answers1

5

The code may not have changed, but perhaps the html document being loaded does not contain any nodes that match "//label"

thus labels is null, and calling Count on it will throw

Erix
  • 7,059
  • 2
  • 35
  • 61
  • Thanks Erix. While your answer definitely makes the most sense to me of all of them, there is definitely no absence of label nodes in the html document. – Stpete111 Jun 22 '17 at 21:20
  • You may find https://stackoverflow.com/questions/5801828/html-agility-pack-null-reference of use @Stpete111 – mjwills Jun 22 '17 at 21:45
  • @mjwills thanks for that link, it certainly is almost exactly what I'm experiencing. Changing the code similar to Alex's suggestions did in fact make the error stop being thrown. Unfortunately, I don't accomplish what I'm supposed to when executing AddorUpdateSource. So really what I need to figure out here is why it sees NULL for the label nodes. – Stpete111 Jun 22 '17 at 22:05
  • @Stpete111: is the casing correct? In other words is it spelled `label` as opposed to `Label` or `LABEL` in the html? – NotMe Jun 22 '17 at 22:34
  • @NotMe - yes as far as I can see. I am looking in the cshtml document that relates to this code. That's correct I assume. – Stpete111 Jun 22 '17 at 22:40