MVC3 System.Collections.Generic.List pass the wrong model item - asp.net-mvc-3

Hello everyone I have checked my controller and view it seems there is no problem but I get System Colletion error.
Here is my controller
public ViewResult Index()
{
return View(db.banner.ToList());
}
Here is My View
{
#model IEnumerable<icerik.Models.banner>
}
And I get this error
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[icerik.Models.banner]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[icerik.Models.contents]'.

Maybe you have a partial in your main view:
#Html.Partial("SomePartial")
and this partial is strongly typed to IEnumerable<contents>:
#model IEnumerable<icerik.Models.contents>
So make sure that you are passing the correct model to this partial. If you do not specify anything to the Partial helper (as in my example) the main model will be passed to this partial.
So always specify the correct model:
#Html.Partial("SomePartial", SomeModelInstance)

Related

In partial view: "The model item passed into the dictionary is of type"

I lack understanding of some basic MVC concepts, despite all my searching.
I created an MVC project in Visual Studio, which contains the partial view _LogOnPartial.shtml. I just want to access information within the view pertaining to the user, to put in a user dropdown menu. When I try to put this at the top of the partial view cshtml page I get the above error:
#model MyProject_MVC.Models.UserRepository
When I try this I also get an error:
#Html.Partial("_LogOnPartial", MyProject_MVC.Models.UserRepository)
'MyProject_MVC.Models.UserRepository' is a 'type', which is not valid in the given context
You have to provide an instance of MyProject_MVC.Models.UserRepository to the partial view. _LogOnPartial is strongly-typed to that type. It lets you access its public members at compile time and decide how you can display it in your view.
If you want to use your own type in that view, first you have to change the type that is strongly-typed to it.
#model MyProject_MVC.Models.UserRepository
Then you have to create an instance of that type in your action method and pass it to the view as the model or a property of the model.
public ActionResult LogOn()
{
return View(new UserRepository());
}
Now you can access this instance as Model object in your view.
#Html.Partial("_LogOnPartial", Model);
#model _LogOnPartial.Models.UserRepository should probably be: #model MyProject_MVC.Models.UserRepository
and for the last part, you have to provide and instance of the type UserRepository as the second parameter, not the type itself.

Return a view from Post method

