Click here to Skip to main content
15,867,921 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,
I've written an API in c# that updates a SQL table. The API passes JSON to the code. If I run the API through Postman the code works correctly and updated the SQL table, but if I run through a CURL command I get the "Object reference not set to an instance of an object." error message.

In trying to work out what is going on I see that the values in the model don't appear to be populating when ran via CURL.

It's probably something simple, I'd appreciate if someone could point me in the right direction.

What I have tried:

My model...

    public class Balance
    {
        public string customer { get; set; }
        public string amount { get; set; }
        public string type { get; set; }
}
    public class CreateUpdate : Balance
    {
    }


and the PUT section of the API that works if I run through Postman...

// PUT api/<controller>/5
        public string Put([FromBody]CreateUpdate value)
        {
            _conPU = new SqlConnection(ConfigurationManager.ConnectionStrings["TestConnection"].ConnectionString);


            var query = "insert into L_UPD (ACUID, AMNT, DATE ,COMMENTS) " +
                "values (@ACUID, CASE WHEN @TYPE = 'debit' THEN @POINTS * -1 ELSE @POINTS END, getdate() , CASE WHEN @TYPE = 'debit' THEN 'REDEEM : ONLINE' ELSE 'EARN : ONLINE' END)";
            SqlCommand insertcommand = new SqlCommand(query, _conPU);
            insertcommand.Parameters.AddWithValue("@ACUID", value.customer);
            insertcommand.Parameters.AddWithValue("@POINTS", value.amount);
            insertcommand.Parameters.AddWithValue("@TYPE", value.type);
            _conPU.Open();
            int result = insertcommand.ExecuteNonQuery();
            if (result > 0)
            {
                return "approved";
            }
            else
            {
                return "update failed";
            }
        }


The CURL request is
curl -X PUT -H "Content-Type: application/json" -d '{"customer":"435673","amount":5,"type":"debit"}' http://localhost:55634/api/balance


EDIT :
Through postman if I try just the json, eg
{"customer":"435673","amount":5,"type":"debit"}

the code works, but in postman if I use curl
curl -X PUT -H "Content-Type: application/json" -d '{"customer":"435673","amount":5,"type":"debit"}'http://localhost:55634/api/balance

it doesn't work.
Posted
Updated 17-Aug-20 4:14am
v4
Comments
F-ES Sitecore 13-Aug-20 11:11am    
You can get postman to generate the curl command for you by clicking on the "code" link and selecting cURL from the options. Does that work? If so alter it by removing things that don't appear in yours until it stops working and whatever you removed last will probably let you know what the issue was.
Bullgill Coder 13-Aug-20 11:26am    
I have generated the curl command and tried the request above in postman and get the same error for both. The problem is that my code - when using curl, doesn't appear to pass the JSON into the model.
F-ES Sitecore 13-Aug-20 12:19pm    
Something to give a try is using HttpRequestMessage instead of FromBody

https://stackoverflow.com/questions/39030314/webapi-frombody-always-null

