ViewData आइटम जिसमें कुंजी 'XXX' टाइप 'System.Int32' की है, लेकिन 'IEnumerable <SelectListItem' टाइप का होना चाहिए


113

मेरे पास निम्नलिखित दृश्य मॉडल है

public class ProjectVM
{
    ....
    [Display(Name = "Category")]
    [Required(ErrorMessage = "Please select a category")]
    public int CategoryID { get; set; }
    public IEnumerable<SelectListItem> CategoryList { get; set; }
    ....
}

और एक नया प्रोजेक्ट बनाने और असाइन करने के लिए निम्न नियंत्रक विधि Category

public ActionResult Create()
{
    ProjectVM model = new ProjectVM
    {
        CategoryList = new SelectList(db.Categories, "ID", "Name")
    }
    return View(model);
}

public ActionResult Create(ProjectVM model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }
    // Save and redirect
}

और देखने में

@model ProjectVM
....
@using (Html.BeginForm())
{
    ....
    @Html.LabelFor(m => m.CategoryID)
    @Html.DropDownListFor(m => m.CategoryID, Model.CategoryList, "-Please select-")
    @Html.ValidationMessageFor(m => m.CategoryID)
    ....
    <input type="submit" value="Create" />
}

दृश्य सही तरीके से प्रदर्शित होता है लेकिन फ़ॉर्म सबमिट करते समय, मुझे निम्न त्रुटि संदेश मिलता है

InvalidOperationException: ViewData आइटम जिसमें 'श्रेणीआईडी' कुंजी है, 'System.Int32' प्रकार का है, लेकिन यह 'IEnumerable <SelectListItem' प्रकार का होना चाहिए।

वही त्रुटि का उपयोग कर होता @Html.DropDownList()विधि, और अगर मैं का उपयोग कर एक selectList पारित ViewBagया ViewData

जवाबों:


109

त्रुटि का मतलब है कि मान CategoryList शून्य है (और परिणामस्वरूप DropDownListFor()विधि को उम्मीद है कि पहला पैरामीटर प्रकार का है IEnumerable<SelectListItem>)।

आप (और न ही आपको) SelectListItemमें से प्रत्येक की प्रत्येक संपत्ति के लिए एक इनपुट उत्पन्न नहीं कर रहे हैं , इसलिए नियंत्रक विधि में पोस्ट किए गए के CategoryListलिए कोई मान नहीं SelectListहैं, और इसलिए model.CategoryListPOST विधि का मूल्य है 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टाइपोफ़ है 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>

8
@ श्यजु, हां, मैंने एसओ पर कई अन्य इसी तरह के सवाल पर डुप्लीकेट हैमरिंग के उद्देश्य से इसे (सामुदायिक विकि के रूप में) शुद्ध रूप से पूछा और उत्तर दिया जो अनुत्तरित या अस्वीकार्य है। लेकिन मुझे लगता है कि बदला लेने वाले मतदाता पहले ही शुरू हो चुके हैं - पहला पोस्ट करने के बाद 2 सेकंड से भी कम था - इतना समय भी नहीं था कि इसे पढ़ने के लिए अकेले जवाब दें।

1
समझा। एक ही समस्या के साथ 100 प्रश्न हैं। आमतौर पर जो लोग उन सवालों को पूछते हैं, वे उचित खोज नहीं करते हैं (या उन्होंने शब्द द्वारा मौजूदा उत्तर शब्द को कॉपी और पेस्ट किया है, लेकिन काम नहीं किया!) इसलिए मुझे यकीन नहीं है कि यह वास्तव में मदद कर सकता है। :) अच्छी तरह से लिखा BTW।
श्यजू

@ यह सही तरीका नहीं है कि आप पूछ रहे हैं और यू जवाब दे रहे हैं
दिलीप ओगनिया

8
@DilipN, आपका क्या मतलब है सही तरीका नहीं है ? यह वास्तव में एसओ को प्रोत्साहित करता है। आप पढ़ना चाहिए इस और मेटा पर कुछ समय खर्च करते हैं।

4
@DilipN, क्योंकि मैं इसका उपयोग कई ऐसे ही सवालों के निशान बनाने के लिए करूँगा जो एक डुप्लिकेट के रूप में हैं जिन्हें या तो अनुत्तरित छोड़ दिया गया है, या उत्तर दिया गया है लेकिन स्वीकार नहीं किया गया है इसलिए उन्हें बंद किया जा सकता है (और इसलिए अन्य अपना समय बर्बाद नहीं करते हैं)। मैंने इसे एक सामुदायिक विकी भी बना दिया है ताकि कोई भी इसे समय के साथ संपादित और बेहतर कर सके।

6

करने के लिए स्टीफंस (user3559349) अनुसार जवाब , इस उपयोगी हो सकता है:

@Html.DropDownListFor(m => m.CategoryID, Model.CategoryList ?? new List<SelectListItem>(), "-Please select-")

या ProjectVM में:

public class ProjectVM
{
    public ProjectVM()
    {
        CategoryList = new List<SelectListItem>();
    }
    ...
}

1