I have this post method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Invitations(SuperInvitationsEditModel model)
{
...
var newmodel = new SuperInvitationsEditModel();
if (hasErrors)
{
SuperInvitationsErrorModel newErrorModel = new SuperInvitationsErrorModel();
newErrorModel.Errors = model.Errors;
return View(newErrorModel);
}
return View(newmodel);
}
When this code in the if(hasErrors) executes I get this error.
The model item passed into the dictionary is of type 'MyProject.Models.SuperInvitationsErrorModel', but this dictionary requires a model item of type 'MyProject.Models.SuperInvitationsEditModel'.
I thought I can do this since the return value of the method is a generic ActionResult. Can anyone tell me why is this not working?
because your current view is strongly typed. change the code as
return View("yourviewname",newErrorModel);
It has nothing to do with casting ViewResult to ActionResult. The problem is, that you have strongly typed view that expects the model of type SuperInvitationsEditModel (see #model on the top of Invitations.cshtml), but you are passing the model of type SuperInvitationsErrorModel to it.
You should merge the two view model classes (SuperInvitationsEditModel and SuperInvitationsErrorModel) into one, or create a standalone view for each of them.

Binding model to view issue

I have my own model classes, which are public, but when making a view, I cannot find the model itself in the list of models to bind to. Why is this? Can I bind the model to the view somehow afterwards?
Thanks
Add the following to the top of your View:
#model your.namespace.YourModelClass
Then your controllers' action method needs to return an appropriate instance of YourModelClass:
public ActionResult Index(){
return View(new YourModelClass());
}

Pass viewmodel to ajax controller action that returns partial with that model?

I have a view that is strongly typed. Inside this view i have jqueryui tabs, that when clicked call my Controller and return a partial view
("#tab0").load('#Url.Action("ProfileImage", "User")');
public ActionResult ProfileImage()
{
return PartialView("_ProfileImage");
}
What I'd like to do is pass the model from the "parent" view to the controller which can then bind it to the partial when it is returned:
("#tab0").load('#Url.Action("ProfileImage", "User", new {model=model})');
public ActionResult ProfileImage(UserViewModel model)
{
return PartialView("_ProfileImage", model);
}
Is this possible? how is this normally done? Where you have the model data in one view and you'd like to pass it to a asynchronously loaded partial view?
You could create a ToJson method on your viewmodel, which could be something like this:
public IHtmlString ToJson()
{
return MvcHtmlString.Create(Json.Encode(this));
}
It just serializes the viewmodel into a json. The IHtmlString returntype makes sure the output isn't encoded in your view.
The call to your controller would be something like this:
("#tab0").load('#Url.Action("ProfileImage", "User", new {model=model.ToJson()})');
The json modelbinder can recreate the viewmodel on the serverside. You probably run into some problems along the way, but nothing unsolvable I guess.

Using one Partial View Multiple times on the same Parent View

I am using MVC3 razor. I have a scenario where I have to use a partial view multiple times on the same parent view. The problem I am having is that when the Parent View gets rendered, it generates same names and ids of the input controls within those partial views. Since my partial views are binded to different models, when the view is posted back on "Save" it crashes. Any idea how can i make the control id/names unique, probably some how prefix them ?
Awaiting
Nabeel
Personally I prefer using editor templates, as they take care of this. For example you could have the following view model:
public class MyViewModel
{
public ChildViewModel Child1 { get; set; }
public ChildViewModel Child2 { get; set; }
}
public class ChildViewModel
{
public string Foo { get; set; }
}
and the following controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
Child1 = new ChildViewModel(),
Child2 = new ChildViewModel(),
};
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return View(model);
}
}
and inside the Index.cshtml view:
#model MyViewModel
#using (Html.BeginForm())
{
<h3>Child1</h3>
#Html.EditorFor(x => x.Child1)
<h3>Child2</h3>
#Html.EditorFor(x => x.Child2)
<input type="submit" value="OK" />
}
and the last part is the editor template (~/Views/Home/EditorTemplates/ChildViewModel.cshtml):
#model ChildViewModel
#Html.LabelFor(x => x.Foo)
#Html.EditorFor(x => x.Foo)
Using the EditorFor you can include the template for different properties of your main view model and correct names/ids will be generated. In addition to this you will get your view model properly populated in the POST action.
There is an alternative:
Add a prefix to the PartialView
Bind the model, removing the prefix
For 1, set the prefix in your View:
ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = "prefix";
For 2, you can recover the data with UpdateModel, like this:
UpdateModel(producto, "prefix");
This is not very advisable because your action doesn't receive the data as a parameter, but updates the model later. This has several inconvenients: 1) it's not clear what your action needs by looking at its signature 2) it's not easy to provide the input to the action for unit testing it 3) the action is vulnerable to overflow parameters (parameters provided by the user that shouldn't be there and are mapped to the model).
However, for 2 there is an alternative: register a custom Model Binder that allows you to do remove the prefix. And the custom Model Binder must know about it.
A good solution is in this SO Q&A: How to handle MVC model binding prefix with same form repeated for each row of a collection? But it has a little flaw: if you add a hidden field with the name "__prefix" in a partial view, and you render it several times as a partial view, this ID will be repeated for several different elements in the page, which is not allowed, and can provoke some trouble. And one of the most important reasons to provide a prefix is precisely rendering the same "edit" view as partial views for several instances of an entity. I.e. this would happen in a page like gmail, where you can edit several emails at once.
There are several possible solutions for this problem.
One of them is providing the prefix as a query string or routedata value, and not as a form field, which avoid the Id conflicts, and can be found by the model binder. (It can always have the same name).
Another solution is to use a hidden field, with a fixed pattern, but which is different for every rendered view. The prefix could follow this pattern for uniqueness: "PP$ActionControllerId" like "PP$EditProduct23", which is unique for each rendered view, and can be easily found between the request parameters looking for one that starts with "PP$".
And a final solution would be to create the prefix only in the view, and not providing it in any kind of request parameter. The Model binder would have to look for the prefix examining the names of the request parameters, until it finds one whose prefix follow the pattern.
Of course, the custom ModelBinder must be adapted to work tieh the chosen convention.

Resources