0

I quite new to c# and asp.net so plz tell me if i give you to little info for my question.

When a user is logging in I create an instance of my User object, calling my getcategories method and the redirect then user to another page. Like this:

if (dt.Rows.Count > 0){

    user apa = new user();

    apa.namn = dt.Rows[0]["FirstName"].ToString() + " " + dt.Rows[0]["LastName"].ToString();
    apa.mail = dt.Rows[0]["Email"].ToString();
    apa.id = dt.Rows[0]["ID"].ToString();
    apa.firstname = dt.Rows[0]["FirstName"].ToString();
    apa.lastnamn = dt.Rows[0]["LastName"].ToString();
    apa.password = dt.Rows[0]["Password"].ToString();

    Session["user"] = apa;
    apa.getcategories();

    Response.Redirect("visainlagg.aspx");
}

The problem is that I get "object reference not set to an instance of an object"-error on "kategorier[i].Name = dt.Rows[i]["Name"].ToString();" (the first thing that happens in my for loop in User class). I do not understand why :(

This is how the User class looks like:

public string namn;
public string mail;
public string id;
public string firstname;
public string lastname;
public string password;
public string constr = "secret";

public Post[] poster;

public anvcateg[] kategorier;
public int antalKategorier;


public void getcategories() { 
    SqlConnection conn = new SqlConnection();
    conn.ConnectionString = constr;

    SqlCommand com = new SqlCommand();
    com.Connection = conn;
    com.CommandText = "SELECT * FROM Category WHERE Author= '" + id + "'";


    SqlDataAdapter adp = new SqlDataAdapter();
    adp.SelectCommand = com;

    DataTable dt = new DataTable();
    adp.Fill(dt);

    antalKategorier = dt.Rows.Count;

    kategorier = new anvcateg[dt.Rows.Count];

    for (int i = 0; i < dt.Rows.Count; i++)
    {
        kategorier[i].Name = dt.Rows[i]["Name"].ToString();
        kategorier[i].ID = dt.Rows[i]["ID"].ToString();
        kategorier[i].Description = dt.Rows[i]["Description"].ToString();
        kategorier[i].Author = dt.Rows[i]["Author"].ToString();

    } 
}

the anvcateg class that getcategories() is using looks like this:

public class anvcateg
{
    public string ID;
    public string Name;
    public string Description;
    public string Author;
John Saunders
  • 160,644
  • 26
  • 247
  • 397
tobbe
  • 1,737
  • 6
  • 23
  • 40
  • possible duplicate of [What is a NullReferenceException in .NET?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-in-net) –  Apr 08 '12 at 17:31
  • after adp.Fill(dt);tell us what is DT and how many rows it has – Royi Namir Apr 08 '12 at 17:33
  • And it doesn't dispose the connection correctly – Marc Gravell Apr 08 '12 at 17:37
  • Also - if you are filling an object - why use DataTable / adapter at all? Something like "dapper-dot-net" would do this directy and much more conveniently. No need for DataTable here – Marc Gravell Apr 08 '12 at 17:38
  • 1
    Btw your Author filter is ripe for SQL injection - is is actively dangerous as-written – Marc Gravell Apr 08 '12 at 17:44

3 Answers3

2

kategorier is an array of anvcateg

You initialized the array here:

kategorier = new anvcateg[dt.Rows.Count];

But you have to create an instance of anvcateg to add to your array)

for (int i = 0; i < dt.Rows.Count; i++)
    {
        kategorier[i] = new anvcateg()
            {
                ID = dt.Rows[i]["ID"].ToString(),
                Author = dt.Rows[i]["Author"].ToString(),
                Description = dt.Rows[i]["Description"].ToString(),
                Name = dt.Rows[i]["Name"].ToString()
            };

    } 
EdSF
  • 11,753
  • 6
  • 42
  • 83
  • @tobbe - no problem. The above is specific to the issue you posted only. Follow the advice of the others about cleaning up your db resource usage and injection protection. – EdSF Apr 08 '12 at 22:32
1

Your array contains all nulls - you have not created any objects. You have created an empty array. A quick fix would be:

kategorier[i] = new anvcateg();

at the start of each iteration.

For info, your current code is risky (SQL injection), doesn't clean up after itself, and unnecessarily complicated. Here's the same via "dapper":

using(var conn = new SqlConnection(constr)) {
    conn.Open();
    var data = conn.Query<anvcateg>(
        "SELECT * FROM Category WHERE Author=@id",
        new { id }).ToList();
}

(or ToArray() if you prefer)

This does all the mapping internally, cleans up the connection, and safely parameterises the "id" avoiding injection attacks. And no DataTable to be seen.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • thanks for the tip but i guess I'm very new to c# because i don't understand the last part :P (the site isn't online tho, so it won't be a problem, it's just for learning) First part solved my problem though! thanks! – tobbe Apr 08 '12 at 18:16
  • @tobbe if it is for learning, then the first thing to learn: SQL injection. Your code is currently vulnerable. This is a bad thing. The "using" is important too. "dapper" here is just a suggestion to save you some code – Marc Gravell Apr 08 '12 at 18:21
  • yea, I'll try to learn asap. My course hasn't taken this up yet, but I'm sure the teacher will do so eventually. We're at the beginning so theres a lot more to learn :) – tobbe Apr 08 '12 at 18:33
  • @tobbe gott love teacher priority... SQL injection is perhaps the easiest and most prevalent exploit, yet simple to avoid if you take a moment to think of it. – Marc Gravell Apr 08 '12 at 19:41
0

Your question is not quite clear, try to find the code "kategorier[i].Name = dt.Rows[i]["Name"].ToString();" but could not found it. if you can post your code which contain these lines then it would be easy to answer you.

Anyway, there may be the following reason of this error:

  1. Either dt.Rows[i]["Name"] is null and you are trying to convert it into string by using .ToString(), change this to Convert.ToString(dt.Rows[i]["Name"])

  2. check you have defined "kategorier" as an array or you can use the List kategorier = new List kategoriers();

Otherwise your code looks fine

Ali Adravi
  • 21,707
  • 9
  • 87
  • 85