C# Nested Properties initialize - c#

I have the below simple declaration of nested properties (simplified):
public class standardMessage
{
public messageProperties message { get; set; }
public messageFlags flag { get; set; }
}
public class messageProperties
{
public string messageSubject { get; set; }
public string messageBody { get; set; }
}
public class messageFlags
{
public Boolean flagImportant { get; set; }
public Boolean flagPersonal { get; set; }
}
Upon initialization, I am trying to enter values, but seems I am missing something:
public class Program
{
static void Main(string[] args)
{
standardMessage myMessage = new standardMessage();
messageProperties myMsgProperties = new messageProperties();
myMsgProperties.messageSubject = "Hey!";
myMsgProperties.messageBody = "Howdy";
//below code throws error System.NullReferenceException: 'Object reference not set to an instance of an object.'
//MyMessage.message.messageSubject = "Greetings";
//MyMessage.message.messageBody = "Happy weekend";
//error - how do I print the values?
Console.WriteLine(myMessage.message.messageSubject.ToString());
Console.ReadLine();
}
}
Could you please help me with the above? wither way I tried, it doesn't run

You should initialize the instance of messageProperties first, before accessing the instance properties
myMessage.message = new messageProperties
{
messageBody = "Happy weekend",
messageSubject = "Greetings"
};
instead of this
//below code throws error System.NullReferenceException: 'Object reference not set to an instance of an object.'
//MyMessage.message.messageSubject = "Greetings";
//MyMessage.message.messageBody = "Happy weekend";
Then you'll be able to print it out successfully
Console.WriteLine(myMessage.message.messageSubject);
prints
Greetings
Another option is to initialize nested properties in constructor, like that
public class standardMessage
{
public standardMessage()
{
message = new messageProperties();
flag = new messageFlags();
}
public messageProperties message { get; set; }
public messageFlags flag { get; set; }
}
Then you can assign the values like you want
myMessage.message.messageSubject = "Greetings";
myMessage.message.messageBody = "Happy weekend";
Or you can finish you snippet and set the nested property directly
standardMessage myMessage = new standardMessage();
messageProperties myMsgProperties = new messageProperties();
myMsgProperties.messageSubject = "Hey!";
myMsgProperties.messageBody = "Howdy";
myMessage.message = myMsgProperties;
Console.WriteLine(myMessage.message?.messageSubject);
Prints
Hey!
Null-conditional operator ? will help you to avoid NullReferenceException if any

You need to modify the definition for your standardMessage class to either use inline initializers or add a default constructor (whichever works depending upon the language version you are using).
public class standardMessage
{
public standardMessage()
{
message = new messageProperties();
flag = new messageFlags();
}
public messageProperties message { get; set; } = new messageProperties();
public messageFlags flag { get; set; } = new messageFlags();
}

Related

List to JSON with JsonSerializer.Serializer returns null

I have a class named clsTest which is defined as:
public class clsTest
{
public string Name;
public string Family;
public int Age;
}
I have another class named clsMain which is Serializing three instances of clsTest class to JSON as:
public class clsMain
{
public string mtdMain()
{
clsTest ct1_a = new clsTest();
clsTest ct1_b = new clsTest();
clsTest ct1_c = new clsTest();
ct1_a.Name = "Satoshi";
ct1_a.Family = "Nakamato";
ct1_b.Name = "Charles";
ct1_b.Family = "Hoskinson";
ct1_b.Age = 33;
ct1_c.Name = "AmirAli";
ct1_c.Family = "Sam";
ct1_c.Age = 25;
List<clsTest> lst = new List<clsTest>();
lst.Add(ct1_a);
lst.Add(ct1_b);
lst.Add(ct1_c);
JsonSerializerOptions option = new JsonSerializerOptions();
option.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
option.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
return JsonSerializer.Serialize(lst, option);
}
}
When I debug the project my list is full as shown in the screenshot:
But at the end return JsonSerializer.Serialize(lst, option); serialize as below:
I couldn't find the problem, any suggestion will be appreciated.
Thanks.
Use properties instead of fields, like so:
public class Test
{
public string Name { get; set; }
public string Family { get; set; }
public int Age { get; set; }
}

