Object reference set to null C# application [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 have a Code where i am getting data from csv file on name search
if i type name in textbox1 then deatails related to that person are displayed in the remaining textboxes like surname , city , state
error :error screenshot 1: https://i.stack.imgur.com/VdVEZ.png
Download link of my project :
Link 1: https://www.sendspace.com/file/76vdv5
Code i have written
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace studentdetails
{
public partial class Form1 : Form
{
String filePath = "C:\\Users\\vikas\\Desktop\\d.csv";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
String con_env = textName.Text.ToString();
UserDetails ud = SearchFor(con_env);
textSurname.Text = ud.surname;
textCity.Text = ud.city;
textState.Text = ud.state;
}
UserDetails SearchFor(String searchName)
{
var strLines = File.ReadLines(filePath);
foreach (var line in strLines)
{
var bits = line.Split(',');
if (bits[0].Equals(searchName))
{
return new UserDetails()
{
surname = bits[1],
city = bits[2],
state = bits[3],
};
}
}
return null;
}
}
}
Userdetails Clas
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace studentdetails
{
class UserDetails
{
public string firstname { get; set; }
public string surname { get; set; }
public string city { get; set; }
public string state { get; set; }
}
}
Can anyone figure out why this error occurring
Object reference not set to an instance of an object.

This error occurs when your object is not initialized. In your case this error occurred while initializing UserDetails ud.
If you debug, you will realize you are returning instance of UserDetails from SearchFor() function.
When bits[0].Equals(searchName) matches at that time it is returning instance of UserDetails, but when this condition failed for all records in foreach then it is returning null which is not acceptable.
To resolve this issue instead of returning null from SearchFor() function, pass instance of UserDetails with default parameters.
Something like,
UserDetails SearchFor(String searchName)
{
var strLines = File.ReadLines(filePath);
foreach (var line in strLines)
{
var bits = line.Split(',');
if (bits[0].Equals(searchName))
{
return new UserDetails()
{
surname = bits[1],
city = bits[2],
state = bits[3],
};
}
}
return new UserDetails()
{
surname = "Default text",
city = "Default text",
state = "Default text",
}; //Here you need to fix
}
If you do something like above solution, then for failed condition it will set values of Surname, City and state to Default text which is not correct. To avoid this situation, you can put null check before assigning values to text box
private void Form1_Load(object sender, EventArgs e)
{
String con_env = textName.Text.ToString();
UserDetails ud = SearchFor(con_env);
//if ud is null then do not set values to text box
if(ud != null)
{
textSurname.Text = ud.surname;
textCity.Text = ud.city;
textState.Text = ud.state;
}
else //else block to set default value
{
textSurname.Text = "Default value";
textCity.Text = "Default value";
textState.Text = "Default value";
}
}
UserDetails SearchFor(String searchName)
{
var strLines = File.ReadLines(filePath);
foreach (var line in strLines)
{
var bits = line.Split(',');
if (bits[0].Equals(searchName))
{
return new UserDetails()
{
surname = bits[1],
city = bits[2],
state = bits[3],
};
}
}
return null;
}

If you look at your code your returning null from the method call below
UserDetails ud = SearchFor(con_env);
You then try to access a field from that object which is null
textSurname.Text = ud.surname;
You need to return the UserDetails that you are reading from the file

I did mention in my previous answer (when I gave this code) that the SearchFor method returns a null if the user is not found - when you do your search, and before you try to use the result, you should check if the return value is null. Something like:
UserDetails ud = SearchFor(con_env);
if(ud != null){
surnameTextbox.Text = ud.Surname;
...
} else {
MessageBox.Show("user not found");
}
Also note that you seem to have forgotten to set the name property of the userdetails object. Check the code i gave in the last answer. Also you should make the properties of the UserDetails class have Names Like This: Surname, City.. "public properties have names starting with a capital letter" is the rule in c# and if you're learning you should get used to doing it now

Related

fetch details from csv file on basis of name search c#