अधिकांश संभावित रूप से आपके पृष्ठ पर पुनर्निर्देशित करने में किसी प्रकार की त्रुटि हुई है और आप अपने मॉडल की ड्रॉप डाउन सूचियों को फिर से शुरू नहीं कर रहे हैं।

यह सुनिश्चित करें कि आप अपने ड्रॉप डाउन को या तो मॉडल के कंस्ट्रक्टर में या हर बार पेज पर भेजे गए मॉडल को भेजने से पहले शुरू करते हैं।

अन्यथा आपको ड्रॉप डाउन सूचियों की स्थिति को व्यू बैग के माध्यम से या छिपे हुए मूल्य सहायकों के माध्यम से बनाए रखना होगा।


0

मेरे पास एक ही समस्या थी, मुझे एक अवैध मॉडलस्टेट मिल रहा था जब मैंने फॉर्म पोस्ट करने की कोशिश की। मेरे लिए, यह कैटेगिरी को इंट में सेट करने के कारण हुआ था, जब मैंने इसे बदलने के लिए मॉडलस्टैट को मान्य किया था और क्रिएट विधि ने अपेक्षा के अनुरूप काम किया था।


0

ठीक है, पोस्टर के कैन्ड उत्तर ने बड़े करीने से समझाया कि त्रुटि क्यों हुई, लेकिन इसे काम करने के लिए नहीं मिला। मुझे यकीन नहीं है कि यह वास्तव में एक उत्तर है, लेकिन इसने मुझे सही दिशा में इंगित किया।

मैं एक ही मुद्दे में भाग गया और इसे हल करने के लिए एक चालाक तरीका पाया। मैं यहाँ पर कब्जा करने की कोशिश करूँगा। डिस्क्लेमर - मैं साल में एक बार वेब पेज पर काम करता हूं और वास्तव में यह नहीं जानता कि मैं ज्यादातर समय क्या कर रहा हूं। इस जवाब को किसी भी तरह से "विशेषज्ञ" जवाब नहीं माना जाना चाहिए, लेकिन यह काम बहुत कम काम करता है ...

यह देखते हुए कि मेरे पास कुछ डेटा ऑब्जेक्ट है (सबसे अधिक डेटा ट्रांसफर ऑब्जेक्ट की संभावना है) जो मैं एक क्षेत्र के लिए मान्य मानों की आपूर्ति करने के लिए ड्रॉप-डाउन सूची का उपयोग करना चाहता हूं, जैसे:

public class MyDataObject
{
  public int id;
  public string StrValue;
}

तब ViewModel इस तरह दिखता है:

public class MyDataObjectVM
{
  public int id;

  public string StrValue;
  public List<SectListItem> strValues;
}

यहाँ वास्तविक समस्या, @Stephen के रूप में, जैसा कि ऊपर वर्णित है, चयनित सूची नियंत्रक में POST विधि पर आबाद नहीं है। तो आपके नियंत्रक तरीके इस तरह दिखेंगे:

// GET
public ActionResult Create()
{
  var dataObjectVM = GetNewMyDataObjectVM();
  return View(dataObjectVM); // I use T4MVC, don't you?
}

private MyDataObjectVM GetNewMyDataObjectVM(MyDataObjectVM model = null)
{
  return new MyDataObjectVM
  {
    int id = model?.Id ?? 0,
    string StrValue = model?.StrValue ?? "", 
    var strValues = new List<SelectListItem> 
      { 
        new SelectListItem {Text = "Select", Value = ""},
        new SelectListITem {Text = "Item1", Value = "Item1"},
        new SelectListItem {Text = "Item2", Value = "Item2"}
      };
  };
}

// POST
public ActionResult Create(FormCollection formValues)
{
  var dataObject = new MyDataObject();

  try
  {
    UpdateModel(dataObject, formValues);
    AddObjectToObjectStore(dataObject);

    return RedirectToAction(Actions.Index);
  }
  catch (Exception ex)
  {
    // fill in the drop-down list for the view model
    var dataObjectVM = GetNewMyDataObjectVM();
    ModelState.AddModelError("", ex.Message);

    return View(dataObjectVM);
  )
}

ये लो। यह काम नहीं कर रहा कोड है, मैं इसे सरल बनाने के लिए कॉपी / पेस्ट और संपादित करता हूं, लेकिन आपको यह विचार मिलता है। यदि मूल डेटा मॉडल और व्युत्पन्न दृश्य मॉडल दोनों में डेटा सदस्यों का एक ही नाम है, तो UpdateModel () फ़ॉर्मकोलियन मानों से आपके लिए सिर्फ सही डेटा भरने का एक भयानक काम करता है।

मैं इसे यहां पोस्ट कर रहा हूं ताकि मुझे जवाब मिल जाए जब मैं अनिवार्य रूप से इस मुद्दे पर फिर से चलाऊंगा - उम्मीद है कि यह किसी और को भी बाहर निकालने में मदद करेगा।


0

मेरे मामले में मेरी सूची में पहली आईडी शून्य थी, एक बार जब मैंने आईडी को 1 से शुरू करने के लिए बदल दिया, तो यह काम किया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.