Value cannot be null. Parameter name: source when Adding object to IEnumerable list

I am building a simple MVC application to perform CRUD applications. I have two simple model classes.
public class MoniModel
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
public class MoniGridModel
{
public IEnumerable<MoniModel> MoniDetails { get; set; }
}
In my controller, I am trying to do the following:
public ActionResult MoniDetails()
{
MoniModel mim = new MoniModel();
MoniGridModel migm = new MoniGridModel();
mim.CategoryId = 1;
mim.CategoryName = "a";
mim.ProductId = 1;
mim.ProductName = "b";
migm.MoniDetails.ToList().Add(mim);
return View(migm);
}
When migm.MoniDetails.ToList().Add(mim); is executed, it gives the mentioned error. I am not able to figure out why this is happening. I am assigning value to each member of mim object. below is the error detail, not sure if that will help, though.
You've never instantiated MoniDetails (it's value is null when you create the MoniGridModel):
public ActionResult MoniDetails()
{
MoniModel mim = new MoniModel();
MoniGridModel migm = new MoniGridModel();
mim.CategoryId = 1;
mim.CategoryName = "a";
mim.ProductId = 1;
mim.ProductName = "b";
var details = new List<MoniModel>();
details.Add(mim);
migm.MoniDetails = details;
return View(migm);
}
As #David's answer points out, it's probably best to let the MoniGridModel class handle the IEnumerable<MoniModel> instead though.
In addition to the options he presents, you could create a private member that backs the IEnumerable<MoniModel> and expose it through the getter you currently have:
public class MoniGridModel
{
private List<MoniModel> moniDetails;
public MoniGridModel()
{
this.moniDetails = new List<MoniModel>();
}
public IEnumerable<MoniModel> MoniDetails
{
get { return this.moniDetails; }
}
public void AddDetail(moniDetail detail)
{
this.moniDetails.Add(detail);
}
}
And then call AddDetail from your controller action:
public ActionResult MoniDetails()
{
MoniModel mim = new MoniModel();
MoniGridModel migm = new MoniGridModel();
mim.CategoryId = 1;
mim.CategoryName = "a";
mim.ProductId = 1;
mim.ProductName = "b";
migm.AddDetail(mim);
return View(migm);
}
MoniDetails is null because it was never instantiated. This should generally be done when constructing the object:
public class MoniGridModel
{
public IEnumerable<MoniModel> MoniDetails { get; set; }
public MoniGridModel()
{
MoniDetails = new List<MoniModel>();
}
}
That way consuming code doesn't need to worry about instantiating it. The responsibility of maintaining the state of the object belongs encapsulated within the object.
Additionally, this doesn't do what you think it does:
migm.MoniDetails.ToList().Add(mim);
ToList() returns an enumerated list of the IEnumerable<>. But you want to add to the enumerable itself. Given this use, you probably want the property to be an IList<> in the first place so it can support the Add() operation:
public class MoniGridModel
{
public IList<MoniModel> MoniDetails { get; set; }
public MoniGridModel()
{
MoniDetails = new List<MoniModel>();
}
}
Then you can add to it:
migm.MoniDetails.Add(mim);

Adding model object to list fails