Step 1: I have created a C# application called : Student details
Step 2: Added four TextBoxes and named them as :
Image below to refer:
Studentname.Text
StudentSurname.Text
StudentCity.Text
StudentState.Text
DATA INSIDE CSV FILE
vikas,gadhi,mumbai,maharashtra
prem,yogi,kolkata,maha
roja,goal,orissa,oya
ram,kala,goa,barka
Issue is How do I fetch all the data(surname,city,state) of user prem into above textboxes studentsurname,studentcity,studentstate from csv file when I search the name in textbox 1 => studentname.Text as prem
Below is the Code where I am stuck at return null and code inside Load_Script_Click
void Connection_fetch_details(String searchName)
{
var strLines = File.ReadLines(filePath);
foreach (var line in strLines)
{
if (line.Split(',')[0].Equals(searchName))
{
Connection_fetch_details cd = new Connection_fetch_details()
{
username = line.Split(',')[1]
};
}
}
return;
}
private void Load_Script_Click(object sender, EventArgs e)
{
// load script is button
String con_env = textenv.Text.ToString();
//Address Address = GetAddress("vikas");
//textsurname.text = Address.Surname
Connection_fetch_details cd = Connection_fetch_details(con_env);
textusername.Text = cd.username;
}
==============================================================
Class file name : Address.class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DDL_SCRIPT_GENERATOR
{
public class Connection_fetch_details
{
public string username { get; set; }
}
}
The main problem is that your method is void, which means it doesn't return any value. So even though you may be finding a match, and creating a Connection_fetch_details object, you aren't returning that result back to the calling method.
This will fix that problem:
Connection_fetch_details Connection_fetch_details(String searchName)
{
var strLines = File.ReadLines(filePath);
foreach (var line in strLines)
{
if (line.Split(',')[0].Equals(searchName))
{
Connection_fetch_details cd = new Connection_fetch_details()
{
username = line.Split(',')[1]
};
return cd; //return the object containing the matched username
}
}
return null;
}
Now it will return a Connection_fetch_details object if there is a match, or null if there is no match.
Next, you asked about returning all the fields, not just one. For that you would need to
a) add more properties to your object
b) add more code to populate those properties from the CSV
c) add code to populate the textboxes with the results from the object.
I'm also going to rename "username" to something more relevant, since none of the field names you described in the question match that. I'm also going to rename your class to "Student", and rename your search method, for the same reason.
Here's an example:
Student searchStudent(String searchName)
{
var strLines = File.ReadLines(filePath);
foreach (var line in strLines)
{
var split = line.Split(',');
if (split[0].Equals(searchName))
{
Student s = new Student()
{
firstname = searchName,
surname = split[1],
city = split[2],
state = split[3]
};
return s; //return the object containing the matched name
}
}
return null;
}
private void Load_Script_Click(object sender, EventArgs e)
{
// load script is button
String con_env = textenv.Text.ToString();
//Address Address = GetAddress("vikas");
//textsurname.text = Address.Surname
Student st = searchStudent(con_env);
textsurname.Text = st.surname;
txtcity.Text = st.city;
txtstate.Text = st.state;
}
namespace DDL_SCRIPT_GENERATOR
{
public class Student
{
public string firstname { get; set; }
public string surname { get; set; }
public string city { get; set; }
public string state { get; set; }
}
}
To accomplish your goal you have to further separate your problem in more granular steps and also distinguish between what you show in your UI and what informations you hold in the background in which format.
Create a class with the desired properties
public class Student { public string Name { get; set; } ... }
Learn how to read a csv file into such an object by using an existing library like CsvHelper or CsvReader.
When you have something like List<Student> from this part. Learn how you can visualize such a thing by using some Binding (also depends on the visualization you use Winforms, WPF, etc.).
Depending on the visualization component it already supports filtering or you need to filter by yourself by using e.g. LINQ to get the matching elements students.Where(student => student.Name.StartsWith(search)).
So far a lot of smaller problems which is simply to much to answer in a single one. Please try to break down your problems into smaller ones and search for their solutions. If you get stuck, ask a new question. That's all I can do for you now.

Multi-level validation for an Object in C#

