Retrieve values from JSON - c#

I am retrieving values from JSON and want to compare that. but I am getting Index Out of Range Exception on:
string email = contactdata.data[0].email[i].value;
Code:
int length = contactdata.data.Length;
for (int i = 0; i <= length; i++)
{
string email = contactdata.data[0].email[i].value;
if (contactemail == email)
{
counter++;
flag = 1;
break;
}
}
JSON Class:
public class Rootobject
{
public bool success { get; set; }
public Datum[] data { get; set; }
public Additional_Data additional_data { get; set; }
}
public class Additional_Data
{
public Pagination pagination { get; set; }
}
public class Pagination
{
public int start { get; set; }
public int limit { get; set; }
public bool more_items_in_collection { get; set; }
}
public class Datum
{
public int id { get; set; }
public Email[] email { get; set; }
}
public class Email
{
public string label { get; set; }
public string value { get; set; }
public bool primary { get; set; }
}

change the line
int length = contactdata.data.Length;
to
int length = contactdata.data[0].email.Length;
and change the condition in the for loop from i <= length to i < length.

Change this
for (int i = 0; i <= length; i++)
with
for (int i = 0; i < length; i++)
index start alwais from 0

Your iteration variable is on the contactdata.datanot on email, thus your i variable is on these indexes.

As I mentioned in a comment, using a nested for loop over data and ALSO over email will ensure you actually have an email you can look at!
The index out of range error means that you're trying to access an item in an array that doesn't exist.
I did not test the following code, but I used really explicit variable names in the loop to show you what I'm trying to count, and how I can only access something in an array if I know that it actually exists:
//first get the length of data
var dataLength = contactdata.data.Length;
//now loop through it
for (var dataCounter = 0; dataCounter < dataLength; dataCounter++){
//next get the length of email - is there even an email available?
var emailLength = contactdata.data[dataCounter].email.Length;
for (var emailCounter = 0; emailCounter < emailLength; emailCounter ++){
//now you can access the email and work with it.
if (contactemail == contactdata.data[dataCounter].email[emailCounter]){
// here do your code
}
}
}

Related

How feed a table with multiple foreign keys from different tables

so I have 3 models :
public class Contact
{
public int ContactID { get; set; }
public string name { get; set; }
public int SegmentID { get; set; }
public Segment Segment { get; set; }
}
public class MedicalPlan
{
public int MedicalPlanID { get; set; }
public string name { get; set; }
public int SegmentID { get; set; }
public Segment Segment { get; set; }
}
public class Target
{
public int TargetID { get; set; }
public int MedicalPlanID { get; set; }
public int ContactID { get; set; }
public MedicalPlan MedicalPlan { get; set; }
public Contact Contact { get; set; }
}
A MedicalPlan got many Contacts, and Target got both many MedicalPlans and Contacts,
Now Each MedicalPlan has a buttom called generate: Example
What I want is when you press that buttom it creates a Target and generates every Contacts that are associated to that MedicalPlan through SegmentID and insert them in the table Target as shown here
I've tried something like this :
IEnumurable<int> cons =
from contact in contacts
where contact.SegmentID == planMedical.SegmentID
select contact.ContactID;
int[] res = cons.ToArray();
for ( int j = 0; j < res.Length ; j++)
{
targets.PlanMedicalID = id; //id MedicalPlans current row's key
targets.ContactID = res[j];
_context.Add(targets);
await _context.SaveChangesAsync();
}
But it does nothing..
You are creating you ViewModel which is PlanTargets, but you have to create you Database Model Entity, you have to create the object as:
for ( int j = 0; j < res.Length ; j++)
{
var target = new Target //ADD THIS LINE
{
MedicalPlanID = id,
ContactID = res[j] ​
​ };
_context.Target.Add(target);
_context.SaveChangesAsync();
}
You are not creating a Target object, you are creating a PlanTargets object and trying to add it to your DbContext.
NOTE: In your scenerio, you want to create a Target object for every ContactID, so in your for loop you have to create the object with the new keyword, and set the related properties, after that you have to add it to your DbContext, and when you SaveChanges then it will save the results to your database.

working with DataTabe, List<> and DataGridView inside nested For Next

