0

Trying to populate a dropdownlist field with data from a model. When running the code I am getting an error that reads: "Exception thrown: 'System.InvalidOperationException' in System.Web.Mvc.dll" in the VS2017 Output screen.

The Model:

namespace FulfillmentPortal.Models
{
using System;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Collections.Generic;

public partial class Carrier
{
    public int CarrierId { get; set; }

    [StringLength(50)]
    public string CarrierName { get; set; }
}

public partial class CarrierModel : DbContext
{
    public CarrierModel()
        : base("name=CarrierModel")
    {
    }

    public virtual DbSet<Carrier> Carriers { get; set; }

    public virtual DbSet<CarrierService> CarrierServices { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    }
}
}

The Controller:

namespace FulfillmentPortal.Controllers
{
public class FulfillmentController : Controller
{
    private CarrierModel db = new CarrierModel();

    // GET: Fulfillment
    public ActionResult Index()
    {
        var carrierList = db.Carriers.ToList();
        return View(carrierList);
    }  
}
}

The View:

@model FulfillmentPortal.Models.Carrier
@{
    ViewBag.Title = "index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="panel panel-primary">
<div class="panel-heading">REPORT OPTIONS</div>
<div class="panel-body">
<form id="processForm" class="form-horizontal" action="~/Fulfillment/Report" method="post" enctype="multipart/form-data">
    <div class="form-group">
        <label for="sel1">Carrier:</label>
        @Html.DropDownListFor(m => m.Carriers, new SelectList(Model.Carriers, "CarrierId", "CarrierName"), " ");       
        <label for="sel2">Carrier Services:</label>
        <select class="form-control" id="sel2" style="width: auto; margin-bottom:15px;">
            <option value="-1" selected>Select One</option>
        </select>
    </div>
</form>
</div>
</div>

Any help would be appreciated.

SGekko
  • 335
  • 1
  • 19
  • I think your `@model` declaration in the view is incorrect. You have `@model FulfillmentPortal.Models.Carrier` but the name of the class is `CarrierModel`. Did you try changing it to `@model FulfillmentPortal.Models.CarrierModel`? – Lews Therin Apr 17 '19 at 19:49
  • Yes I did and still the same error. – SGekko Apr 17 '19 at 19:52

1 Answers1

1

The problem is that you are passing a list of carrier objects to the view.

var carrierList = db.Carriers.ToList();
return View(carrierList);

But your view accepts a single Carrier object

@model FulfillmentPortal.Models.Carrier

If you want to follow an MVC pattern:

You should create a new Viewmodel object which contains the list of Carrier objects, which you will then pass the view.

class ViewModel {
   public List<Carrier> carrierList {get; set;}
}

In your controller:

public ActionResult Index()
{
    ViewModel vm = new ViewModel();
    vm.carrierlist = db.Carriers.ToList();
    return View(vm);
}  

Your view should then accept a ViewModel object:

@model ViewModel

If you don't want to follow an MVC pattern:

Change your view to accept a list of Carrier objects

@model List<FulfillmentPortal.Models.Carrier>
zing
  • 561
  • 3
  • 12
  • Okay, I am going to ask a noobie question. Where would the new ViewModel be created? – SGekko Apr 17 '19 at 20:18
  • Where ever you'd like to create it. I'd create a new folder in your root directory called ViewModels, then create the new class in there. Just make sure that where ever you use it, you reference the path to it so the program knows where to find it. eg. "using ViewModels.ViewModel" – zing Apr 17 '19 at 20:23
  • Sure. The code on your view might need to be changed slightly to accommodate for the new ViewModel list. If I understand what you are trying to do, have a look at this [post](https://stackoverflow.com/questions/33321790/bind-dropdownlistfor-with-list-on-viewmodel) which might be similar. – zing Apr 17 '19 at 20:29
  • Thanks guys! It is working now. I am still unclear as to the reason. It was said "The problem is that you are passing a list of carrier objects to the view. But your view accepts a single Carrier object". Could you elaborate on that a bit? – SGekko Apr 17 '19 at 20:33
  • When declaring "@model ViewModel" in a view file, you are telling the view what type of object it should expect. In a controller, if you use "return View(someObject)", that object is being sent to the view. Therefore, if the object you send to the view is not the same type as the type you specified at the top of the view, it will throw the error you saw. Specifically, your "return View(carrierList)" line, was sending an object of type List, but you told the view it would receive an object of type Carrier ("@model FulfillmentPortal.Models.Carrier") – zing Apr 17 '19 at 20:39
  • Understood. Thanks again! – SGekko Apr 17 '19 at 22:02