I have a Console project reads inputs from CSV file and tries to save them to database.
For that, I created a class Person that maps a CSV row.
The CSV file has two columns Name and Age. Person class is like.
class Person
{
public string Name;
public int Age;
}
So the list of all populated objects is List<Person>.
I have a new requirement to display validation messages to console before proceed with saving populated objects to database.
Validation has two levels: Error and Warning.
For example if Name property contains a special character, I have to display this message: "Error: Name contains special character"
In case Name properly contains a numeric character, I have to display only warning message: "Warning: Name contains numeric character"
I was thinking about using DataAnnotation but I cannot see a way to add different levels (Error and Warning) to validation process. Also, I'm not sure if DataAnnotation fits only in Web Applications.
Is there a way to add some functionality to Person class to get this validation done for each property?
NB: This is just an example to better understand the question, I have other rules for other properties.
You could change the Name field to a property, and incorporate this error checking into its setter. For checking if the string contains special characters though, you will need to build an array of characters you want to look for and see if any of those match a character within the string.
An example can be found here.. Special Character Check
class Person
{
private static readonly char[] numbers = "0123456789".ToCharArray();
private static readonly char[] specialChars = "!##$%^&*()".ToCharArray();
private string _name;
public string Name
{
set
{
if (Validate(value, "Name"))
_name = value;
}
get { return _name; }
}
public int age;
private bool Validate(string input, string varName)
{
bool isValid = true;
if (input.IndexOfAny(specialChars) != -1)
{
Console.WriteLine("Error- " + varName + " contains a special character.");
isValid = false;
}
if (input.IndexOfAny(numbers) != -1)
Console.WriteLine("Warning- " + varName + " contains a number.");
//optionally set isValid = false if warnings warrant this
return isValid;
}
}
Any other strings your person class contains can be formatted with properties in this same way.
add a public "validation" function inside Person - you will be able to call that function from outside the class
Use Regex class to search for digits.
define your own special characters inside an array and use Contains() method to check if the name contains special chars.
return aftermath using enum (one way to do that) and handle names that are not valid
here is a general idea for what you need (please see comments):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
Foo();
}
private static void Foo()
{
// init new object
Person p1 = new Person { age = 55, Name = "jonat8han" };
Person p2 = new Person { age = 55, Name = "jonat#han" };
Person p3 = new Person { age = 55, Name = "jonathan" };
List<Person> p = new List<Person>();
p.Add(p1);
p.Add(p2);
p.Add(p3);
foreach (Person person in p)
{
if (person.IsValid() == Person.Validation.IsWarning)
{
Console.WriteLine(person.Name + " has digit...");
Console.ReadLine();
// write here some logic to do somthing with this....
}
else if (person.IsValid() == Person.Validation.IsError)
{
Console.WriteLine(person.Name + " special char...");
Console.ReadLine();
// write here some logic to do somthing with this....
}
else if (person.IsValid() == Person.Validation.IsErrorAndWarning)
{
Console.WriteLine(person.Name + " special char and digit...");
Console.ReadLine();
// write here some logic to do somthing with this....
}
else
{
// everything IsOk
}
}
}
class Person
{
public enum Validation
{
IsWarning = 0,
IsError = 1,
IsErrorAndWarning = 2,
IsOk = 3
}
public string Name;
public int age;
public Validation IsValid()
{
if (IsError() && IsWarning())
{
return Validation.IsErrorAndWarning;
}
else if (IsError())
{
return Validation.IsError;
}
else if (IsWarning())
{
return Validation.IsWarning;
}
else
{
return Validation.IsOk;
}
}
private bool IsWarning()
{
// check if there are digits...
Regex reg = new Regex("\\d");
if (reg.IsMatch(this.Name) == true)
{
// there is digit
return true;
}
else
{
return false;
}
}
private bool IsError()
{
string[] speacialChars = new string[] { "*", "&", ".", "^", "#", "#" }; // define here what is a special character for your needs
foreach (Char c in this.Name)
{
if (speacialChars.Contains(c.ToString()))
{
return true;
}
}
return false;
}
}
}
}

How to filter a Linq Query from XML to IEnumerable of Objects

