C# API Call: Null Exception at foreach loop [duplicate] - c#

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 3 years ago.
I'm trying to map API JSON data into some properties of a class, and I'm getting the error below. I was able to narrow down the data entry causing this issue.
[The value for PositionDateStart]
The script successfully creates an object off the properties, but once I call the object to test it using a foreach loop, it crashes and gives me this error.
My question is what could I write to tell the script to replace null with today's date if this comes up.
Thanks in advance!
Error Message:
NullReferenceException: Object reference not set to an instance of an object.
JSON Results #Console.WriteLine(json)
[
{
"EntryID": 41992,
"Position": "Associate",
"PositionDateEnd": "2020-05-15T00:00:00",
"PositionDateStart": null
}
]
Script
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json); //JSON results above
var result = JsonConvert.DeserializeObject<List<Properties>>(json);
//Point at which code errors outs
foreach (var item in result)
{
Console.WriteLine(item.PositionDateStart);
Console.WriteLine(item.PositionDateStart.GetType());
}
Class Properties
public class Properties
{
public int EntryID { get; set; }
public string Position { get; set; }
public DateTime? PositionDateEnd { get; set; }
public DateTime? PositionDateStart { get; set; }
}

You can simply assign current date if PositionDateStart is null then output to console anyway without errors since it will never be empty:
//Point at which code errors outs
foreach (var item in result)
{
if (item.PositionDateStart == null)
item.PositionDateStart = DateTime.Now;
Console.WriteLine(item.PositionDateStart);
Console.WriteLine(item.PositionDateStart.GetType());
}
EDIT
As asked in comment, if you prefere to modify the class itself here is a variant through the get accessor so your foreach remains the same:
public class Properties
{
public int EntryID { get; set; }
public string Position { get; set; }
public DateTime? PositionDateEnd { get; set; }
private DateTime? _positionDateStart;
public DateTime? PositionDateStart
{
get { return _positionDateStart == null ? DateTime.Now : _positionDateStart; }
set { _positionDateStart = value; }
}
}

Try (not tested):
Console.WriteLine(item?.PositionDateStart ?? DateTime.Now);
The null condional and null coalese operators are explained here

try the following code:
foreach (var item in result)
{
if(item.PositionStartDate == null)
{
item.PositionDateStart = DateTime.Now;
}
Console.WriteLine(item.PositionDateStart.GetType());
}

Related

C# linq DefaultIfEmpty() NullReferenceException Value cannot be empty. Parameter name: Source [duplicate]

This question already has answers here:
Value cannot be null. Parameter name: source
(20 answers)
Closed 2 years ago.
I have a problem
How can I inquire in a linq correctly
Get a mistake NullReferenceException every time
public class Model
{
public int Nmb { get; set; }
public string _UserId { get; set; }
}
public static List<Model> _models_List { get; set; }
string user = "test name";
int test = _models_List.Where(o => o._UserId == user).Select(o => o.Nmb).DefaultIfEmpty(0).First();
if (test == 0)
{
Model obj = new Model();
obj._UserId = user;
obj.Nmb = 1;
_models_List.Add(obj);
}
I tried to correct the code like this
But I get the same mistake
NullReferenceException
Value cannot be empty. Parameter name: Source
int test = _models_List.Where(o => o._UserId == user).Select(o => o.Nmb).FirstOrDefault();
Please Help
The list _models_List is empty, to solve the issue replace the following code:
public static List<Model> _models_List { get; set; }
with:
public static List<Model> _models_List { get; set; } = new List<Model>();

Read a JSON property with NULL handling using JSON.Net