I have a model class like this
namespace ConnectBLL.DTO.Response
{
public class CategorySettings
{
public bool NeedsLoginToViewLongText { get; set; }
public bool NeedsLoginToViewAnyDetails { get; set; }
public bool ShowAttachment { get; set; }
public string CategoryPageID { get; set; }
public string TpUrl { get; set; }
}
public class CategorySettingsListResponse
{
public List<CategorySettings> CategorySettingsList { get; set; }
}
}
And I am trying to add data to it like this
private readonly CategorySettings cs = new CategorySettings();
CategorySettingsListResponse csr=new CategorySettingsListResponse();
public string GetAllCategorySettings()
{
cs.NeedsLoginToViewLongText = true;
cs.NeedsLoginToViewAnyDetails = false;
cs.ShowAttachment = true;
cs.CategoryPageID = "1";
cs.TpUrl = "url";
csr.CategorySettingsList.Add(cs);
}
But this fails and gives an error
Object reference not set to an instance of an object.
Can any one point out what is I am doing wrong?
Somewhere, you need to initialize CategorySettingsList.
public class CategorySettingsListResponse
{
CategorySettingsListResponse() {
CategorySettingsList = new List<CategorySettings>();
}
public List<CategorySettings> CategorySettingsList { get; set; }
}
You are tying to use an instance of List before initializing. Before
csr.CategorySettingsList.Add(cs);
Insert:
if (csr.CategorySettingsList == null) {
csr.CategorySettingsList = new List<CategorySettings>();
}
You are using uncreated objects cs and CategorySettingsList, you should create them before use:
public string GetAllCategorySettings()
{
csr.CategorySettingsList = new ListCategorySettings<>();
var cs = new CategorySettings
{
NeedsLoginToViewLongText = true,
...
What is cs? Something missing?
You forgot to do this:
var cs = new CategorySettings();
Also
You need to instantiate the CategorySettingsList in constructor for CategorySettingsListResponse.

Parsing JSON into Object

Trying to get the result from a webservice call to return a Model. I eep getting the error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'CI.Models.Schedule' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
public Schedule getCourseSchedule()
{
var obj = new
{
States = new[] { new { State = "MX" } },
Zip = "",
Miles = "",
PaginationStart = 1,
PaginationLimit = 3
};
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "apoplication/json";
var url = "http://192.168.1.198:15014/ShoppingCart2/CourseSchedule";
var json = JsonConvert.SerializeObject(obj);
byte[] data = Encoding.UTF8.GetBytes(json);
byte[] result = client.UploadData(url, data);
string returnjson = Encoding.UTF8.GetString(result);
Schedule sched = JsonConvert.DeserializeObject<Schedule>(returnjson);
return sched;
}
}
Schedule Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;
namespace CI.Models
{
public class Schedule
{
public IEnumerable<Course> Courses { get; set; }
}
public class Course
{
/*
JSON Data returned from web service:
{
"ProgramGroup":"MR",
"ProgramCode":"RM",
"EventCode":"20160901MXMR",
"FormalDate":"September 1-2, 2016",
"StartDate":"2016\/09\/01",
"Price":5,
"LocName":"WB Hotel",
"LocAddress":"Av. Speedy Gonzales 220",
"LocCity":"Monterrey",
"LocState":"MX",
"LocZipCode":null,
"LicenseeURL":null,
"AgendaURL":"NA",
"SeatsAreAvailable":"2",
"GeneralInfoHTML":"General Info goes here.",
"GateKeeperHTML":null,
"EventType":"SS",
"TotalCourses":3
}
*/
public string ProgramGroup { get; set; }
public string ProgramCode { get; set; }
public string EventCode { get; set; }
public string FormalDate { get { return FormalDate; } set { FormalDate = convertFormalDateToSpanish(value); } }
public string StartDate { get; set; }
public double Price { get; set; }
public string LocName { get; set; }
public string LocAddress { get; set; }
public string LocCity { get ; set; }
public string LocState { get; set; }
public string LocZipCode { get; set; }
public string LicenseeURL { get; set; }
public string AgendaURL { get { return AgendaURL; } set { AgendaURL = buildAgendaLink(value); } }
public string SeatsAreAvailable { get; set; }
public string GeneralInfoHTML { get; set; }
public string GateKeeperHTML { get; set; }
public string EventType { get; set; }
public int TotalCourses { get; set; }
public string convertFormalDateToSpanish(string val)
{
DateTime TheDate = DateTime.Parse(StartDate);
string[] FormalDate = val.Split(" ".ToCharArray());
CultureInfo ci = new CultureInfo("es-ES");
string _Date = FormalDate[1].Replace("-", " al ").Replace(",", "");
string _Month = ci.TextInfo.ToTitleCase(TheDate.ToString("MMMM", ci));
val = string.Concat(_Date, " ", _Month);
return val;
}
private string buildAgendaLink(string val)
{
if (val.Trim() != "")
{
val = string.Concat("Agenda");
}
else
{
val = "Agenda";
}
return val;
}
}
}
Your server returns an array. Just try
Course[] courses = JsonConvert.DeserializeObject<Course[]>(returnjson);
Note that this is not an answer to your original problem, but I added it like an answer in order to explain my comment above with some actual code.
First problem with your code is that FormalDate and AgendaUrl properties simply won't work. Accessing them will result in a StackOverflowException, because you basically defined them recursively.
A property is merely syntax sugar for two separate getter/setter methods, so by writing this:
public class Course
{
public string FormalDate
{
get { return FormalDate; }
}
}
You are basically writing this:
public class Course
{
public string GetFormalDate()
{
// recursive call, with no terminating condition,
// will infinitely call itself until there is no
// more stack to store context data (and CLR
// will then throw an exception)
return GetFormalDate();
}
}
To fix that, you need to add an actual backing field, e.g.:
public class Course
{
private string _formalDate; // <-- this is a backing field;
// and this property uses the backing field to read/store data
public string FormalDate
{
get { return _formalDate; }
set { _formalDate = convertFormalDateToSpanish(value); }
}
}
Additionally, it's unusual for a property getter to return a different value than the one set through a setter. In other words, I would never expect this from a class:
var course = new Course();
course.StartDate = "2016/09/01";
course.FormalDate = "September 1-2, 2016";
Console.WriteLine(course.FormalDate); // prints "1 al 2 Septiembre" ?
I would rather move this functionality into a different class, or at least create different properties which return these values:
public class CourseInfo
{
// this is now a "dumb" auto-implemented property
// (no need for a backing field anymore)
public string FormalDate { get; set; }
// this read-only property returns the converted value
public string LocalizedFormalDate
{
get
{
return convertFormalDateToSpanish(FormalDate);
}
}
}

crash Console Application

This is my problem:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public abstract class EntityMember<T>
{
public T Value { get; set; }
}
public class Int32EntityMember : EntityMember<int?>
{
}
public class StringEntityMember : EntityMember<string>
{
}
public class GuidEntityMember : EntityMember<Guid?>
{
}
public class Entity
{
public GuidEntityMember ApplicationId { get; private set; }
public Int32EntityMember ConnectedCount { get; private set; }
public GuidEntityMember MainApplicationId { get; private set; }
public Int32EntityMember ProcessId { get; private set; }
public StringEntityMember ProcessName { get; private set; }
}
class Program
{
static void Main(string[] args)
{
Entity entity2 = new Entity();
Guid empty = Guid.NewGuid();
Guid applicationId = Guid.NewGuid();
int Id = 10;
string name = "koko";
entity2.MainApplicationId.Value = new Guid?(empty);
entity2.ApplicationId.Value = new Guid?(applicationId);
entity2.ProcessId.Value = new int?(Id);
entity2.ProcessName.Value = name;
entity2.ConnectedCount.Value = 1;
}
}
}
The application has totally blocked on the line:
entity2.MainApplicationId. Value = new Guid? (empty);
Why?
The exception you're receiving is:
Object reference not set to an instance of an object.
This is because entity2.MainApplicationId is null. Your Entity class does not have a constructor to set MainApplicationId to be not null, hence the error you're seeing.
Adding a constructor to your Entity class as shown in the code below results in your code running without error:
public Entity()
{
ApplicationId = new GuidEntityMember();
ConnectedCount = new Int32EntityMember();
MainApplicationId = new GuidEntityMember();
ProcessId = new Int32EntityMember();
ProcessName = new StringEntityMember();
}
Using Auto-Implemented properties does not result in the underlying fields (that are created and managed on your behalf by the compiler) being new'd when the instance is constructed. Thus the two properties that follow are not the same:
public MyClass MyProperty { get; private set; }
private MyClass _myOtherProperty = new MyClass();
public MyClass MyOtherProperty
{
get
{
return _myOtherProperty;
}
set
{
_myOtherProperty = value;
}
}
Try changing the line to a type cast:
entity2.ApplicationId.Value = (Guid?)(applicationId);

Categories