see if that's at least seeing your json as a string, if it is you can just deserialise that string yourself to your CreateUpdate class.
Bullgill Coder 14-Aug-20 5:43am    
When I change to HttpRequestMessage (if I'm doing that correctly) The value from (CreateUpdate value) is null when I use the curl command, but again when I just use JSON the value is correctly populated.
Sandeep Mewara 13-Aug-20 11:33am    
http://localhost:55634/api/balance => is this URL valid? Asking this based on PORT.

Is this accessible?

Further, believe your query here is more on why CURL is not working then Object reference error. You know that why you have that error (as response is not in desired format and you have not handled that bad response)

This is one of the most common problems we get asked, and it's also the one we are least equipped to answer, but you are most equipped to answer yourself.

Let me just explain what the error means: You have tried to use a variable, property, or a method return value but it contains null - which means that there is no instance of a class in the variable.
It's a bit like a pocket: you have a pocket in your shirt, which you use to hold a pen. If you reach into the pocket and find there isn't a pen there, you can't sign your name on a piece of paper - and you will get very funny looks if you try! The empty pocket is giving you a null value (no pen here!) so you can't do anything that you would normally do once you retrieved your pen. Why is it empty? That's the question - it may be that you forgot to pick up your pen when you left the house this morning, or possibly you left the pen in the pocket of yesterdays shirt when you took it off last night.

We can't tell, because we weren't there, and even more importantly, we can't even see your shirt, much less what is in the pocket!

Back to computers, and you have done the same thing, somehow - and we can't see your code, much less run it and find out what contains null when it shouldn't.
But you can - and Visual Studio will help you here. Run your program in the debugger and when it fails, VS will show you the line it found the problem on. You can then start looking at the various parts of it to see what value is null and start looking back through your code to find out why. So put a breakpoint at the beginning of the method containing the error line, and run your program from the start again. This time, VS will stop before the error, and let you examine what is going on by stepping through the code looking at your values.

But we can't do that - we don't have your code, we don't know how to use it if we did have it, we don't have your data. So try it - and see how much information you can find out!
I'd start by looking at what ConfigurationManager.ConnectionStrings["TestConnection"] returns. If that's null you will get the error immediately.
 
Share this answer
 
Comments
Bullgill Coder 14-Aug-20 5:50am    
As explained, I know there is a pen in my shirt pocket as when I just submit the json from the curl command everything works correctly and my data datatable is populated. The problem seems to be if I wrap the json within a curl command then I can't find the pen in the pocket, even though I know it's still there!
From my code (above) the problem is with
public string Put([FromBody]CreateUpdate value)
when using json only value is populated, when within curl it is not.
Well, the first thing I see with your controller is that it assumes the "value" passed into the method is not null and contains valid data. You do no validation of the "value" at all.

...and this leads to the error you're getting. In Postman, it's providing the data, and formatted correctly in json, to the API method. Your CURL command is making the same call but isn't supplying the data correctly, therefor, the call fails.
 
Share this answer
 
Comments
Bullgill Coder 14-Aug-20 5:45am    
I'm planning to add the validation once I have everything working. Stepping through the code shows me that the "value" class isn't getting populated by curl but is by json.
Dave Kreskowiak 14-Aug-20 10:04am    
That was a bad idea. No you have to add the validation code and start testing all over again, and add more testing for edge cases.

You didn't save yourself any time, you doubled it. Adding the validation would have told you there is a problem with the parameters being passed in and focused your troubleshooting effort on the test tool and not your code.
I've managed to get things working by changing my code to a HttpRequestMessage
[HttpPut]
public void Confirmation(HttpRequestMessage request)
{
    var content = request.Content;
    _conPU = new SqlConnection(ConfigurationManager.ConnectionStrings["Test_Connection"].ConnectionString);
    string jsonContent = content.ReadAsStringAsync().Result;
    jsonContent = jsonContent.Replace("'{", "{'").Replace(":", "':'").Replace(",", "','").Replace("}'", "'}");
    CreateUpdate cpu = JsonConvert.DeserializeObject<CreatePointsUpdate>(jsonContent);

     var query = "insert into L_UPD (ACUID, AMNT, DATE ,COMMENTS) " +
        "values (@ACUID, CASE WHEN @TYPE = 'debit' THEN @POINTS * -1 ELSE @POINTS END, getdate() , CASE WHEN @TYPE = 'debit' THEN 'REDEEM : ONLINE' ELSE 'EARN : ONLINE' END)";

     SqlCommand insertcommand = new SqlCommand(query, _conPU);
     insertcommand.Parameters.AddWithValue("@ACUID", cpu.customer_urn, null);
     insertcommand.Parameters.AddWithValue("@POINTS", cpu.amount, null);
     insertcommand.Parameters.AddWithValue("@TYPE", cpu.type, null);
     _conPU.Open();

     int result = insertcommand.ExecuteNonQuery();

    return;
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900