如何在下拉列表MVC中解决此错误'IEnumerable <selectlistitem>'

时间:2016-12-18 15:50:54

标签: c# asp.net-mvc asp.net-mvc-4

在我的MVC项目中,我将货币列表传递到下拉列表中的视图。但是,一旦我尝试发布视图,我会得到以下异常:

  

具有键“FromCurrencyId”的ViewData项是类型   'System.Int32'但必须是'IEnumerable'类型。

货币控制器

namespace Project.Controllers
{
    public class CurrencyController : Controller
    {
      [HttpGet]
        // GET: Currency
        public ActionResult Index()
        {

            CurrenciesClient Cur = new CurrenciesClient();
            var listCurrency = Cur.findAll().ToList();

            Currencies model = new Currencies();
            model.FromCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
            model.ToCurrencies = new SelectList(listCurrency, "Id",  "CurrencyName");

            return View(model);

        }

        [HttpPost]
        public ActionResult Index(Currencies cur)
        {


            if (ModelState.IsValid)
            {
                if (cur.FromCurrencyId == cur.ToCurrencyId)
                {
                    //do something if same currecnies and return.
                    ModelState.AddModelError("CurrencyCountry", "Can't make the conversion for the same value");
                }
                else
                {
                   some code .....
                }
            }

            return View(cur);

        }
    }
}

货币VM

namespace Project.ViewModels
{
    public class Currencies
    {
        public int Id { get; set; }
        [Required]
        public int FromCurrencyId { get; set; }
        public SelectList FromCurrencies { get; set; }

        [Required]
        public int ToCurrencyId { get; set; }
        public SelectList ToCurrencies { get; set; }

        public string CurrencyName { get; set; }

        public string CurrencyCountry { get; set; }


        [Required]
        public decimal ConversionRate { get; set; }

        public decimal Value { get; set; }

        public SelectList AvailableCurrencies { get; set; }


    }
}

CurrencyClient Web服务VM

namespace Project.ViewModels
{
    public class CurrenciesClient 
    {
        private string base_Url = "http://localhost:51646/api/";

        public IEnumerable<Currencies> findAll()
        {
            try
            {
                HttpClient client = new HttpClient();
                client.BaseAddress = new Uri(base_Url);
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                HttpResponseMessage response = client.GetAsync("currencies").Result;
                if (response.IsSuccessStatusCode)
                {
                    var resposeData = response.Content.ReadAsStringAsync().Result;
                    var Currency = JsonConvert.DeserializeObject<List<Currencies>>(resposeData);
                    return Currency;


                }
                return null;

            }
            catch
            {
                return null;
            }
        }
    }
}

索引视图

model Project.ViewModels.Currencies

@{
    ViewBag.Title = "Index";
}


@using (Html.BeginForm("Index", "Currency", FormMethod.Post))
{
    @Html.TextBoxFor(m => m.ConversionRate, new { @size = "5" })
    @Html.DropDownListFor(m => m.FromCurrencyId, Model.FromCurrencies as IEnumerable<SelectListItem>)
      @Html.DropDownListFor(m => m.ToCurrencyId, Model.ToCurrencies as IEnumerable<SelectListItem>)
        <button type="submit" class="btn btn-primary">Convert</button>
}

3 个答案:

答案 0 :(得分:1)

这个问题是因为您从下拉列表中传递 null 值。您没有选择任何值。检查如果你将从下拉列表中传递一些值,它将正常工作。要解决此问题,您需要添加相同的 代码

Currencies model = new Currencies();
            model.FromCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
            model.ToCurrencies = new SelectList(listCurrency, "Id",  "CurrencyName");

在你的控制器索引发布方法中。因为如果selectListitem为null,则将执行以下代码

 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>"));
}

哪会抛出异常。 (如果你使用

会更好

ViewBag.FromCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");

像这样。)

这里给出了更好的描述:

The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'

此链接也提供了整个解释,例如此代码如何工作。

答案 1 :(得分:0)

您还必须在帖子控制器中设置Dropdown数据,否则它将无法找到ViewBag值,因此在发布后操作后它会调用Index视图ViewBag.FromCurrenciesViewBag.ToCurrencies将是null,这显然是我们不想要的。

要修复错误,您必须将后期操作更改为:

[HttpPost]
public ActionResult Index(Currencies cur)
{


        if (ModelState.IsValid)
        {
            if (cur.FromCurrencyId == cur.ToCurrencyId)
            {
                //do something if same currecnies and return.
                ModelState.AddModelError("CurrencyCountry", "Can't make the conversion for the same value");
            }
            else
            {
               some code .....
            }
        }

        CurrenciesClient Cur = new CurrenciesClient();
        var listCurrency = Cur.findAll().ToList();

        Currencies model = new Currencies();
        model.FromCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
        model.ToCurrencies = new SelectList(listCurrency, "Id",  "CurrencyName");

        return View(cur);

    }

答案 2 :(得分:0)

您不应该从POST操作返回视图,否则会遇到很多问题。这是问题所在:

  1. 当您提交表单时,网址指向您的Index。您的http帖子的正文中会包含一堆Currencies项。因此,MVC会使用Index参数将表单提交到您的Currencies cur方法。
  2. 如果一切顺利,您将返回相同的视图。
  3. 如果您刷新页面,您的浏览器将重新发出最后一个请求并猜测是什么,它将再次提交表单。但这不是你想要的更新。您希望获得最初提交的表单,而不是重新提交表单。
  4. 因此,除了使用AJAX之外,您应该始终返回重定向,而不是从POST返回视图。

    在这种情况下,如果一切顺利,您可能希望将用户发送到成功页面或其他页面,因此您应该这样做:

    return RedirectToAction("YourActionName", "YourControllerName");
    

    此模式称为PRG模式。这样做是这样的:

    1. 用户提交表单
    2. 如果一切顺利,请告诉浏览器发出另一个请求并获取另一个页面。
    3. 浏览器获取可能是成功页面的其他页面。
    4. 现在用户在成功页面上。如果他们点击刷新,他们将再次获得成功页面。他们不会一遍又一遍地提交相同的表格。