Reputation: 273
I have an application that allows user to create new items. As it stands now the user need to fill out Title, body and category.
The category is a textbox but I would like to convert it to a dropdownlist. This is all connected to a database and when the user submits it the data should be saved in the database. Everything works fine as it stands now, I am only having trouble implementing the dropdownlist.
My model:
public class NewsItem
{
public int ID { get; set; }
[Required(ErrorMessage = "Title is Required")]
public string Title { get; set; }
[Required(ErrorMessage = "Body is Required")]
public DateTime DateCreate { get; set; }
public string Category { get; set; }
}
What is the quickest/best way implementing this. Should I do it in the model or can I assign the values available in the view?
Thanks in advance!
Upvotes: 0
Views: 349
Reputation: 239210
First, some semantics. Since Entity Framework comes along with MVC, the assumption is that your POCOs are "models". (Unfortunately, Microsoft kind of piles on by putting scaffolded POCOs in a "Models" folder). However, these are not models in terms of the "Model" in Model-View-Controller; instead, they are merely "entities", which is a fancy way of saying "pretty much just a DTO EF can use to stuff data from the database into."
I point that out to say this: no, you shouldn't put your drop down list choices on your entity. But, you shouldn't rely on the view for this either. What you really want here is a view model. You create a class that has just the fields you need to edit and any additional business logic your view needs (such as the choices of categories), and then you map your entity to and from this view model. As an example:
public class NewsItemViewModel
{
[Required(ErrorMessage = "Title is Required")]
public string Title { get; set; }
[Required(ErrorMessage = "Body is Required")]
public DateTime DateCreate { get; set; }
public string Category { get; set; }
public IEnumerable<SelectListItem> CategoryChoices { get; set; }
}
Notice that while this class is mostly the same, it doesn't contain an Id
property, because this is not something you'd want the user to edit. Also, it includes a CategoryChoices
property to hold the items for your drop down list.
Then in your controller, you would do something like:
public ActionResult CreateNewsItem()
{
var model = new NewsItemViewModel();
model.CategoryChoices = db.Categories.Select(m => new SelectListItem { Value = m.Name, Text = m.Name });
return View(model);
}
Basically, you're just newing up the view model so you can feed it to the view. You fill in your category choices before actually returning it, though. I've assumed they're also entities, but you would use whatever method you needed to fetch them here, otherwise.
For your post action:
[HttpPost]
public ActionResult CreateNewsItem(NewsItemViewModel model)
{
if (ModelState.IsValid)
{
// map view model to entity
var newsItem = new NewsItem
{
Title = model.Title,
Category = model.Category,
// and so on
}
db.NewsItems.Add(newsItem);
db.SaveChanges();
return RedirectToAction("Index");
}
model.CategoryChoices = db.Categories.Select(m => new SelectListItem { Value = m.Name, Text = m.Name });
return View(model);
}
I'm just doing a manual mapping from the view model to a new news item, here, but for real world scenarios, you'd probably want to integrate a mapping library for this, such as AutoMapper. Also, take note that in the case where there's an error, you must refill the category choices before returning the view again. These will not be posted by your form, so the model that was passed in will not have them.
Finally, in your view:
@model Namespace.To.NewsItemViewModel
...
@Html.DropDownListFor(m => m.Category, Model.CategoryChoices)
Upvotes: 1