I have a JSON structure like below to show the details of a specific candidate
It can be either null or can contain some details like below
"details": {
"gender": {
"id": 3,
"props": {
"name": "male"
}
}
}
or as null
"details": {
"gender": null
}
To read the value of gender i tried
string _gender = (string)result["details"]["gender"]["props"]["name"];
This will works in non null cases . But if its null then this code returns an exception
So to check first is it null or not and if not null try to read the value, i tried below code
string _gender = (string)result["details"]["gender"];
if (!string.IsNullOrEmpty(_gender))
{
_gender = (string)result["details"]["gender"]["props"]["name"];
}
But i am getting the exception that not possible to convert object to string. So how to read a JSON property with proper null handling \
I strongly suggest you to deserialize the json as known type.
public class Props
{
public string name { get; set; }
}
public class Gender
{
public int id { get; set; }
public Props props { get; set; }
}
public class Details
{
public Gender gender { get; set; }
}
public class JsonObject
{
public Details details { get; set; }
}
Then perform deserialization;
var jsonObject = JsonConvert.DeserializeObject<List<JsonObject>>(json);
foreach (var o in jsonObject)
{
var genderName = o?.details?.gender?.props?.name;
}
In this way, you can handle the possible null values and get strongly typed object.
EDIT
Also, in your code, you are trying to convert an object to string and it is completely wrong. It seems that gender object is a complex type. So you can't convert it to string and you should modify your code like this;
object _gender = result["details"]["gender"];
if (_gender != null)
{
string genderName = result["details"]["gender"]["props"]["name"].ToString();
}
Keep in mind that jToken[xx..][yy..] is not a string, it is a JToken object, therefore we cannot explicitly cast it to string. If we want to convert it to string we'd have to call ToString() on it explicitly (which in terms calls JToken's overridden implementation of .ToString).
First we need to check that Jtoken has values for that we have method .HasValues.
Later when we know for certain that there is a string in ["name"]
property we can use either - explicit cast or .ToString() again
string _gender;
var genderToken = jToken["details"]["gender"];
if (genderToken.HasValues)
{
_gender = genderToken["props"]["name"].ToString();
}

C# How to initialize an object containing a list<T> with standard values

This question is related to this question. I managed to get one step further, but I am now unable to initialize my whole object with default values in order to prevent it from being null at list level. The goal of this is to hand down the "null" values to my SQL query. Ultimately what I want is one record in my DB that will express: This row has been recorded, but the related values were "null".
I have tried Brian's fiddle and it does not seem to work for me to initialize the whole model with standard values.
Expectation: Upon object initialisation the "null" values should be used and then overwritten in case there is a value coming through JSON deserialisation.
Here is what I have tried. None of this will have the desired effect. I receive this error:
Application_Error: System.ArgumentNullException: Value cannot be null.
Every time I try to access one of the lists in the data model.
namespace Project.MyJob
{
public class JsonModel
{
public JsonModel()
{
Type_X type_x = new Type_X(); // This works fine.
List<Actions> action = new List<Actions>(); // This is never visible
/*in my object either before I initialise JObject or after. So whatever
gets initialised here never makes it to my object. Only Type_X appears
to be working as expected. */
action.Add(new Actions {number = "null", time = "null", station =
"null", unitState = "null"}) // This also does not prevent my
//JsonModel object from being null.
}
public string objectNumber { get; set; }
public string objectFamily { get; set; }
public string objectOrder { get; set; }
public string location { get; set; }
public string place { get; set; }
public string inventionTime { get; set; }
public string lastUpdate { get; set; }
public string condition { get; set; }
public Type_X Type_X { get; set; }
public List<Actions> actions { get; set; }
}
public class Actions
{
public Actions()
{
// None of this seems to play a role at inititialisation.
count = "null";
datetime = "null";
place = "null";
status = "null";
}
// public string count { get; set; } = "null"; should be the same as above
// but also does not do anything.
public string count { get; set; }
public string datetime { get; set; }
public string place { get; set; }
public string status { get; set; }
}
public class Type_X
{
public Type_X
{
partA = "null"; // This works.
}
public string partA { get; set; }
public string PartB { get; set; }
public string partC { get; set; }
public string partD { get; set; }
public string partE { get; set; }
}
}
This is how I now initialize the object based on Brian's answer.
JObject = JsonConvert.DeserializeObject< JsonModel >(json.ToString(), new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore});
When I try to iterate over Actions' content, it (logically) gives me above mentioned null error.
for (int i = 0, len = JObject.actions.Count(); i < len; i++)
My current understanding of constructor initialisations:
If I define values such as count = "null"; they should appear in any new object that is created.
If default values are present I would then also expect that a list that has items with default values (such as count for ex.) would be of Count() 1 and not null. How is that even possible?
This will get you out of your bind:
private List<Actions> _actions = new List<Actions>();
public List<Actions> actions { get => _actions; set => _actions = value ?? _actions; }
This causes trying to set actions to null to set it to the previous value, and it is initially not null so it can never be null.
I'm not absolutely sure I'm reading your question right, so here's the same fragment for partA:
private string _partA = "null";
public string partA { get => _partA; set => _partA = value ?? _partA; }
I have found that in some cases, initializing generic lists with their default constructor on your model increases ease of use. Otherwise you will always want to validate they are not null before applying any logic(even something as simple as checking list length). Especially if the entity is being hydrated outside of user code, i.e. database, webapi, etc...
One option is to break up your initialization into two parts. Part 1 being the basic initialization via default constructor, and part 2 being the rest of your hydration logic:
JObject = new List < YourModel >();
... < deserialization code here >
Alternatively you could do this in your deserialization code, but it would add a bit of complexity. Following this approach will allow you to clean up your code in other areas since each access will not need to be immediately proceeded by a null check.

