0

I am pretty new in .NET and C# (I came from Java and Spring framework) and I have some problem following a tutorial.

I have this simple controller class:

namespace Vidly.Controllers
{
    public class CustomersController : Controller
    {
        public ViewResult Index()
        {
            var customers = GetCustomers();

            return View(customers);
        }

        public ActionResult Details(int id)
        {
            System.Diagnostics.Debug.WriteLine("Into Details()");
            var customer = GetCustomers().SingleOrDefault(c => c.Id == id);
            System.Diagnostics.Debug.WriteLine("customer: " + customer.Id + " " + customer.Name);

            if (customer == null)
                return HttpNotFound();

            return View(customer);
        }

        private IEnumerable<Customer> GetCustomers()
        {
            return new List<Customer>
            {
                new Customer { Id = 1, Name = "John Smith" },
                new Customer { Id = 2, Name = "Mary Williams" }
            };
        }
    }
}

As you can see this class contains this Details(int id) method:

public ActionResult Details(int id)
{
    System.Diagnostics.Debug.WriteLine("Into Details()");
    var customer = GetCustomers().SingleOrDefault(c => c.Id == id);
    System.Diagnostics.Debug.WriteLine("customer: " + customer.Id + " " + customer.Name);

    if (customer == null)
        return HttpNotFound();

    return View(customer);
}

So, this method handle HTTP request of type GET toward URL like:

localhost:62144/Customers/Details/1

and it seems to work because into the output console I obtain the Into Details() log. Also the other log explains that the customer model object is correctly initialized, infact I obtain this console output:

customer: 1 John Smith

Then the controller reuturn a ViewResult object (calling the View method) containinf the previous model object.

I think that .NET automatically try to send this ViewResult object (that contains the model) to a view having the same name of the controller method that handle this request. So I have this Details.cshtml view:

@model Vidly.Models.Customer

@{
    ViewBag.Title = Model.Name;
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>@Model.Name</h2>

that in theory should receive this ViewResult object, from here extract the model object (having Vidly.Models.Customer as type) and it should print the value of the Name property of this model object.

The problem is that I am obtaining this excepetion istead the expected page with the expected data:

[InvalidOperationException: The model item passed into the dictionary is of type 'Vidly.Models.Customer', but this dictionary requires a model item of type 'Vidly.ViewModels.RandomMovieViewModel'.]

Why? What it means?

Vidly.ViewModels.RandomMovieViewModel is another model object used into another controller and another view.

What is the problem? What am I missing? How can I fix this issue?

AndreaNobili
  • 40,955
  • 107
  • 324
  • 596
  • Because what you pass as argument is of the wrong (derived) type. Usually you try to pick the Function arguments so that only the right type can be given. That way the compiler can do the checks for you before you even hit "compile". But that is not always possible. And if that is not possible, you have to do some `is` checks on what you got instead. And if that is not to your liking, you have to throw a Exception. – Christopher Oct 20 '18 at 15:47
  • @Christopher mmm I suspect that I have not get your point... – AndreaNobili Oct 20 '18 at 15:51
  • I seriously do not get what you could not understand here. The check `Vidly.Models.Customer is Vidly.ViewModels.RandomMovieViewModel` returns false. And if returns false, the line `throw new InvalidOperationException("The model item passed into the dictionary is of type 'Vidly.Models.Customer', but this dictionary requires a model item of type 'Vidly.ViewModels.RandomMovieViewModel'");` is run. The Java Equivalents are "IllegalStateException" and "UnsuportedOperationException": https://stackoverflow.com/a/3381332/3346583 – Christopher Oct 20 '18 at 15:54
  • @Christopher where\who perform this check? I can't see it in my code – AndreaNobili Oct 20 '18 at 16:02
  • Sorry, but if you do not know what Exceptions are and how they work it is half a year to early for you to do this kind of programming work (wich seems to be learning the MVVM pattern). Indeed even your claims that you Programmed in Java seem unlikely a best. I can give you some articles on Exception Handling, but I think you have to start with a basic Toutorial here. https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/ | https://www.codeproject.com/Articles/9538/Exception-Handling-Best-Practices-in-NET – Christopher Oct 20 '18 at 16:51
  • 2
    @AndreaNobili Is your `Details.cshtml` file is located inside `Views/Customers` directory? It looks like MVC engine is picking up wrong view file. – Mohsin Mehmood Oct 20 '18 at 16:55
  • @MohsinMehmood yes the Details.cshtml file is located into the Views/Customers directory. Also I was thinking that it seems that it is picking the wrong view that needs another model object (because it seems that it is pointing to the Views/Movies/Random.cshtml view that expects the RandomMovieViewModel objets...but the view seems to be in the correct place – AndreaNobili Oct 20 '18 at 17:05
  • @AndreaNobili Do you have any other `Details.cshtml` file in Views folder hierarchy? One quick test can be to remove the `Details.cshtml` from `Views/Customers` directory and see if you get the same error. If yes, it will confirm that rendering engine is picking up wrong view file – Mohsin Mehmood Oct 20 '18 at 17:08
  • @MohsinMehmood no this is the only Details.cshtml file that I have in my project. – AndreaNobili Oct 20 '18 at 17:13
  • @MohsinMehmood it seems a view resolution problem, infact changing the return to a simple return Content(customer.Name); it returns the correct content without the view. It is finding problem with this stupid view – AndreaNobili Oct 20 '18 at 17:21
  • @AndreaNobili If you explicitly specify view using its path e.g. `View("~/Views/Customers/Details.cshtml", model)` does that work? – Mohsin Mehmood Oct 20 '18 at 17:32
  • @MohsinMehmood no, same error – AndreaNobili Oct 20 '18 at 17:49
  • 1
    @AndreaNobili Does your _Layout.cshtml renders Movie view which requires `RandomMovieViewModel`? Or if your Details view is partially renderning that movies view? – Mohsin Mehmood Oct 20 '18 at 18:03
  • @MohsinMehmood actually the _Layout.cshtml start with the model Vidly.ViewModels.RandomMovieViewModel statment – AndreaNobili Oct 20 '18 at 18:34
  • 1
    @AndreaNobili and that could be the reason. Do you need that model declaration inside _Layout.cshtml? Remove that model declaration and you will be set – Mohsin Mehmood Oct 20 '18 at 18:35
  • @MohsinMehmood removing this statment that refers to the RandomMovieViewModel from the _Layout.cshtml page (I don't know why the author of the tutorial put it here because it is unused in this payout page) it works fine. In fact it makes sense but I had not thought about looking for them because I did not expect it. If you create a response I will accept, tnx – AndreaNobili Oct 20 '18 at 18:37
  • @Christopher Anyway...I worked as Java developer for 5 years. I am Spring framework certified. I am absolutly not into .NET but I know pretty well what an exception is and what was the meaning of this exception (also because the message was pretty clear). You were not very polite, indeed you were pretty arrogant but above all you did not fully understand my question and my problem. You only criticized my skill without centering the core of the problem and without providing a possible solution...this is not nice – AndreaNobili Oct 20 '18 at 19:00

1 Answers1

1

This error was appearing due to Vidly.ViewModels.RandomMovieViewModel model declaration in _Layout.cshtml file.

Declaring a model inside layout view means that all views that are using layout view must either use that model class or a class that derives from that layout view model class

Mohsin Mehmood
  • 4,156
  • 2
  • 12
  • 18