I have two view models:
public class ParentViewModel
{
public Id { get; set; }
.....
public ChildViewModel Child{ get; set; }
}
public class ChildViewModel
{
public ChildId { get; set; }
.....
}
Controllers:
public ActionResult Index()
{
.... <some code>
return View("NewIndex", ParentViewModel);
}
[HttpPost]
public ActionResult PartialAction(ChildViewModel childView)
{
return RedirectToAction("Index");
}
And views:
Index
#model ParentViewModel
....
#Html.Partial("_Partial", Model.Child)
and _Partial
#model ChildViewModel
... do some stuff with child model
When I'm trying to open Index page I've got an error:
The model item passed into the dictionary is of type 'ParentViewModel', but this dictionary requires a model item of type 'ChildViewModel'.
Why it tries to pass ParentViewModel instead of ChildViewModel. What I'm doing wrong?
I had the same issue as the OP. From one of the comments, I realized that the second parameter shouldn't be null, i.e from
#model ParentViewModel
#Html.Partial("_Partial", Model.Child)
If Model.Child is null, then Model is passed instead of Model.Child. If there will be cases when the second parameter is null, then you will have to check first in your code and maybe pass an initialized Child as the second parameter. Something like this
#Html.Partial("_Partial", new Child())
The answer is that needs to pass an empty object to Partial, like
#Html.Partial("_Partial", new ChildViewModel ())
You could return PartialView("...") from a Controller instead, and call the action from the Index view.
Controllers:
public ActionResult Index()
{
.... <some code>
return View("NewIndex", ParentViewModel);
}
public ActionResult Partial(ChildViewModel cvm)
{
var vm = cvm ?? new ChildViewModel(); //if cvm from the parent view is null, return new cvm
return PartialView("_Partial", vm) //return partial view
}
[HttpPost]
public ActionResult PartialAction(ChildViewModel childView)
{
return RedirectToAction("Index");
}
And Index
#model ParentViewModel
....
#Html.Action("Partial", Model.Child)
Alternatively, you could initialize ParentViewModel in the Index()
public ActionResult Index()
{
.... <some code>
return View("NewIndex", new ParentViewModel{Child = new ChildViewModel});
}
Related
I want to pass more than one object in the view. I have two object. One name is "Caller" and one Name is "Receiver". I am new in MVC. This is my action method.
public ActionResult IsActiveCaller(int id)
{
var caller = new CallerService().getCallerById(id);
if(caller.active)
{
var reciver= new reciverService().getReviverTime(caller.dialNo);
return (caller ) // here i also want to send reciver to view
}
return View();
}
Is there any way to send more than object in view?
Yes you can do this. There are multiple ways to do this.
1) You can use viewBag to pass the data or object into view.
You can see here to see how to use viewBag in mvc
2) you can use ViewData but it is not a good approach.
3) you can make ViewModel like as below (recomended)
public class callerReciver
{
public Caller caller {set;get;}
pblic Reciver eciver {set;get;}
}
Now pass callerReciver to view.You can access both object.hope you will understand.
4) Another way is to use partial view.You can make partial view to use more than one object in same view.
You can use a View Model:
public class MyViewModel
{
public Caller Caller { get; set; }
public Receiver Receiver { get; set; }
}
Then you can populate the view model this way:
public ActionResult IsActiveCaller(int id)
{
var caller = new CallerService().getCallerById(id);
var vm = new MyViewModel {
Caller = caller
};
vm.Receiver = caller.active ? new reciverService().getReviverTime(caller.dialNo) : null;
return View(vm);
}
View:
#model MyViewModel
<h1>#Model.Caller.Title</h1>
#if(Model.Receiver != null) {
<h1>#Model.Receiver.Title</h1>
}
The cleanest way is to pass by a view model :
ViewModel
public class MyViewModel {
public Caller MyCaller { get;set; }
public Receiver MyReceiver { get;set; }
}
Controller
public ActionResult IsActiveCaller(int id)
{
var caller = new CallerService().getCallerById(id);
var viewModel = new MyViewModel();
viewModel.MyCaller = caller;
if(caller.active)
{
var reciver= new reciverService().getReviverTime(caller.dialNo);
viewModel.MyReceiver = reciver;
}
return View(viewModel);
}
View
#model MyViewModel
<h1>#Model.MyCaller.Id</h1>
<h1>#Model.MyReceiver.Id</h1>
How can I call and render a view of controller from action of another controller.
I have this, an action of Product Controller :
public ActionResult SortedLists(List<string> items, string ShopID)
{
//Do sth...
db.SaveChanges();
return RedirectToAction("Index", "ControlPanel", new { ID = ShopID });
}
And Index is the action(view) of ControlPanel Controller :
public ActionResult Index(int ID)
{
ViewBag.theRelatedShopID = ID;
return View();
}
How can I render Index and display it in browser???
public ActionResult SortedLists(List<string> items, string ShopID)
{
//Do sth...
db.SaveChanges();
return View("~/ControlPanel/Index.cshtml", (object)ShopID);
}
Here we are passing the ShopId as model to the Index view. If this view is strongly typed to some model you should pass this model:
MyViewModel model = ...
return View("~/ControlPanel/Index.cshtml", model);
My question is about binding in MVC. Could you please help me with it?
My controller:
public class TestController : Controller
{
//
// GET: /Test/
[HttpGet]
public ActionResult Index()
{
return View(new TestModel());
}
public ActionResult Index(TestModel test)
{
return View(test);
}
}
My View:
#model MvcApplication1.Models.TestModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(x => x.test) // or x.Test
<input type="submit" value="Set"/>
}
My model:
public class TestModel
{
public string test { get; set; } // or Test{get;set;}
}
The problem is connected with the name of parameter "test" in controller as I understand. I have just changed it to "model" and the binding is working. But it is not working in original state (the name of parameter is 'test'), 'test' parameter is null.
Please give me understand why the binding is not working in current example. Thank you a lot!
You need an [HttpPost] attribute on your second method. You also cannot use test as your variable name, as it is the same name as the property of the class you're attempting to bind to; the ModelBinder fails to determine which to use. Your code would look as follows:
public class TestController : Controller
{
//
// GET: /Test/
[HttpGet]
public ActionResult Index()
{
return View(new TestModel());
}
//
// POST: /Test/
[HttpPost]
public ActionResult Index(TestModel testModel)
{
return View(testModel);
}
}
I have a problem with DropDownlist in MVC
I use ModelView in my application and this is my code
namespace MedicallexiconProject.ViewModel
{
public class WordViewModel
{
private readonly ICategoryService _categoryService;
public WordViewModel(ICategoryService categoryService)
{
_categoryService = categoryService;
var selectList = _categoryService.GetAllCategorysSelectList().
Select(x => new SelectListItem
{
Text = x.Name,
Value = x.ID.ToString()
}).ToList();
Categories = selectList;
}
public WordViewModel()
{
}
public string Name { get; set; }
private IList<SelectListItem> _categories;
public IList<SelectListItem> Categories
{
get
{
if (_categories == null)
{
_categories = new List<SelectListItem>();
}
return (_categories);
}
set { _categories = value; }
}
}
}
and this is my controller
[HttpGet]
public ActionResult Create()
{
var wordViewModel = new WordViewModel(_categoryService);
ViewBag.CategoryID = wordViewModel.Categories;
return View();
}
[HttpPost]
public ActionResult Create(WordViewModel wordViewModel)
{
Mapper.CreateMap<WordViewModel, Word>();
var word = new Word();
Mapper.Map(wordViewModel, word);
if (ModelState.IsValid)
{
_wordService.AddNewWord(word);
_uow.SaveChanges();
return RedirectToAction("Index");
}
return View(wordViewModel);
}
Now how can I insert dropdownlist in my View?
As AlfalfaStrange mentioned, you should not add logic in your ViewModel. That makes it ugly ! Keep your ViewModel simple POCO.
Add one more property in your ViewModel called "SelectedCategoryID" like this
public class WordViewModel
{
public int SelectedCategoryID { set;get;}
public IList<SelectListItem> Categories { set;get;}
public string Name { set;get;}
}
Initialize your Items (Categories) of your ViewModel in your GET method. Here i am calling a method called GetCategories which returns a list of categories.I can simply call the method wherever i want.
public ActionResult Create()
{
var model=new WordViewModel();
model.Categories=YourService.GetCategories();
return View(model);
}
In your strongly typed Create view , use this
#model WordViewModel
using(#Html.BeginForm())
{
#Html.DropDownFor(x=>x.SelectedCategoryID,
new SelectList(Model.Categories,"Value","Text"),"Select Category")
<input type="submit" value="Save" />
}
In your HttpPost action method , you can check for wordViewModel.SelectedCategoryID for the selected value.
[HttpPost]
public ActionResult Create(WordViewModel wordViewModel)
{
if(ModelState.IsValid)
{
//Checck for wordViewModel.SelectedCategoryID here now
}
//some validation failed. Let's reload the category data again.
wordViewModel.Categories=YourService.GetCategories();
return View(wordViewModel);
}
It's absolutely fine to include code that loads a dropdown list in your view model. A select list and a drop down are both "view" items.... they are not related to business logic and your controller and model need not know anything about SelectLists or SelectListItems or DropDownList, etc.
I can't figure out what's going on with this error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[RepositoryExample.Employee]', but this dictionary requires a model item of type 'RepositoryExample.Models.IEmployeeManagerRepository'.`
I get the error when I go to the Index view. I added the Index View from the controller but there is no code in it. I'm using Linq to SQL.
#model RepositoryExample.Models.IEmployeeManagerRepository
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
This is my code:
EmployeeController.cs
// GET: /Employee/
public ActionResult Index()
{
return View(_repository.ListEmployees());
}
LinqEmployeeManagerRepository.cs
public class LinqEmployeeManagerRepository: RepositoryExample.Models.IEmployeeManagerRepository
{
private DeptDirectoryDataClassesDataContext _db = new DeptDirectoryDataClassesDataContext();
public Employee GetEmployee(string UserName)
{
return (from e in _db.Employees where e.UserName == UserName select e).FirstOrDefault();
}
public IEnumerable<Employee> ListEmployees()
{
return _db.Employees.ToList();
}
public Employee CreateEmployee(Employee employeeToCreate)
{
_db.Employees.InsertOnSubmit(employeeToCreate);
_db.SubmitChanges();
return employeeToCreate;
}
public Employee EditEmployee(Employee employeeToEdit)
{
var OriginalEmployee = GetEmployee(employeeToEdit.UserName);
_db.Employees.Attach(employeeToEdit, OriginalEmployee);
_db.SubmitChanges();
return employeeToEdit;
}
public void DeleteEmployee(Employee employeeToDelete)
{
var OriginalEmployee = GetEmployee(employeeToDelete.UserName);
_db.Employees.DeleteOnSubmit(OriginalEmployee);
_db.SubmitChanges();
}
}
IEmployeeManagerRepository.cs
namespace RepositoryExample.Models
{
public interface IEmployeeManagerRepository
{
Employee CreateEmployee(Employee employeeToCreate);
void DeleteEmployee(Employee employeeToDelete);
Employee EditEmployee(Employee employeeToUpdate);
Employee GetEmployee(string UserName);
IEnumerable<Employee> ListEmployees();
}
}
Any ideas what I'm doing wrong? I'm trying to follow the example on Repository pattern in this tutorial: http://www.asp.net/mvc/tutorials/iteration-4-make-the-application-loosely-coupled-cs.
In the top of your Index.cshtml view replace:
#model RepositoryExample.Models.IEmployeeManagerRepository
with:
#model IEnumerable<RepositoryExample.Employee>
The _repository.ListEmployees() method returns IEnumerable<Employee> and that's what you are passing to the view here:
return View(_repository.ListEmployees());
So that's the type you should be using in the #model directive in your view.