=I am writing a .NET page in C# to retrieve a feed from a WordPress blog and display it on the page. It works fine, until I try to filter the posts.
I declare an XDocument and load the feed from the URL.
Then read the posts, based on the Post class, into a IEnumarable, as I say this all works. The problem is I, for some reason, don't understand how to filter by elements.
In the Query any attempt to filter gives an error. I've tried every iteration of syntax I can think of but they all give errors. Can anyone explain, so I can slap my head perhaps, how I can filter on the Category element? Because I can't get it to recognize anything like post.Category etc. All I get is an error that post.Category does not have a definition.
If I remove the where clause it works fine? What am I doing wrong? The where syntax I am using matches MSDN examples exactly? Edit to add: It's not the single equal sign. I have changed that but it was just a typo when copying to the web.
The error is always in the form of "post.Category" (or other element name) not being defined. I am missing something in how you address the elements in the where clause, but I can't figure out what it is and my code matches several MS examples exactly.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Load the blog posts and print the title of the blog
string sURL2 = "http://myurl.com/?feed=rss2";
XDocument ourBlog = XDocument.Load(sURL2);
// Query the <item>s in the XML RSS data and select each one into a new Post()
IEnumerable<Post> posts =
from post in ourBlog.Descendants("item")
where post.Category == "x"
select new Post(post);
postRepeater.DataSource = posts;
postRepeater.DataBind();
// GridView1.DataSource = posts;
// GridView1.DataBind();
}
class Post
{
public string Title { get; private set; }
public DateTime? Date { get; private set; }
public string Url { get; private set; }
public string Description { get; private set; }
public string Category { get; private set; }
public string Creator { get; private set; }
public string Content { get; private set; }
private static string GetElementValue(XContainer element, string name)
{
if ((element == null) || (element.Element(name) == null))
return String.Empty;
return element.Element(name).Value;
}
public Post(XContainer post)
{
// Get the string properties from the post's element values
Title = GetElementValue(post, "title");
Url = GetElementValue(post, "guid");
Description = GetElementValue(post, "description");
Category = GetElementValue(post, "category");
Creator = GetElementValue(post,
"{http://purl.org/dc/elements/1.1/}creator");
// Content = GetElementValue(post,
// "{http://purl.org/dc/elements/1.0/modules/content/}encoded");
// Content = GetElementValue(post, "content");
Content = GetElementValue(post,
"{http://purl.org/rss/1.0/modules/content/}encoded");
// The Date property is a nullable DateTime? -- if the pubDate element
// can't be parsed into a valid date, the Date property is set to null
DateTime result;
if (DateTime.TryParse(GetElementValue(post, "pubDate"), out result))
Date = (DateTime?)result;
}
public override string ToString()
{
return String.Format("{0} by {1}", Title ?? "no title", Creator ?? "Unknown");
}
}
}
Your problem is, that the ourBlog.Descendants does not contain Posts but an IEnumerable<XElement>
You could try the following:
var posts = from post in ourBlog.Descendants("item")
select new Post(post);
var filteredPosts = from post in posts
where post.Category == "x"
select post;
or
var posts = from post in ourBlog.Descendants("item")
where Post.GetElementValue(post, "category") == "x"
select new Post(post);
Hope it helps ...
I edited the second statement, so that it should work now, if you change the visibility of GetElementValue to public.

C# List Elements in the Session Not Responding