Im trying to get information out of certain List inside For Next loop to be able to place the data in a DataTable so I can show it in a DataGridView. Well I have been searching and trying for hours but I dont gett the result I want. I think I'm almost there but something I'm doing wrong. Is ther eanybody willing to help me?
private void Form4_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
//Set first column names
//dt.Columns.Add("Sample No");
for (int i = 0; i <= frmMain.iAnaChan-1; i++)
//Loop to add analog channel columns
{
dt.Columns.Add(frmMain.AnalogChannelList[i].ch_id.ToString());
}
DataRow row = dt.NewRow();
for (int sam = 1; sam <= frmMain.TotSamples ; sam++)
{
for (int chan = 0; chan <= frmMain.iAnaChan -1; chan++)
{
row[chan] = frmMain.channeldata[sam-1].sSampleVal.ToString();
dt.Rows.Add(row);
}
}
dataGridViewSampleData.DataSource = dt;
}
Class
public class aChannelList
{
//Class for retreiving all Analog Channel information
public string An { get; set; }
public string ch_id { get; set; }
public string ph { get; set; }
public string ccbm { get; set; }
public string uu { get; set; }
public string chanMult { get; set; }
public string chanOffset { get; set; }
public string skew { get; set; }
public string minRange { get; set; }
public string maxRange { get; set; }
public string primVal { get; set; }
public string secVal { get; set; }
public string scalingID { get; set; }
}
public class SampledData
{
//This class retreives the relevant information into a list to give the relevant channel data visible into a datagrid for information
public string sSampleNo { get; set; }
public string sTimeStamp { get; set; }
public string sSampleVal { get; set; }
}
iAnaChan is an integer than should set the amount of "channels" i.e. columns I need. And this works correct if I don't run the below code.
Than I need to start rows, the amount of rows have the values of frmMain.TotSamples and place them inside a a For Next loop so it will place the rows automatically. Than I try to add in the columns the sample values in the repectivly columns and add a row. After all loops have been passed thru I try to place it in a DataTable. But unfortunatly this doesn't work and I really would like to know what I am doing wrong?
You can create public ObservableCollection<object> Items { get; set; } into which you will add the items using a foreach loop
foreach (var item in dataCollection)
Items.Add(item)
Then just set DataGrid's ItemSource to Items. DataGrid is able to autogenerate itself this way.

Empty string comparison is failing

Currently writing a simple reservation. Right now I have a multidimensional string array that holds the passengers name and I am trying to iterate through that array and see whether there are any open seats so I know whether or not to add them to a waiting list.
// Check how many seats are taken
for (int i = 0; i <= nameArray.GetUpperBound(0); i++)
{
for (int j = 0; j <= nameArray.GetUpperBound(1); j++)
{
if (nameArray[i, j] == "")
{
seatsFilled--;
}
else
{
seatsFilled++;
}
}
}
For some reason when I debug, I notice that this line
if (nameArray[i, j] == "")
Doesn't do anything at all and gets skipped over despite there being no names in the array. I cannot for the life of me figure out why. Any suggestions?
One of the reason i can see is the comparison may have the whitespace. Try this
if(string.IsNullOrWhiteSpace(nameArray[i, j]))
I would do something like this:
First I would create some interfaces and models that would define the structure of the seat. Make sure to account for seat restrictions.
public interface ISeat
{
int RowNumber { get; }
string SeatLetter { get; }
PassangerModel Passenger { get; }
}
We want to allow some of the seats to be restricted based on passenger age and height. Hard coding that into each seat is nasty so instead I created a SeatRestriction class that has a predicate in it. This predicate will take the passenger model in and return a result. So for example you could create a SeatRestriction that checked a passengers height or age to make sure they can open emergency doors.
public class SeatRestriction
{
public Predicate<PassangerModel> Restriction { get; private set; }
public SeatRestriction(Predicate<PassangerModel> restriction)
{
Restriction = restriction;
}
}
The passenger model can actually be much more verbose than this. I'm assuming here no dietary needs. Maybe this is a reservation system for Spirit Airlines.
public class PassangerModel
{
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string CreditCardName { get; set; }
public string CreditCardNumber { get; set; }
public string CreditCardExpiration { get; set; }
public string CreditCardSecurityPin { get; set; }
}
Next We come to our seat class. This class allows us to see if a passenger is assigned to the seat. Take note that it also asserts prior to adding the passenger to the seat if the passenger meets the restrictions, if any.
public interface IRestrictedSeat
{
List<SeatRestriction> Restrictions { get; }
bool AssertQualifiedPassenger(PassangerModel passenger);
}
public class Seat : ISeat, IRestrictedSeat
{
public bool IsSeatReserved { get { return Passenger != null; } }
public int RowNumber { get; private set; }
public string SeatLetter { get; private set; }
public PassangerModel Passenger { get; private set; }
public List<SeatRestriction> Restrictions { get; private set; }
public Seat(int rowNumber, string seatLetter)
{
Restrictions = new List<SeatRestriction>();
RowNumber = rowNumber;
SeatLetter = seatLetter;
}
public bool TryAddPassenger(PassangerModel passanger)
{
if (AssertQualifiedPassenger(passanger))
{
Passenger = passenger;
return true;
}
else
{
return false;
}
}
public bool AssertQualifiedPassenger(PassangerModel passenger)
{
foreach(SeatRestriction restriction in Restrictions)
{
if (!restriction.Restriction(passenger))
{
return false;
}
}
return true;
}
}
Finally we get to the row. Our row knows how manys seats it has and what its number is. You should be able to add seats to it and then call GetAvailableSeats to get the seats that are left in this row.
public class SeatRow
{
public int TotalSeats { get; private set; }
public int RowNumber { get; private set; }
public List<Seat> Seats { get; private set; }
public SeatRow(int seatsInRow, int rowNumber)
{
TotalSeats = seatsInRow;
RowNumber = rowNumber;
}
public bool TryAddSeatToRow(Seat seat)
{
if(Seats.Count <= TotalSeats && seat.RowNumber == RowNumber)
{
Seats.Add(seat);
return true;
}
else
{
return false;
}
}
public IEnumerable<Seat> GetAvailableSeats()
{
return Seats.Where(seat => seat.IsSeatReserved == false);
}
}
The long and short of this answer is there's a million ways to solve CIS problems and to not rely on stack overflow while you're in school/learning. Good luck and welcome to the club :-)
if (nameArray[i, j] == "")
Doesn't do anything at all and gets skipped over despite there being no names in the array.
That line is inside a loop that iterates through the items in the array. If the array is empty then this will never get executed.

