MVC5 / C# - Cannot perform runtime binding on a null reference

自闭症网瘾萝莉.ら 提交于 2020-05-29 11:03:08

问题


I'm trying to figure out what's causing a Cannot perform runtime binding on a null reference error from this code:

var query = "SELECT Id, UserName, List_Order, LoggedIn " + 
            "FROM AspNetUsers" +
            "WHERE LoggedIn = 1" + 
            "ORDER BY List_Order ASC";

var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
var cmd = new SqlCommand(query, conn);   
conn.Open();
var rdr = cmd.ExecuteReader();
var n = 0;
while(rdr.Read())
{
    if (Convert.ToString(rdr["UserName"]) != null)
    {
        ViewBag.speakers[n] = new string[4] {
            Convert.ToString(rdr["Id"]),
            Convert.ToString(rdr["UserName"]),
            Convert.ToString(rdr["List_Order"]),
            Convert.ToString(rdr["LoggedIn"]) 
        };

        //Exception Details: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot 
        //perform runtime binding on a null reference
        n++;
    }
}

The n++ increment seems to be the cause of this error and I don't understand why.

Updated code to reflect possible solutions. However, the error still remains.

Tried this with the same result:

if (!string.IsNullOrWhiteSpace(Convert.ToString(rdr["UserName"]))) {
        List<string> speakers = new List<string>();
        speakers.Add(Convert.ToString(rdr["Id"]));
        speakers.Add(Convert.ToString(rdr["UserName"]));
        speakers.Add(Convert.ToString(rdr["List_Order"]));
        speakers.Add(Convert.ToString(rdr["LoggedIn"]));

        ViewBag.speakers[n] = speakers;
        n++;
}

回答1:


There are two issues in your code:

Consider this:

public ActionResult Index()
{
   int n = 0;
   ViewBag.speakers[n] = 5;
   return View();
}

This simplified piece of code throws Cannot perform runtime binding on a null reference since speakers is not defined (null reference).

You can fix it by defining speakers in the dynamic ViewBag before the loop:

ViewBag.speakers = new List<string>();

The second issue:

ViewBag.speakers[n] = speakers;

speakers in your code is a List, you might want to define ViewBag.speakers as a List<List<string>> and call .Add(speakers) instead of accessing using an index (you might get index was out of range)




回答2:


Calling the .ToString() method on a null column value can result in the Cannot perform runtime binding on a null reference. Use Convert.ToString() instead; it will return an empty string if you attempt to convert a null value and won't require additional code for null checking.




回答3:


ViewBag is a dynamic object and when you try to do assignments to its properties, the null check will happen in runtime. You get this error because ViewBag.speakers is either null, or it throws an exception while trying to access its nth slot with indexer (maybe its size is less than n, or it doesn't define an indexer at all). You should initialize ViewBag.speakers before adding elements to it.

var query = "SELECT Id, UserName, List_Order, LoggedIn " + 
            "FROM AspNetUsers" +
            "WHERE LoggedIn = 1" + 
            "ORDER BY List_Order ASC";

var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
var cmd = new SqlCommand(query, conn);   
conn.Open();
var rdr = cmd.ExecuteReader();
ViewBag.speakers = new List<string[]>();
while(rdr.Read())
{
    if (Convert.ToString(rdr["UserName"]) != null)
    {
        var speakers = new string[4] {
            Convert.ToString(rdr["Id"]),
            Convert.ToString(rdr["UserName"]),
            Convert.ToString(rdr["List_Order"]),
            Convert.ToString(rdr["LoggedIn"]) 
        };
        ViewBag.speakers.Add(speakers);
    }
}



回答4:


Your problem seems originated from usage of Read method after ExecuteReader, which gives null reference on dynamic object ViewBag.speakers at certain point that enough to throw runtime binding exception on view side.

Using DataTable.Load and simple for-loop to iterate DataTable contents, I modified Gökhan Kurt's answer to this one:

var query = "SELECT Id, UserName, List_Order, LoggedIn " + 
            "FROM AspNetUsers" +
            "WHERE LoggedIn = 1" + 
            "ORDER BY List_Order ASC";

using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
{
    using (var cmd = new SqlCommand(query, conn))
    {
        conn.Open();
        var dt = new DataTable();
        ViewBag.speakers = new List<string[]>();
        var rdr = cmd.ExecuteReader();
        dt.Load(rdr);

        for (int n = 0; n < dt.Rows.Count; n++)
        {
            if (!String.IsNullOrWhiteSpace(Convert.ToString(dt.Rows[n]["UserName"])))
            {
                // speakers returns String[4] array instead of null value
                var speakers = new String[4] {
                    Convert.ToString(dt.Rows[n]["Id"]),
                    Convert.ToString(dt.Rows[n]["UserName"]),
                    Convert.ToString(dt.Rows[n]["List_Order"]),
                    Convert.ToString(dt.Rows[n]["LoggedIn"])
                };

                ViewBag.speakers.Add(speakers);
            }
        }

        conn.Close();
    }
}

NB: SqlDataReader.Read() is forward-only, it will returns false after last row has reached. The ViewBag.speakers assigned to null reference if the DataReader.Read method returns false, thus while loop is not executed. Using DataTable.Load method keeps returned data from ExecuteReader even after SqlDataReader is closed or reached last row.

Secondly, you may look at reader.Read() only read once even when there are multiple rows to read problem, but IMHO it seems only work when the row length is already known or fixed size. Since it is impossible to use SqlDataReader.RecordsAffected before the data reader is closed, you need another way to get row count from SqlDataReader.

References:

Populate data table from data reader

SqlDataReader.Read()

SqlDataReader.RecordsAffected

DataTable.Load()



来源:https://stackoverflow.com/questions/40531522/mvc5-c-sharp-cannot-perform-runtime-binding-on-a-null-reference

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!