Элемент ViewData с ключом «SelectedServiceName» имеет тип «System.String», но должен иметь тип «IEnumerable & lt; SelectListItem & gt;»; [Дубликат]

Запрос может быть неудачным по различным причинам, и в этом случае оба mysql_ * и расширение mysqli вернут false из своих соответствующих функций / методов запроса. Вам нужно проверить это условие ошибки и обработать его соответствующим образом.

mysql_ * extension :

ПРИМЕЧАНИЕ Функции mysql_ устарели и были удалены в версии 7 php.

blockquote>

Перед передачей mysql_fetch_array проверьте $result. Вы обнаружите, что это false, потому что запрос завершился неудачно. См. Документацию mysql_query для возможных возвращаемых значений и предложений о том, как с ними обращаться.

$username = mysql_real_escape_string($_POST['username']);
$password = $_POST['password'];
$result = mysql_query("SELECT * FROM Users WHERE UserName LIKE '$username'");

if($result === FALSE) { 
    die(mysql_error()); // TODO: better error handling
}

while($row = mysql_fetch_array($result))
{
    echo $row['FirstName'];
}

расширение mysqli процедурный стиль :

$username = mysqli_real_escape_string($mysqli, $_POST['username']);
$result = mysqli_query($mysqli, "SELECT * FROM Users WHERE UserName LIKE '$username'");

// mysqli_query returns false if something went wrong with the query
if($result === FALSE) { 
    yourErrorHandler(mysqli_error($mysqli));
}
else {
    // as of php 5.4 mysqli_result implements Traversable, so you can use it with foreach
    foreach( $result as $row ) {
        ...

oo-style :

$username = $mysqli->escape_string($_POST['username']);
$result = $mysqli->query("SELECT * FROM Users WHERE UserName LIKE '$username'");

if($result === FALSE) { 
    yourErrorHandler($mysqli->error); // or $mysqli->error_list
}
else {
    // as of php 5.4 mysqli_result implements Traversable, so you can use it with foreach
    foreach( $result as $row ) {
      ...

с использованием подготовленного оператора:

$stmt = $mysqli->prepare('SELECT * FROM Users WHERE UserName LIKE ?');
if ( !$stmt ) {
    yourErrorHandler($mysqli->error); // or $mysqli->error_list
}
else if ( !$stmt->bind_param('s', $_POST['username']) ) {
    yourErrorHandler($stmt->error); // or $stmt->error_list
}
else if ( !$stmt->execute() ) {
    yourErrorHandler($stmt->error); // or $stmt->error_list
}
else {
    $result = $stmt->get_result();
    // as of php 5.4 mysqli_result implements Traversable, so you can use it with foreach
    foreach( $result as $row ) {
      ...

Эти примеры только иллюстрируют , что должно быть сделано (обработка ошибок), а не как это сделать. При выпуске HTML код производства не должен использовать or die , иначе он будет (по крайней мере) генерировать недопустимый HTML. Кроме того, сообщения об ошибках базы данных не должны отображаться для пользователей, не являющихся администраторами, так как раскрывает слишком много информации .

68
задан Stephen Muecke 19 December 2015 в 02:26
поделиться

1 ответ

Ошибка означает, что значение CategoryList равно нулю (и в результате метод DropDownListFor() ожидает, что первый параметр имеет тип IEnumerable<SelectListItem>).

Вы не генерируете вход для каждого свойства каждого SelectListItem в CategoryList (и не должен), поэтому никакие значения для SelectList не отправляются в метод контроллера, и поэтому значение model.CategoryList в методе POST равно null , Если вы вернете представление, вы должны сначала переназначить значение CategoryList, как и в методе GET.

public ActionResult Create(ProjectVM model)
{
    if (!ModelState.IsValid)
    {
        model.CategoryList = new SelectList(db.Categories, "ID", "Name"); // add this
        return View(model);
    }
    // Save and redirect
}

Чтобы объяснить внутреннюю работу (исходный код может быть см. здесь )

Каждая перегрузка DropDownList() и DropDownListFor() в конечном итоге вызывает следующий метод

private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata,
  string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple,
  IDictionary<string, object> htmlAttributes)

, который проверяет, есть ли selectList (второй параметр из @Html.DropDownListFor()) является null

// If we got a null selectList, try to use ViewData to get the list of items.
if (selectList == null)
{
    selectList = htmlHelper.GetSelectData(name);
    usedViewData = true;
}

, который, в свою очередь, вызывает

private static IEnumerable<SelectListItem> GetSelectData(this HtmlHelper htmlHelper, string name)

, который оценивает первый параметр @Html.DropDownListFor() (в данном случае CategoryID )

....
o = htmlHelper.ViewData.Eval(name);
....
IEnumerable<SelectListItem> selectList = o as IEnumerable<SelectListItem>;
if (selectList == null)
{
    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, 
        MvcResources.HtmlHelper_WrongSelectDataType,
        name, o.GetType().FullName, "IEnumerable<SelectListItem>"));
}

Поскольку свойство CategoryID является typeof int, оно не может быть передано в IEnumerable<SelectListItem>, и генерируется исключение (которое определено в файле MvcResources.resx как)

<data name="HtmlHelper_WrongSelectDataType" xml:space="preserve">
    <value>The ViewData item that has the key '{0}' is of type '{1}' but must be of type '{2}'.</value>
</data>
66
ответ дан Stephen Muecke 25 August 2018 в 18:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: