Consider the two views. Which is preferred and what is a situation where you would use style 1 and not style 2 and vice versa?
Style 1 : View Injection
using System.Web.Mvc;
using Ninject;
namespace Views.Models.ViewClasses {
public abstract class CalculatorView : WebViewPage {
[Inject]
public ICalculator Calulator { get; set; }
}
}
And the view:
#inherits Views.Models.ViewClasses.CalculatorView
#{
ViewBag.Title = "Calculate";
}
<h4>Calculate</h4>
The calculation result for #ViewBag.X and #ViewBag.Y is #Calulator.Sum(ViewBag.X, ViewBag.Y)
Style 2: Using a Model
public class CalculatorModel {
// a constructor in here somewhere
public int X { get; set; }
public int Y { get; set; }
public int SumXY { get; set; }
}
The Controller:
public class CalculatorController : Controller {
private readonly ICalculator _calculator;
[Inject]
public CalculatorController (ICalculator calculator) {
_calculator = calculator;
}
public ActionResult Calculate(int x, int y)
{
return View(new CalculatorModel(x, y, _calculator.Sum(x, y))
}
...
The view:
#model CalculatorModel
#{
ViewBag.Title = "Calculate";
}
<h4>Calculate</h4>
The calculation result for #Model.X and #Model.Y is Model.SumXY
All I can really think of is:
If the calculator or whatever needs to be used a lot in the view, then view injection makes more sense as otherwise the model would have loads and loads of data otherwise models should be preferred?
Related
I have a MVC3 app with the following model
public class Class1
{
public List<Class2> Class2Data { get; set; }
}
public class Class2
{
public int Id { get; set; }
public IEnumerable<Class3> Class3Data { get; set; }
}
public class Class3
{
public int Id { get set; }
public bool Selected { get; set; }
}
In my razor model
for (var i = 0; i < Model.Class2Data.Count();i++)
{
#Html.HiddenFor(c => c.Class2Data[i].Id)
foreach (var n in Model.Class2Data[i].Class3Data.ToList())
{
#Html.CheckBoxFor(x=> n.Selected);
#Html.HiddenFor(x=> n.Id);
}
}
However, when iam posting this to my controller, the Class3Data count is always 0 when I tick the checkboxes. Any ideas? Thanks
Resolved by changing IEnumerable to List as wasn't binding properly
Could I have more models on a razor page?
for example when I have more grid controls each with an area(a template) for editing the data,and after that i want to save the data and see it in the grid.
You can do something like the example below (this is a very over simplified example):
public class AnimalDataViewModel
{
public List<Dog> DogData { get; set; }
public List<Cat> CatData { get; set; }
public List<Mouse> MouseData { get; set; }
public AnimalDataViewModel()
{
this.DogData = new List<Dog>();
this.CatData = new List<Cat>();
this.MouseData = new List<Mouse>();
}
}
Then in your action method:
public ActionResult DisplayAnimalDataGrids()
{
AnimalDataViewModel model = new AnimalDataViewModel();
model.DogData = this.myDataService.GetDogData();
model.CatData = this.myDataService.GetCatData();
model.MouseData = this.myDataService.GetMouseData();
return View(model);
}
Then in your view:
#model AnimalDataViewModel
#Html.Grid(Model.DogData)
#Html.Grid(Model.CatData)
#Html.Grid(Model.MouseData)
I am trying to update a compound page model which as one of its properties has a list of objects.
My Model looks like this:
public class PageViewModel
{
public ProgramListVM ProgramsDDL { get; set; }
public PageViewModel()
{
this.ProgramsDDL = new ProgramListVM();
}
}
The ProgramListVM class is:
public class ProgramListVM
{
public List<ProgramVM> Program_List { get; set; }
public int SelectedValue { get; set; }
public ProgramListVM()
{
this.Program_List = new List<ProgramVM>();
this.SelectedValue = 0;
}
}
and ProgramVM is:
public class ProgramVM
{
public int ProgramID { get; set; }
public string ProgramDesc { get; set; }
public ProgramVM(int id, string code)
{
this.ProgramID = id;
this.ProgramDesc = code;
}
}
I try to render this dropdownlist by the following two:
1-
<%: Html.DropDownList("ProgramsDDL", new SelectList(Model.Page6VM.ProgramsDDL.Program_List, "ProgramID", "ProgramDesc", Model.Page6VM.ProgramsDDL.SelectedValue))%>
2-
<%: Html.DropDownListFor(m => m.Page6VM.ProgramsDDL.Program_List, new SelectList(Model.Page6VM.ProgramsDDL.Program_List, "ProgramID", "ProgramDesc"), Model.Page6VM.ProgramsDDL.SelectedValue)%>
But when I try to update my model through a controller action
[HttpPost]
public ActionResult UpdateUser(PageViewModel model)
{
}
model.ProgramsDDL.count is zero.
What is the best way to render this dropdownlist and be able to set the selected index, and also be able to send the selected index back to the controller?
You mixed up the parameters for Html.DropDownListFor(). Code sample below should work.
<%: Html.DropDownListFor(m => m.SelectedValue,
new SelectList(Model.Page6VM.ProgramsDDL.Program_List, "ProgramID", "ProgramDesc"),
null) %>
You also should have a SelectedValue in your model that's posted back.
public class PageViewModel
{
public ProgramListVM ProgramsDDL { get; set; }
public int SelectedValue { get; set; }
public PageViewModel()
{
this.ProgramsDDL = new ProgramListVM();
}
}
Also default model binder can't map complex collections to your model. You probably don't need them in your post action anyway.
I am trying to create a dropdown list to display all the value in a custom collection class
such as
public class MyCustomClassCollection
{
public List<MyCustomClass> {get;set;}
}
I want it to show the Description:string of each MyCustomClass
I tried
<%: Html.DropDownList "Description", MyCustomClass %>
Resharper suggests that I cast MyCustomClass to IEnemerable
but the server returns an unable to cast error.
Any Idea how I can create this DropDownList?
__Modification___
public class ViewModel
{
public Detail detail { get; set; }
}
public class Detail //Inherited from webservce
{
public CustomClassCollection {get;set;}
.... Other Properties, a.k.a Custom Classes
}
public class CustomClassCollection
{
public List<CustomClass> {get;set;}
}
public class CustomClass {
public int Id {get;set;}
public string Description{get;set;}
... other properties
}
public ActionResult Index(int? id, DateTime? date)
{
if (id.Equals(null))
id = ######### ;
if (date.Equals(null))
date = DateTime.Today;
var vm = new ViewModel
{
Detail = _repository.Detail((int)id,(DateTime)date)
};
return View(vm);
}
The second argument of the DropDownList helper must be an IEnumerable<SelectListItem> or a SelectList which implements this interface for that matter. So in your controller action organize in such a way that you convert your custom collection into an IEnumerable<SelectListItem>. As always you could start by writing a view model:
public class MyViewModel
{
public string SelectedDescription { get; set; }
public SelectList Descriptions { get; set; }
}
and then have your controller action query the custom list and populate the view model which will be passed to the view:
public ActionResult Index()
{
var descriptions = yourCustomCollection.MyCustomClass.Select(x => new
{
Value = x.Description,
Text = x.Description
});
var model = new MyViewModel
{
Descriptions = new SelectList(descriptions, "Value", "Text")
};
return View(model);
}
and finally in your strongly typed view:
<%= Html.DropDownListFor(x => x.SelectedDescription, Model.Decriptions) %>
UPDATE:
After posting your updated models (which by the way are still incomplete and impossible to compile as you haven't provided any property names), here's an example:
public class ViewModel
{
public int SelectedId { get; set; }
public Detail Detail { get; set; }
}
public class Detail
{
public CustomClassCollection MyCollection { get; set; }
}
public class CustomClassCollection
{
public List<CustomClass> CustomClass { get; set; }
}
public class CustomClass
{
public int Id { get; set; }
public string Description { get; set; }
}
public class HomeController : Controller
{
public ActionResult Index()
{
var vm = new ViewModel
{
Detail = new Detail
{
MyCollection = new CustomClassCollection
{
CustomClass = new List<CustomClass>
{
new CustomClass
{
Id = 1,
Description = "description 1",
},
new CustomClass
{
Id = 2,
Description = "description 2",
},
new CustomClass
{
Id = 3,
Description = "description 3",
},
}
}
}
};
return View(vm);
}
}
and in the view:
<%= Html.DropDownListFor(
x => x.SelectedId,
new SelectList(Model.Detail.MyCollection.CustomClass, "Id", "Description")
) %>
What you have to understand in order to define a dropdown list in ASP.NET MVC ius that you need 2 things:
A scalar property to bind the selected value to (SelectedId in my example)
A collection to bind the list to (Model.Detail.MyCollection.CustomClass in the example)
i have a model :
public class person
{
public int id{get;set;}
public string name{get;set;}
}
how can i make a drop down list, from list of person in mvc3 razor by this syntax : #Html.DropDownListFor(...) ?
what type must be my persons list?
sorry I'm new in mvc3
thanks all
public class PersonModel
{
public int SelectedPersonId { get; set; }
public IEnumerable<Person> persons{ get; set; }
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
then in the controller
public ActionResult Index()
{
var model = new PersonModel{
persons= Enumerable.Range(1,10).Select(x=>new Person{
Id=(x+1),
Name="Person"+(x+1)
}).ToList() <--- here is the edit
};
return View(model);//make a strongly typed view
}
your view should look like this
#model Namespace.Models.PersonModel
<div>
#Html.DropDownListFor(x=>x.SelectedPersonId,new SelectList(Model.persons,"Id","Name","--Select--"))
</div>
You should translate that to a List<SelectListItem> if you want to use the build in MVC HtmlHelpers.
#Html.DropDownFor(x => x.SelectedPerson, Model.PersonList)
Alternatively, you can simply make your own in the template:
<select id="select" name="select">
#foreach(var item in Model.PersonList)
{
<option value="#item.id">#item.name</option>
}
</select>