MVC4 Incorrect model error - asp.net

Hi I getting this error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[DBModel.Telemarketing]', but this dictionary requires a model item of type 'TWeb.Models.LoginModel'
In _Layout.cshtml file i have
#Html.Partial("_LoginPartial")
this partial login view is rendered in div on _layout page (it`s hides/shows with javaScripts )
#model TWeb.Models.LoginModel
Then I have "Telemarketings" controller having view:
public class TelemarketingController : Controller
{
private Entities db = new Entities();
//
// GET: /Telemarketing/
public ActionResult Index()
{
return View(db.Telemarketings.ToList());
}
When I click link in _Layout page
#Html.ActionLink("Telemarketingas", "Index", "Telemarketing", new{area="" },new{ })
It throws an error written in top of the post.
I am new in MVC, please help me.

problem 1) Your Partial requires a model, and you're not passing one.
proper syntax: #Html.Partial("_LoginPartial", Model.LoginModel)
problem 2) _layout, as far as I know, can't have a Model passed
Solution 1:
Use an ActionPartial. AcionPartials are called similarly,
#Html.Action("/Tools/_LoginPartial").
The difference is they have an ActionMethod Associated which can return a Model
public ActionResult _LoginPartial()
{
LoginModel Model= new LoginModel();
//populate Model from whatever
return View(Model);
}
Option 2:
Pass a LoginModel object to a Viewbag
Viewbag.LoginModel = new LoginModel();
and reference the Viewbag in your _layout's Partial
#Html.Partial("_LoginPartial", Viewbag.LoginModel)

Your "_LoginPartial" expects "LoginModel" model, but since you're not giving it any, Razor engine sets its model to the current view model ("db.Telemarketings.ToList()").
All you have to do is somehow set its model, probably like so:
#Html.Partial("_LoginPartial", new LoginModel())

Simplest way was to remove model declaration from Login Div :).

You can use this code
#Html.Partial("Partial page", new ModelFroLogin())

Related

Can I pass both the ViewBag AND a Model to a View

Can I use a hybrid approach that passes information in the ViewBag (C#) / ViewData (VB) but also includes a model
For example, I started passing a simple title through an error controller to an error view:
Function NotFound() As ActionResult
Response.StatusCode = 404
ViewData.Add("Title", "404 Error")
Return View("Error")
End Function
This worked fine and the View had access to the property #ViewData("Title")
Then I wanted to include some of the exception information that is automatically routed by Custom Errors in the HandleErrorInfo object like this:
Function NotFound(exception As HandleErrorInfo) As ActionResult
Response.StatusCode = 404
ViewData.Add("Title", "404 Error")
ViewData.Add("Message", "Sorry, the requested page could not be found.")
Return View("Error", exception)
End Function
Then, on the View, I declared a Model like this:
#ModelType System.Web.Mvc.HandleErrorInfo
Now I can access properties like #Model.Exception.Message but my #ViewData("Title") has disappeared.
The WebViewPage(Of TModel) still has a ViewData property, but it looks like I can't pass anything to it from the controller unless it's explicitly in the model.
Of course, as a workaround, I could create a base class that can strongly type storage for each object, but that seems a little heavy handed when all I want to pass in through the ViewBag is the title.
Is there a way to use both ViewBag AND the Model at the same time?
What was happening in this case was that when the CustomErrors tried to route to the NotFound action on the Error controller, it could only supply the default constructor. Not finding one, it bypassed the controller altogether and went directly to the error page which already had the model it wanted to pass ready.
As a small Proof of Concept, passing both parameters is definitely possible as evidenced by this example
TestModel.vb:
Public Class TestModel
Public Property ModelInfo As String
End Class
TestController.vb:
Public Class TestController : Inherits System.Web.Mvc.Controller
Function Index() As ActionResult
Dim model As New TestModel With {.ModelInfo = "Hello"}
ViewData("ViewDataInfo") = "World"
Return View("Index", model)
End Function
End Class
Test\Index.vbhtml:
#ModelType TestModel
#Model.ModelInfo #ViewData("ViewDataInfo")

Basic ASP.NET MVC query with parameter

I am new in ASP.Net MVC and MVC architecture in general. I'm building a simple application using the Database Code First method.
I have a Recipe Model with a property called cookId which is the id of the user who created the recipe.
Now I want to be able to pass a querystring to my page and get ONLY the recipes where the cookId is the same as the parameter and list i on my View.
How can I achieve this? Where should i put this logic? In my controller or in my view?
Well, asp.net mvc works with routes, or TableRoutes. The default routes is created with this format: {controller}/{action}/{id}.
So, when you get a request on your action, you could retrive this id from id parameter on your Action (at controller) and use this value to hit on your database and get all records you need to show on the View. You could try something liek this:
public ActionResult Recipes(string id)
{
IEnumerable<Recipe> list = _repository.GetRecipeByCookId(id); // this method should return list of Recipes
return View(list); // return your View called "Recipes" passing your list
}
You also could use Request.QueryString["Id"] to get the Id, but it is not a good pratice in asp.net mvc. You can use parameters on your action and use it.
On your View, you could type it with the IEnumerable<Recipe> and show it on a table, something like:
#model IEnumerable<Recipe>
<table>
#foreach(var recipe in Model)
{
<tr>
<td>#recipe.Name</td>
<td>#recipe.CookId</td>
<td>#recipe.OtherProperties</td>
</tr>
}
</table>
To create an link passing this id for the request, you could just use Html.ActionLink, something like on your View:
#Html.ActionLink("Text of You Link", "Action", "Controller", new { id = 5, another = 10 }, new { #class = "css class for you link" });
and asp.net mvc will render an a tag with a apropriated route following routetable setted on global.asax. If you have other parameters to pass in querystring, you also could add it like I did on sample with another parameter.
NEVER put logic in the view. The view should simply display the information provided in the model. Put the logic in the controller.
Controller:
[HttpGet]
public ActionResult Recipes(int cookId)
{
var recipes = /* get recipes based on cook */;
List<RecipeModel> model = recipes
.Select(r => new RecipeModel
{
Id = r.Id,
CookId = r.CookId,
...
})
.ToList();
return View(model);
}
View:
#model List<RecipeModel>
#foreach (RecipeModel item in Model)
{
<div>
<span>Id:</span>
<span>#item.Id</span>
</div>
}
Controller:
[HttpGet]
public ActionResult GetRecipes(int cookId)
{
// model can view a List<Recipe>, logic goes here
var model = SomeQueryThatReturnsRecipesFrom(cookId);
return View(model)
}
View (for example views\yourController\GetRecipes.cshtml), only use this file to show data, its not recommendend to put logic here:
#model List<Namespace.Recipe>
<h2>Recipes</h2>
#foreach(var r in Model)
{
<p>r.Name</p>
}
This will be called with the following querystring:
/Recipes/GetRecipes?cookId=SomeId
You might have a CooksController. That controller would return a list of cooks. That list might include a link for the cook's recipes. Your RecipesController could handle the request for all recipes for a given cookId.
#Html.ActionLink("Recipes", "RecipesByCook", "Recipes", new { cookId = model.cookId }, null};
The above code is used in the view Cooks/Index.shtml. It creates a link that uses the query string to identify the cookId like you want.
The RecipesController would then have a method RecipiesByCook which takes a parameter for the cookId. This method will handle requests for URLs like this, Home/Recipies/RecipeByCook?cookId=4.
Your RecipesController can then return an ActionResult with the correct set of recipes to show. Very simply (as in you may want to add more for the view to show, like information about the cook):
public ActionResult RecipesByCook(int cookId)
{
var recipes = repository.Recipes.Where(r => r.cookId == cookId);
return View(recipes);
}

How should I auto-fill the Html.EditorFor with a value in ASP.Net MVC3?

I'm just taking a look at ASP.Net MVC3 and in one of the auto-generated views for Create, it uses "Html.EditorFor(model => model.User)" to provide a text box for the user to enter their username. Ideally, I would auto-populate this with #User.Identity.Name.
What is the correct way to achieve this? Does Html.EditorFor allow me to automatically populate it in the view, or should I be setting that at the controller when passing it in?
I've found that if I change the Create method in the controller from this:
public ActionResult Create()
{
return View();
}
To this:
public ActionResult Create()
{
MyObject myobject = new MyObject();
myobject.User = User.Identity.Name;
return View(myobject);
}
This seems to work. Is this the correct way to do this?
Thanks in advance for any confirmation that I'm doing this right.
Absolutely, the assignment is fine.
This is absolutely the correct way. You define a view model (MyObject) containing the User string property, then have your controller action instantiate and populate this model and finally pass the view model to the view for displaying. It is also easy to unit test because the User.Identity property on the controller is an abstraction that could be mocked.
its a good way in this case, but if you bild a big project it's better to create a global model class where you will put all your models, not in controller.

Is it possible to pass my model which I used in a view back to my controller in MVC3?

In my QuestionModel I have:
private List<QuestionModel> _questionList = new List<QuestionModel>();
Which I use in my view:
//GetQuestionList returns the _questionList
foreach (var item in Model.GetQuestionList()){...}
I want to acces my model in the controller when I submit my form in the view.
I have tried to add the model as a parameter in de controller function like:
public ActionResult SaveData(QuestionModel model){}
But I get nothing in it
So my question is, is it possible and how to do it?
You will need to bind back to the type of Model and use a for loop not a for each loop in your view.

ASP.NET MVC: How to transfer more than one object to View method?

I finished NerdDinner tutorial and now I'm playing a bit with project.
Index page shows all upcoming dinners:
public ActionResult Index()
{
var dinners = dinnerRepository.FindUpComingDinners().ToList();
return View(dinners);
}
In DinnerRepository class I have method FindAllDinners and I would like to add to above Index method number of all dinners, something like this:
public ActionResult Index()
{
var dinners = dinnerRepository.FindUpComingDinners().ToList();
var numberOfAllDinners = dinnerRepository.FindAllDinners().Count();
return View(dinners, numberOfAllDinners);
}
Of course, this doesn't work. As I'm pretty new to OOP I would need help with this one.
Thanks,
Ile
Create view model:
public class DinnerViewModel
{
public List<Dinner> Dinners { get; set; }
public int NumberOfAllDinners { get; set; }
}
public ActionResult Index()
{
var dinners = dinnerRepository.FindUpComingDinners().ToList();
var numberOfAllDinners = dinnerRepository.FindAllDinners().Count();
return View(new DinnerViewModel { Dinners = dinners, NumberOfAllDinners = numberOfAllDinners } );
}
You need to create a "wrapper" object that contains the objects you wish to pass as public properties of it. For instance, create an object called DinnerViewModel and give it two properties and set these with two properties, one a List called Dinners and one an int called DinnerCount. Then pass the DinnerViewModel to the view and you can then access Model.Dinners and Model.DinnerCount
In your case I would prefer the solution mentioned by LukLed.
In general you could of course also transfer multiple values from your controller to your view using ViewData:
ViewData["dinners"] = dinners;
ViewData["numberOfAllDinners"] = 150;
...
For more information also take a look at this link.
Just simply use dinners.Count property instead.
Remember, you start off using the ViewData inherts in you .aspx filesand returning the same in you return statements. Because of that, I figure that it was an issue with the Inherits attribute on the top of the ASP.NET files. But, if you are getting the error when trying to create or edit a new Dinner when you are on the 'Upcoming Dinners' page (generated from the Details.aspx and the LINQ file that gets all Dinners that are after todays date), go into your 'Controllers' directory, specifically the DinnerController.cs. Then look at the Edit and or Create methods. the answer lies right here. If you put breakpoints on these methods, you should be able to figure it out. If not, continue reading:
Look where it fails, the 'return...' line. Maybe I am the only person who forgot to change this, but my error is the same as people are getting in this page and this os how I fixed it.....the 'return(dinner)' line, in Create and Edit (and any others that you are having issues with), they are using the NerDinner.Model.Dinner / ViewData method. However, if you change it to the ViewModel return method instead, it should fix it, For example: 'return(new DinnerFormViewModel(dinner));', it should work for you. I hope this helps, as it was what my issue was. Just a simple overlook.

Resources