Filling POCO Object with List inside a List [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
I´m attempting to fill a POCO object but I get the NullReferenceException - Object reference not set to an instance of an object, at line "objectAreas.position.Add(objectPositions);" I think I'm not initializing well but I don't see my mistake, let's see the code:
POCO OBJECT
public class GenericQuery
{
public sealed class Areas
{
public int idarea { get; set; }
public string areaname { get; set; }
public List<Positions> positions { get; set; }
}
public sealed class Positions
{
public int idposition { get; set; }
public string positionname { get; set; }
}
public sealed class QueryAreasPositions
{
public int code { get; set; }
public string response { get; set; }
public List<Areas> areas { get; set; }
}
}
Filling It
GenericQuery.QueryAreasPositions objectAreasPositions = new GenericQuery.QueryAreasPositions();
var query = areaRepository.Get(); //Eager Loading EntityFramework List Object, see the AreaRepository at the end
objectAreasPositions.code = 123;
objectAreasPositions.response = "anything";
foreach (var area in query)
{
GenericQuery.Areas objectAreas = new GenericQuery.Areas();
objectAreas.idarea = area.IdArea;
objectAreas.areaname = area.Name;
foreach (var position in area.Position)
{
GenericQuery.Positions objectPositions = new GenericQuery.Positions();
objectPositions.idposition = position.IdPosition;
objectPositions.positionname = position.Name;
***objectAreas.position.Add(objectPositions);***//HERE
}
objectAreasPositions.areas.Add(objectAreas); //And maybe here
}
AreaRepository
public List<Area> Get()
{
using (var context = new Entities())
{
return context.Area.Include("Position").ToList();
}
}
I would appreciate any help/guide you can give me, Thanks.
You are never initializing objectAreas.position, hence the default value for a List<T> is null.
Since you are trying to call the Add method on a null reference, you are getting a NullReferenceException.
To fix this, you should initialize the property before using it:
objectAreas.position = new List<GenericQuery.Positions>();
Alternatively, you can add this logic on GenericQuery.Areas constructor, which would be more appropriate:
public sealed class Areas
{
public int idarea { get; set; }
public string areaname { get; set; }
public List<Positions> positions { get; set; }
public class Areas()
{
positions = new List<Positions>();
}
}
Shouldn't you rather be doing like below. Your position is null cause not yet initialized and thus the said exception.
objectAreas.position = new List<Position>();
objectAreas.position.Add(objectPositions);

why null reference exception in List<decimal> [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 7 years ago.
i have a problem, i created an object in C# like this:
public class logis
{
public string codigo { get; set; }
public List<decimal> Necesidades { get; set; }
decimal SumaNecesidades{get;set;}
}
then i do something like this:
logisva logi = new logis();
logi.codigo = oDataReader.GetValue(0).ToString();
logi.Necesidades.Add(0);
But when i execute my code i get a null reference exception error. Object reference not set to an instance of an object. on the last line logi.Necesidades.Add(0);
Any idea why i get this error?
In C# the properties do not initialize/create the List<ofType> object automatically. You need to create the list explicitely:
public class logis
{
public string codigo { get; set; }
public List<decimal> Necesidades { get; set; }
decimal SumaNecesidades{get;set;}
public logis()
{
this.Necesidades = new List<decimal>();
}
}
Another option is to create the list in the getter resp. setter (so to say your own lazy initialization, downside - introduces more code, advantage no need to override every contructor):
public class logis
{
public string codigo { get; set; }
decimal SumaNecesidades{get;set;}
private List<decimal> necesidades = null;
private void initNecesidades()
{
if (this.necesidades == null)
{
this.necesidades = new List<decimal>();
}
}
public List<decimal> Necesidades
{
get
{
this.initNecesidades();
return this.necesidades;
}
set
{
this.initNecesidades();
this.necesidades = value;
}
}
}
Yet another option would be to use the new C# 6.0 features (if it is an option to use/already using the latest .NET Framework version) as already suggested in the comments by #Jcl:
public List<decimal> Necesidades { get; set; } = new List<decimal>()

Categories

Resources