I have a model:
public class MenuItem
{
public int Id { get; set; }
....
[StringLength(50)]
public string PageTemplate { get; set; }
public int MenuId { get; set; }
public Menu Menu { get; set; }
}
Notice the PageTemplate. I need to somehow create a property that list out files from a folder. This property should then be a selectlist in the view, and then saved in the PageTemplate.
What would the proper way of doing this be?
In the model add:
public IEnumerable<SelectListItem> Templates { get; set; }
In the action method populate your data to the property:
public ActionResult Create()
{
return View(new MenuItem
{
Templates = _yourFilesList.
.Select(f => new SelectListItem { Text = f.Title })
});
}
[HttpPost]
public ActionResult Create(MenuItem item)
{
var userTemplate=item.PageTemplate; // user's selected item is there
}
Finally in the view add this
#Html.DropDownListFor(x => x.PageTemplate , Model.Templates)
Related
I have a class for which has a 1 to many relationship with another class. for this I will use class Car and class Gears. I need to create a form, which registers a car and the user needs to specify a choice of gears.
public class Car
{
public int id { get; set; }
public string desc { get; set; }
public List<Gear> Gears { get; set; }
}
public class Gear
{
public int gid { get; set; }
public int gname { get; set; }
}
using asp.net MVC 5, I have a create form, which I have scaffolded to the Car model, and within the form, I wish to have a checkboxlist of gears,
I also have a ViewModel that I have provided for my checkboxlist which is as below:
public class GearsViewModel
{
public Gear _gear {get; set; }
public bool _isChecked {get; set;}
}
Controller looks like:
Gears fetched from db context will be
"GearR","Gear1","Gear2","Gear3","Gear4","Gear5","Gear6","Gear7"
public action Create()
{
ViewBag.Gears = new SelectList(db.Gears, "gid","gname");
List<GearViewModel> _gears= new List<GearViewModel>();
foreach(Gear G in ViewBag.Gears)
{
_gears.Add(new GearViewModel(G, false));
}
ViewBag.GearsCheckList = _gears.ToList();
return View();
}
Now, this is the part I'm getting stuck at, is how to display and capture details in the CreateView.
I need assistance on how to design the Create form and how I will capture the info.
Firstly, view models should not contain data models when editing. You view models should be (add validation and display attributes as appropriate)
public class CarVM
{
public int? ID { get; set; }
public string Description { get; set; }
public List<GearVM> Gears { get; set; }
}
public class GearVM
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
and the GET method will be
public ActionResult Create()
{
var gears = db.Gears;
CarVM model = new CarVM
{
Gears = gears.Select(x => new GearVM
{
ID = x.gid,
Name = x.gname
}).ToList()
};
return View(model);
}
and the view will then be
#model CarVM
....
#using (Html.BeginForm())
{
..... // elements for editing ID and Description properties of CarVM
#for (int i = ; i < Model.Gears.Count; i++)
{
<div>
#Html.HiddenFor(m => m.Gears[i].ID)
#Html.HiddenFor(m => m.Gears[i].Name) // include if your want to get this in the POST method as well
#Html.CheckboxFor(m => m.Gears[i].IsSelected)
#Html.LabelFor(m => m.Gears.IsSelected, Model.Gears[i].Name)
</div>
}
<input type="submit" .... />
}
Then in the POST method
public ActionResult Create(CarVM model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// To get the ID's of the selected gears
IEnumerable<int> selected = model.Gears.Where(x => x.IsSelected).Select(x => x.ID);
// Initialize your data models, save and redirect
}
I have Entity Framework model which contains reference to other Entity like
public class Product
{
[Key]
public int ProductID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public virtual Shop Shop { get; set; }
[Required]
public double Price { get; set; }
}
I would like to create Edit View which contain Shop selector (DropDown).
By default I have created basic MVC Controller with Entity model connected, which created Edit like:
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Product product = db.Products.Find(id);
if (product == null)
{
return HttpNotFound();
}
return View(product);
}
and View does not contain Shop selector.
I have tried to add DropDown like:
#Html.DropDownListFor(product => product.Shop, (SelectList)ViewBag.Shops)
But in POST method, Shop entity is null.
How to handle that?
Create a view model to represent what you want to display
public class ProductVM
{
public int ProductID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int? ShopID { get; set; }
[Required]
public double Price { get; set; }
public SelectList ShopList { get; set; }
}
and in your controller, map your model to the view model
public ActionResult Edit(int? ID)
{
....
Product product = db.Products.Find(id);
ProductVM model = new ProductVM();
// map properties
....
// populate select list (assumes Shop has properties ID and Name)
model.ShopList = new SelectList(db.Shops, "ID", "Name");
return View(product);
}
and in your view
#model ProductVM
....
#Html.DropDownListFor(m => m.ShopID, Model.ShopList, "--Select shop--")
#Html.ValidationMessageFor(m -> m.ShopID)
this will post back the model with the selected ID of the Shop. Select controls post back single values so you cannot post back a complex object such as Shop. The POST method would be
[HttpPost]
public ActionResult Edit(ProductVM model)
{
....
}
Note you can use tools such as automapper to make mapping easier
I hope this helps.
Model for Product:
public class Product
{
public int ProductID { get; set; }
public string Name { get; set; }
public int ShopID { get; set; }
public double Price { get; set; }
}
Then a ViewModel for Product:
public class ProductViewModel
{
public Product Model { get; set; }
public IEnumerable<SelectListItem> Shops{ get; set; }
public ProductViewModel()
{
GetShops();
}
public void GetShops()
{
Shops = new List<SelectListItem>();
var collectionShops = GetShopsFromDatabase();
Shops.AddRange(
collectionShops.Select(
contract =>
new SelectListItem
{
Text = contract.ShopDescription,
Value = contract.ShopID.ToString()
}));
}
}
In your View:
#model ProductViewModel
....
#Html.DropDownListFor(x => x.Model.ShopID, Model.Shops, new { #title = "Please select a shop" })
I currently have an application with a home page that shows a list of ten movies based on the date they were "created", or entered into the database. I would also like to show a list of the top ten movies based on the rating of each movie. Is there a way to pass in another model or alter my current ViewModel to do this? Here is the Index section of my Home Controller:
public ActionResult Index()
{
var model =
_db.Movies
.OrderByDescending(m => m.DateEntered)
.Take(10)
.Select(m => new MovieListViewModel
{
Id = m.Id,
Title = m.Title,
Genre = m.Genre,
ReleaseDate = m.ReleaseDate,
CountOfReviews = m.Reviews.Count()
});
return View(model);
}
And the ViewModel being passed in:
public class MovieListViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public string Genre { get; set; }
[Display(Name="Year Released")]
public DateTime ReleaseDate { get; set; }
public int CountOfReviews { get; set; }
}
Create a model that encompasses both lists:
public class MovieListViewModel
{
public List<MovieModel> Top10ByCreated { get; set; }
public List<MovieModel> Top10ByRating { get; set; }
}
public class MovieModel
{
public int Id { get; set; }
public string Title { get; set; }
public string Genre { get; set; }
[Display(Name="Year Released")]
public DateTime ReleaseDate { get; set; }
public int CountOfReviews { get; set; }
}
Then in your controller:
var model = new MovieListViewModel();
model.Top10ByCreated = ...
model.Top10ByRating = ...
return View(model);
In your view, use MovieListViewModel as your model and use your two lists as needed.
Just create another viewmodel, with two properties for the two lists:
public class MovieIndexViewModel
{
public IEnumerable<MovieListViewModel> TopTenByDate { get; set; }
public IEnumerable<MovieListViewModel> TopTenByRating { get; set; }
}
In the controller you can create this viewmodel and pass the two lists:
public ActionResult Index()
{
var vm = new MovieIndexViewModel();
vm.TopTenByDate = ....;
vm.TomTenByRating = ...;
return View(vm );
}
You can compose a single view model that contains the two result sets. The controller then instantiates the parent type and populates the child collections as you see fit.
public sealed class HomeViewModel{
public MovieListViewModel TopTenByRating { get; set; }
public MovieListViewModel TopTenByDate { get; set; }
}
public ActionResult Index()
{
var model = new HomeViewModel();
model.TopTenByDate =
_db.Movies
.OrderByDescending(m => m.DateEntered)
.Take(10)
.Select(m => new MovieListViewModel
{
Id = m.Id,
Title = m.Title,
Genre = m.Genre,
ReleaseDate = m.ReleaseDate,
CountOfReviews = m.Reviews.Count()
});
model.TopTenByRating = // something else
return View(model);
}
For more complex scenarios, I prefer a dedicated composer that is responsible for setting up the view model (rather than having all the logic in the action method).
For a simple scenario like this, setting it up in the controller is the easiest way. If you find yourself needing to reuse the query logic, consider abstracting it to a helper class.
A different approach would be to create the main view and get it to render the results of 2 action methods returning 2 partial views each typed to one of the models.
You have different options you can use anyone of them
Use ViewModel
For view model you have to create a class and in this class you will define all models as properties of this class.Here are two classes.
public class EmployeeDetails
{
[Required]
[Display(Name = "Name")]
public string Name { get; set; }
}
public class Employee
{
public int Id { get; set; }
}
Here is viewmodel
public class ViewModel
{
public Employee emp { get; set; }
public EmployeeDetails empdet{ get; set; }
}
Now in Controller you will do like this
public ActionResult About()
{
ViewModel vm = new ViewModel();
vm.emp = new Employee();
vm.empdet = new EmployeeDetails();
return View(vm);
}
And in view you will receive it like this
#model ViewModel
Use Tuple
Tuple is used to store different types.You can store your required classes object in it and pass to view
In controller
Tuple<int, string> tuple = new Tuple<int, string>(1, "Hello world");
return View(tuple);
In view you will receive it like this
#model Tuple<int,string>
I feel a bit stupid.
I'm trying to get a hang of MVC 4, using boxing as a functional example.
I have WeightCategories in the database (Heavyweights, etc), and Boxers.
Seem simple. The relation is a boxer has a current weight category, but when I edit, I want it to be able to change it with a drop down.
I understand how to do it if it's a list I've made myself in the code, but I have problem understanding how to "load" the list from the WeightCategory table and show it in the view/model of the boxer.
So, here is my code for the WeightCategory item:
[Table("WeightCategories")]
public class WeightCategory
{
[Key]
public int WeightCategoryId { get; set; }
public WEIGHT_CATEGORIES WeightCategoryType { get; set; }
[Display(Name = "Weight Category Name")]
[Required]
[MinLength(5)]
public string Name { get; set; }
[Display(Name = "Weight Limit In Pounds")]
public int? WeightLimit { get; set; }
}
Here is the code for the boxer item
[Table("Boxers")]
public class Boxer
{
[Key]
public int BoxerId { get; set; }
public WeightCategory CurrentWeightCategory { get; set; }
[Required]
public string Name { get; set; }
public int Wins { get; set; }
public int Losses { get; set; }
public int Draws { get; set; }
public int Kayos { get; set; }
}
In the view, I'm really not sure how to tackle that, I'm pretty sure it's not automatic and I need to load the table somewhere in the controller maybe... I'm looking for best practice or something.
Something like that in the view at the end:
#Html.DropDownListFor(model => model.CurrentWeightCategory.WeightCategoryId,
new SelectList(Model.WeightCategories, "WeightCategoryId", "Name",
Model.WeightCategories.First().WeightCategoryId))
You could design a view model:
public class MyViewModel
{
public Boxer Boxer { get; set; }
public IEnumerable<SelectListItem> WeightCategories { get; set; }
}
and then have your controller action populate and pass this view model to the view:
public ActionResult Edit(int id)
{
var model = new MyViewModel();
using (var db = new SomeDataContext())
{
// Get the boxer you would like to edit from the database
model.Boxer = db.Boxers.Single(x => x.BoxerId == id);
// Here you are selecting all the available weight categroies
// from the database and projecting them to the IEnumerable<SelectListItem>
model.WeightCategories = db.WeightCategories.ToList().Select(x => new SelectListItem
{
Value = x.WeightCategoryId.ToString(),
Text = x.Name
})
}
return View(model);
}
and now your view becomes strongly typed to the view model:
#model MyViewModel
#Html.DropDownListFor(
x => model.Boxer.CurrentWeightCategory.WeightCategoryId,
Model.WeightCategories
)
i am using asp.net mvc3 and i populate a create view using following model
Model
public class CategoryModel
{
public int Id { get; set; }
public string Name { get; set; }
public string URL { get; set; }
public string Description { get; set; }
public string Logo { get; set; }
public bool IsActive { get; set; }
public bool isPopular { get; set; }
public IList<Category> Parentcategories { get; set; }
}
In my create View i populate like this
View
<div class="editor-field">
#Html.DropDownList("parentcategories", new SelectList(Model.Parentcategories.Select(c => c.Name), Model.Parentcategories.Select(c => c.Name)))
#Html.ValidationMessageFor(model => model.Parentcategories)
</div>
now how can i access the selected item in my controller method
Method
[HttpPost]
public ActionResult Create( CategoryModel model , HttpPostedFileBase file)
{
//
}
thanks,
Ahsan
Try this:
public ActionResult Create(string parentcategories, CategoryModel model , HttpPostedFileBase file)
parentcategories will contain selected option value.
As Smartboy already mentioned, you should use DropDownListFor:
1. append your model with public int ParentCategoryId { get; set; } field.
2. instead of using #Html.DropDownList use:
#Html.DropDownListFor(m => m.ParentCategoryId, new SelectList(...))
3. the server side can stay the same:
[HttpPost]
public ActionResult Create(CategoryModel model)
{
//
}
where model.ParentCategoryId will have selected item value.
Also note that you can first set selected item value for your view:
public ActionResult Index()
{
var model = CategoryModel();
...
model.ParentCategoryId = some_selected_value;
return View(model);
}
Details: You can access it directly from your model.
[HttpPost]
public ActionResult Create( CategoryModel model , HttpPostedFileBase file)
{
var selectedCategory = model.parentcategories; // something like that
}