Tshumore Ответов: 2

Как разрешить исключение htmldropdownfor nullreference


У меня есть выпадающий список MVC Razor, который бросает "ссылка на объект не установлена на экземпляр объекта", когда я делаю отправку. Я совершенно не знаю, как возникает эта ошибка.


В моей модели у меня есть:
public int BankId { get; set; }
public List<SelectListItem> Banks { get; set; }

Метод, который заполняет SelectListItem как :
public static List<SelectListItem> PopulateBank()
{
    List<SelectListItem> items = new List<SelectListItem>();
    using (SqlConnection conn = new SqlConnection(Helpers.DatabaseConnect))
    {
        SqlCommand cmd = new SqlCommand("SELECT BankId,BankName FROM Bank WHERE Active=" + Convert.ToInt32(Helpers.parameters.active) + "", conn);
        conn.Open();
        SqlDataReader dr = cmd.ExecuteReader();
        while (dr.Read())
        {
            items.Add(new SelectListItem
            {
                Text = Convert.ToString(dr["BankName"]),
                Value = Convert.ToString(dr["BankId"])
            });
        }
        conn.Close();
    }
    return items;
}

Тогда в контроллере у меня есть :
public ActionResult Bank ()
{
    Models.Employee.Registration bank = new Models.Employee.Registration();
    bank.Banks = PopulateBank();        
    return View(bank);
}

