Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asp.Net MVC3 - How create Dynamic DropDownList

I found many articles on this but still I don´t know how exactly to do this. I am trying to create my own blog engine, I have View for create article (I am using EF and Code first) and now I must fill number of category in which article should be add but I want to change it to dropdownlist with names of categories. My model looks this:

public class Article
{
    public int ArticleID { get; set; }
    [Required]
    public string Title { get; set; }
    [Required]
    public int CategoryID { get; set; }
    public DateTime Date { get; set; }
    [Required()]
    [DataType(DataType.MultilineText)]
    [AllowHtml]
    public string Text { get; set; }
    public virtual Category Category { get; set; }
    public IEnumerable<SelectListItem> Categories { get; set; }
    public virtual ICollection<Comment> Comments { get; set; }
}
public class Category
{
    public int CategoryID { get; set; }
    [Required]
    public string Name { get; set; }
    public virtual ICollection<Article> Articles { get; set; }

}

I know I must use Enum (or I think) but I am not exactly sure how. I don´t know which tutorial from that I found is best for me.


Edit:

Thanks for your answers but I found something else. I am trying this:

This is my model:

public class Article
{
    [Key]
    public int ArticleID { get; set; }

    [Display(Name = "Title")]
    [StringLength(30, MinimumLength = 5)]
    [Required]
    public string Title { get; set; }

    public DateTime Date { get; set; }

    public int CategoryID { get; set; }

    [Required()]
    [DataType(DataType.MultilineText)]
    [AllowHtml]
    public string Text { get; set; }

   public Category Category { get; set; }

    public virtual ICollection<Comment> Comments { get; set; }

    public IEnumerable<Category> Categories { get; set; }
}
public class Category
{
[Key]
    public int CategoryId { get; set; }
    [Required]
public string CategoryName { get; set; }
    public virtual ICollection<Article> Articles { get; set; }

}

This is my controller to create article:

public ActionResult Vytvorit()
{
    IEnumerable<Category> categories = GetCaregories();
    var view = View(new Article() { Categories = categories });
    view.TempData.Add("Action", "Create");

    return view;

}

private static IEnumerable<Category> GetCaregories()
{
    IEnumerable<Category> categories;
    using (BlogDBContext context = new BlogDBContext())
    {
        categories = (from one in context.Categories
                      orderby one.CategoryName
                      select one).ToList();
    }
    return categories;
}

private Category GetCategory(int categoryID)
{
        return db.Categories.Find(categoryID);
}
//
// POST: /Clanky/Vytvorit

[HttpPost]
public ActionResult Vytvorit(Article newArticle)
{

    try
    {
        if (newArticle.CategoryID > 0)
        {
            newArticle.Category = GetCategory(newArticle.CategoryID);
        }
        if (TryValidateModel(newArticle))
        {
                db.Articles.Add(newArticle);
                db.SaveChanges();
            return RedirectToAction("Index");
        }
        else
        {
            newArticle.Categories = GetCaregories();
            var view = View(newArticle);
            view.TempData.Add("Action", "Create");
            return view;
        }
    }
    catch
    {
        return View();

    }
}

And this is part of my view:

     @Html.DropDownListFor(model => model.CategoryID, new SelectList(Model.Categories,"CategoryID","CategoryName"))
        @Html.ValidationMessageFor(model => model.CategoryID)

I have problem with NullReferenceExeption but I don´t know why. Can I do it this way? It looks very easy for me.

like image 814
Libor Zapletal Avatar asked Feb 19 '11 07:02

Libor Zapletal


2 Answers

Your model seems quite strange. It contains properties such as CategoryID and Category which seem redundant. It also contains a SelectListItem collection property called Categories. So, is this a model or a view model? It looks quite messed up. Let's assume it's a model. In this case it would more likely look something like this:

public class Article
{
    public int ArticleID { get; set; }

    [Required]
    public string Title { get; set; }

    public DateTime Date { get; set; }

    [Required()]
    [DataType(DataType.MultilineText)]
    [AllowHtml]
    public string Text { get; set; }

    public virtual Category Category { get; set; }

    public IEnumerable<Category> Categories { get; set; }

    public virtual ICollection<Comment> Comments { get; set; }
}

public class Category
{
    public int CategoryID { get; set; }

    [Required]
    public string Name { get; set; }

    public virtual ICollection<Article> Articles { get; set; }

}

Now that the model is clear we could define a view model which will be passed to the view. A view model is a class which is specifically designed for the view. So depending on what you intend to put in this view you define it in this view model. So far you have talked only about a drop down, so let's do it:

public class ArticleViewModel
{
    public int SelectedCategoryId { get; set; }
    public IEnumerable<SelectListItem> Categories { get; set; }
}

and then we have a controller:

public class ArticlesController: Controller
{
    private readonly IArticlesRepository _repository;
    public ArticlesController(IArticlesRepository repository)
    {
        _repository = repository;
    }

    public ActionResult Index()
    {
        Article article = _repository.GetArticle();
        ArticleViewModel viewModel = Mapper.Map<Article, ArticleViewModel>(article);
        return View(viewModel);
    }
}

So the controller uses a repository to fetch the model, maps it to a view model (in this example I use AutoMapper) and passes the view model to the view which will take care of showing it:

@model AppName.Models.ArticleViewModel
@using (Html.BeginForm())
{
    @Html.DropDownListFor(
        x => x.SelectedCategoryId, 
        new SelectList(Model.Categories, "Value", "Text"),
        "-- Select category --"
    )
    <input type="submit" value="OK" />
}
like image 62
Darin Dimitrov Avatar answered Oct 14 '22 00:10

Darin Dimitrov


I have gone through this as well and I have to agree that at first it seems odd (In my explanation I'm assuming you want to select one category only, but the process is very similar for a multi select).

Basically you need to perform 3 steps:

1:
You need two properties on your viewmodel One will hold the selected category id (required for postback) and the other will a SelectList with all possible categories:

public class Article
{
    public int ArticleID { get; set; }

    public int CategoryID { get; set; }

    public SelectList Categories { get; set; }
}

2:
Also before passing the viewmodel on to the view you need to initialize the SelectList (Best practivce is to prepare as much as possible before passing a model into the view):

new SelectList(allCategories, "CategoryID", "Name", selectedCategoryID)

3:
In the view you need to add a ListBox for the CategoryID property, but using the Categories property too fill the ListBox with values:

@Html.ListBoxFor(model => model.CategoryID , Model.Categories)

Thats it! In the post back action of the controller you will have the CategoryID set. You can do whatever you need to from there to persist things in your db.

like image 21
ntziolis Avatar answered Oct 14 '22 00:10

ntziolis