Refactor a method that it can handle multiple types?

I have the following class:
public class Disciplines
{
public int Id { get; set; }
public string Discipline { get; set; }
public bool IsChecked { get; set; }
}
My project has several view models that use that class to create a checkbox group in the form of:
public List<Disciplines> DisciplinesCBG { get; set; }
I'm saving the checkbox selections to the database as a comma separated string, and then splitting the string on the comma to re display as checkboxes:
public static UserProfileViewModel DisciplinesStringToCheckboxGroup(UserProfileViewModel model)
{
string[] disciplineArray = model.Disciplines.Split(',');
for (int i = 0; i < model.DisciplinesCBG.Count; i++)
{
string currentValue = model.DisciplinesCBG[i].Discipline;
if(Array.IndexOf(disciplineArray, currentValue) > -1)
{
model.DisciplinesCBG[i].IsChecked = true;
}
}
return model;
}
My question is, how can I write the method to be usable for other ViewModel types in addition to UserProfileViewModel? For example I have a view model called RegisterViewModel that uses the same public List<Disciplines> DisciplinesCBG { get; set; } that I would like to be able to use the same method as above without having to just copying it and change the signature. I'm assuming that it is possible?
You can create an interface that has Disciplines and DisciplinesCBG property and then implement it in each classes that you want to apply.
interface IHasDiciplines
{
string Disciplines { get; set; }
List<Disciplines> DisciplinesCBG { get; set; }
}
class UserProfileViewModel : IHasDiciplines
{
public string Disciplines { get; set; }
public List<Disciplines> DisciplinesCBG { get; set; }
}
public static IHasDiciplines DisciplinesStringToCheckboxGroup(IHasDiciplines model)
{
string[] disciplineArray = model.Disciplines.Split(',');
for (int i = 0; i < model.DisciplinesCBG.Count; i++)
{
string currentValue = model.DisciplinesCBG[i].Discipline;
if(Array.IndexOf(disciplineArray, currentValue) > -1)
{
model.DisciplinesCBG[i].IsChecked = true;
}
}
return model;
}

store array in data contract

i have a data contract defined as follows:
[DataContract]
public class DemoSearchList : ReturnValuesBase
{
[DataMember]
public string SessionId { get; set; }
[DataMember]
public string[] StartDate { get; set; }
[DataMember]
public string[] EndDate { get; set; }
[DataMember]
public string ProductID { get; set; }
}
as u can observe StartDate and Enddate are array of strings.
i want to send array of responses to these.
for (int i = 0; i < DS.Tables[0].Rows.Count; i++)
{
DemoSearchList.StartDate[i] = Convert.ToString(DS.Tables[0].Rows[i][0]);
DemoSearchList.EndDate[i] = Convert.ToString(DS.Tables[0].Rows[i][1]);
}
DS is a dataset.
but i get an error as index out of bound . can anyone please help and also tel me if anything extra needs to be declared and used to achieve this
This means that your array is has not the correct size or is not yet initialized. You need to do this before your for-loop:
DemoSearchList.StartDate = new string[DS.Tables[0].Rows.Count];
DemoSearchList.EndDate = new string[DS.Tables[0].Rows.Count];
But I would prefer to make a list instead of an array (if you don't need the index of each value):
[DataContract]
public class DemoSearchList : ReturnValuesBase
{
public DemoSearchList()
{
this.StartDate = new List<string>();
this.EndDate = new List<string>();
}
[DataMember]
public List<string> StartDate { get; set; }
[DataMember]
public List<string> EndDate { get; set; }
}
Then your for-loop could look like this:
for (int i = 0; i < DS.Tables[0].Rows.Count; i++)
{
DemoSearchList.StartDate.Add(Convert.ToString(DS.Tables[0].Rows[i][0]));
DemoSearchList.EndDate.Add(Convert.ToString(DS.Tables[0].Rows[i][1]));
}
For using Array their length should be defined
StartDate = new String[10]; //can use data row count here
EndDate = new String[10]; //can use data row count here
if you want to use objects of dynamic length then use LISTinstead
or change them to
[DataMember]
public List<String> StartDate { get; set; }
[DataMember]
public List<String> EndDate { get; set; }

Categories