Когда я нажимаю submit BankId не получает никакого значения:
[HttpPost]
public ActionResult Bank(FormCollection formcollection)
{
    try
    {
        Models.Employee.Registration bank = new Models.Employee.Registration();

        bank.Banks = PopulateBank();
	bank.BankId = Convert.ToInt32(formcollection["BankId"]);
	if (ModelState.IsValid)
        {
            using (SqlConnection conn1 = new SqlConnection(Helpers.DatabaseConnect))
            {
                SqlCommand cmd = new SqlCommand("SaveEmployeeBankDetail", conn);
                cmd.CommandType = CommandType.StoredProcedure;

                cmd.Parameters.AddWithValue("@EmployeeNumber", bank.EmployeeNumber);
                cmd.Parameters.AddWithValue("@BankId", bank.BankId); conn.Open();
                cmd.ExecuteNonQuery();
            }
        }
        catch (Exception)
        {
            ViewBag.ErrorMessage = Helpers.Messages.GENERAL_ERROR;
            return View();
        }
        return RedirectToAction("Index");
}

В Bank.cshtml у меня есть
<div class="col-sm-9">
    <span class="input-icon">
        @Html.DropDownListFor(m => m.BankId, Model.Banks, "", htmlAttributes: new { @class = "form-control" })
        @Html.ValidationMessageFor(model => model.BankId, "", new { @class = "text-danger" })
        <i class="ace-icon fa fa-bank blue"></i>
    </span>
</div>


Что я уже пробовал:

Я искал некоторые источники в интернете , предложения заключаются в том, что мне нужно повторно заполнить DropDownListFor в этом посте . Что же касается самого модель я уже передал его обратно в представление, то есть в GET-версии общественный банк ActionResult Пожалуйста, кто-нибудь может помочь мне в том, как я могу повторно инициализировать это модель с ценностями.

Кроме того, есть ли что-нибудь, что я должен сделать в Bank.cshtml по этому поводу ?

2 Ответов

Рейтинг:
5

Richard Deeming

Вместо того чтобы пройти мимо FormCollection и вручную привязав модель, попробуйте передать сам класс модели, и пусть привязка модели позаботится об этом за вас:

[HttpPost]
public ActionResult Bank(Models.Employee.Registration bank)
{
    if (!ModelState.IsValid)
    {
        bank.Banks = PopulateBank();
        return View(bank);
    }
    
    try
    {
        using (SqlConnection conn = new SqlConnection(Helpers.DatabaseConnect))
        using (SqlCommand cmd = new SqlCommand("SaveEmployeeBankDetail", conn))
        {
            cmd.CommandType = CommandType.StoredProcedure;

            cmd.Parameters.AddWithValue("@EmployeeNumber", bank.EmployeeNumber);
            cmd.Parameters.AddWithValue("@BankId", bank.BankId); 
            
            conn.Open();
            cmd.ExecuteNonQuery();
        }
        
        return RedirectToAction("Index");
    }
    catch (Exception)
    {
        ViewBag.ErrorMessage = Helpers.Messages.GENERAL_ERROR;
        return View();
    }
}
Кроме того, не используйте конкатенацию строк для построения запроса в вашем PopulateBank метод.
public static List<SelectListItem> PopulateBank()
{
    List<SelectListItem> items = new List<SelectListItem>();
    
    using (SqlConnection conn = new SqlConnection(Helpers.DatabaseConnect))
    using (SqlCommand cmd = new SqlCommand("SELECT BankId, BankName FROM Bank WHERE Active = @Active", conn))
    {
        cmd.Parameters.AddWithValue("@Active", Helpers.parameters.active);

        conn.Open();
        
        using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
        {
            while (dr.Read())
            {
                items.Add(new SelectListItem
                {
                    Text = Convert.ToString(dr["BankName"]),
                    Value = Convert.ToString(dr["BankId"])
                });
            }
        }
    }
    
    return items;
}


Tshumore

Спасибо @RichardDeeming. Это подтверждает dropdownfor хорошо, но я получаю исключение "ViewData элемент, который имеет идентификатор банка ключ' - это типа 'System.Типа int32' но должны быть типа 'интерфейс IEnumerable&ЛТ;selectlistitem&ГТ;'." Я получаю это во всех других выпадающих списках для формы , я попытался переназначить модель обратно как :
[HttpPost]
общественный банк ActionResult(модели.Работник.Регистрация банка)
{
if (!ModelState.Функция IsValid)
{
банк.Банки = PopulateBank();
обратный вид(банк);
}

пробовать
{
используя (sqlconnection с соед = новый объект sqlconnection(помощники.DatabaseConnect))
используя (команда sqlcommand cmd и = новая команда sqlcommand("SaveEmployeeBankDetail", соед))
{
УМК.CommandType = CommandType.Хранимая процедура;

cmd.параметры.AddWithValue("@EmployeeNumber", bank.EmployeeNumber);
cmd.параметры.AddWithValue ("@BankId", банк.Идентификатор банка);

Коннектикут.Открыть();
УМК.Метод executenonquery();
}

return RedirectToAction("индекс");
}
catch (исключение)
{
var data = from p in bank.SortCodes
выберите новый
{
Столбце bankname = стр. Текст,
Сайт BankID = стр. Значение
};

Список списка = новый списка(данные, "идентификатор банка", "столбце bankname");
Видовой мешок.Сортировка кодов = список;
Видовой мешок.Сообщение Об Ошибке = Помощники.Сообщения.ОБЩАЯ ОШИБКА;
возвращение смотреть();
}
}

Richard Deeming

Похоже, вы попали в исключение. Попробуйте изменить это последнее return View(); В вашем catch блок до:

bank.Banks = PopulateBank();
return View(bank);

Рейтинг:
0

OriginalGriff

Это одна из самых распространенных проблем, которые нам задают, и это также та, на которую мы меньше всего готовы ответить, но вы больше всего готовы ответить сами.

Позвольте мне просто объяснить, что означает ошибка: вы пытались использовать переменную, свойство или возвращаемое значение метода, но оно содержит null - что означает, что в переменной нет экземпляра класса.
Это немного похоже на карман: у вас есть карман в рубашке, который вы используете, чтобы держать ручку. Если вы сунете руку в карман и обнаружите, что там нет ручки, вы не сможете подписать свое имя на листе бумаги - и вы получите очень смешные взгляды, если попытаетесь! Пустой карман дает вам нулевое значение (здесь нет ручки!), поэтому вы не можете сделать ничего, что обычно делали бы, когда вы извлекли свою ручку. Почему он пуст? Вот в чем вопрос - может быть, вы забыли взять ручку, когда уходили из дома сегодня утром, или, возможно, вы оставили ручку в кармане вчерашней рубашки, когда снимали ее вчера вечером.

Мы не можем сказать, потому что нас там не было, и, что еще важнее, мы даже не можем видеть вашу рубашку, не говоря уже о том, что находится в кармане!

Вернемся к компьютерам, и вы каким - то образом сделали то же самое-и мы не можем увидеть ваш код, а тем более запустить его и узнать, что содержит null, когда это не должно быть.
Но вы можете - и Visual Studio поможет вам здесь. Запустите свою программу в отладчике, и когда она выйдет из строя, VS покажет вам строку, в которой она обнаружила проблему. Затем вы можете начать просматривать различные его части, чтобы увидеть, какое значение равно null, и начать просматривать свой код, чтобы узнать, почему. Поэтому поставьте точку останова в начале метода, содержащего строку ошибки, и снова запустите программу с самого начала. На этот раз VS остановится перед ошибкой и позволит вам изучить, что происходит, пройдя через код, глядя на ваши значения.

Но мы не можем этого сделать - у нас нет вашего кода, мы не знаем, как его использовать, если бы он у нас был, у нас нет ваших данных. Так что попробуйте - и посмотрите, сколько информации вы можете узнать!