I'm doing a simple program to add a student(with ID,Name) to a List, then to search Student by ID through session.
Add Student Module is like below,
protected void addStudent(object sender, EventArgs e)
{
List<Student> thisstdlist = new List<Student>();
thisstdlist = (List<Student>)Session["stdlist"];
thisstdlist.Add(new Student(txtsid.Text,txtsname.Text));
Session["stdlist"] = thisstdlist;
Response.Redirect("Home.aspx");
}
Search Student Module is Like Below,
protected void searchStudent(object sender, EventArgs e)
{
foreach (Student element in (List<Student>)Session["stdlist"])
{
if(element.getID().Equals(txtstdid.Text)){
txtstdname.Text = element.getName();
}
}
}
Student Class is like below,
public class Student
{
private String Name;
private String ID;
public Student(String sid, String sn) {
this.Name = sn;
this.ID = sid;
}
public String getName() {
return this.Name;
}
public String getID()
{
return this.ID;
}
}
But when I added students, for ex: 100,John and Search by 100 it gives me no result. Please can anyone show me the mistake or the correct way of doing this.
are you setting breakpoints and actually checking what the values of these lists and what is actually stored in the session?
.Equals() is not doing what you think it is
try :
foreach (Student element in (List<Student>)Session["stdlist"])
{
if(element.ID == txtstdid.Text){
txtstdname.Text = element.getName();
}
}
The add Student module won't initialize the student list correctly - you are creating a new List<Student> and then throwing the new list away with the next line assignment. I would go with something like:
var thisstdlist = (List<Student>)Session["stdlist"];
// If a key isn't found in Session, it will be null ..
if (thisstdlist == null)
{
// i.e. only re-initialize if it was missing from session
thisstdlist = new List<Student>();
// You don't need to continually reassign the session variable
Session["stdlist"] = thisstdlist;
}
// Adds to the list; now that Session also has a reference to the same list
thisstdlist.Add(new Student(txtsid.Text,txtsname.Text));
As per the comment, note that c# has automatic (albeit mutable) properties - you don't need the Java-style getters and setters.
public class Student
{
public Student(string sid, string sn)
{
Name = sn;
ID = sid;
}
public string Name
{
get;
set;
}
public string ID
{
get;
set;
}
}
Also, in .Net, == for strings is overridden to test values (unlike Java's reference equality for strings), so you can rewrite the comparison as:
if (element.ID == txtstdid.Text)
{
txtstdname.Text = element.Name;
}
Re : foreach - I guess means that you are using the List in a Dictionary (HashMap) fashion - if you use Dictionary instead of List - this will allow you do remove the foreach in favour of:
// addStudent ...
var txtstdname = new Dictionary<string, Student>();
// ...
txtstdname.Add(txtsid.Text, new Student(txtsid.Text,txtsname.Text))
// searchStudent ...
Student element = null;
if (txtstdname.TryGetValue(out element))
{
txtstdname.Text = element.Name();
}

Using a ComboBox as filter

I have made a program that is a kind of a wiki, but in a program. I've added lots of pictureBoxes, and I have 3 filters to sort those pictureBoxes: ROLE, ATTACK TYPE and NAME.
What I'd like to do is, like, if you select the Attack Type RANGED it disables the other pictureBoxes that has a different Attack Type than RANGED.
I've tried comparing each Hero (I've made a different class for it) with a timer, but I didn't know how to do it.
I also tried this
if(comboBox1.Text == "RANGED") { //do stuff }
But I don't know how could I access all of the heroes inside an array I made, and check if they have atkType = RANGED.
My Hero.cs class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace WindowsFormsApplication1
{
public struct Hero
{
public string Name;
public string Role; /* carry, disabler, lane support, initiator, jungler, support, durable, nuker, pusher, escape */
public string atkType; /* melee or ranged */
public string Type; /* strength, agility or intelligence */
public string imgName;
public Hero(string name, string role, string atktype, string type, string imgname)
{
Name = name;
Role = role;
atkType = atktype;
Type = type;
imgName = imgname;
}
public static Hero[] heroes = new Hero[] {
new Hero() {Name = "test", Role = "", atkType = "Melee", Type = "Strength", imgName = "test" }
};
}
}
I've managed to get the filter working, but now, there's only a problem: I can't dispose (images wont unload) the current loaded images and can't load new ones.
What I tried:
if (melee == false && ranged == false)
{
for (int i = 0; i < Hero.heroes.Length; i++)
{
imgs[i].Load("http://cdn.dota2.com/apps/dota2/images/heroes/" + Hero.heroes[i].imgName + "_sb.png");
comboBox3.Items.Add(Hero.heroes[i].Name);
//imgs[i].MouseHover += displayInfo(i);
}
}
if (ranged == true)
{
for (int i = 0; i < Hero.heroes.Length && Hero.heroes[i].atkType.Contains("Ranged"); i++)
{
imgs[i].Image.Dispose();
imgs[i].Load("http://cdn.dota2.com/apps/dota2/images/heroes/" + Hero.heroes[i].imgName + "_sb.png");
}
}
The code could be something like this:
if(cmb.text=="goofy")
//Code
else if(cmb.text=="mars")
//Other code
else
//BLA BLA

Categories

Resources