ASP.NET MVC - dropdown list post handling problem
- by ile
I've had troubles for a few days already with handling form that contains dropdown list. I tried all that I've learned so far but nothing helps. This is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using CMS;
using CMS.Model;
using System.ComponentModel.DataAnnotations;
namespace Portal.Models
{
public class ArticleDisplay
{
public ArticleDisplay() { }
public int CategoryID { set; get; }
public string CategoryTitle { set; get; }
public int ArticleID { set; get; }
public string ArticleTitle { set; get; }
public DateTime ArticleDate;
public string ArticleContent { set; get; }
}
public class HomePageViewModel
{
public HomePageViewModel(IEnumerable<ArticleDisplay> summaries, Article article)
{
this.ArticleSummaries = summaries;
this.NewArticle = article;
}
public IEnumerable<ArticleDisplay> ArticleSummaries { get; private set; }
public Article NewArticle { get; private set; }
}
public class ArticleRepository
{
private DB db = new DB();
//
// Query Methods
public IQueryable<ArticleDisplay> FindAllArticles()
{
var result = from category in db.ArticleCategories
join article in db.Articles on category.CategoryID equals article.CategoryID
orderby article.Date descending
select new ArticleDisplay
{
CategoryID = category.CategoryID,
CategoryTitle = category.Title,
ArticleID = article.ArticleID,
ArticleTitle = article.Title,
ArticleDate = article.Date,
ArticleContent = article.Content
};
return result;
}
public IQueryable<ArticleDisplay> FindTodayArticles()
{
var result = from category in db.ArticleCategories
join article in db.Articles on category.CategoryID equals article.CategoryID
where article.Date == DateTime.Today
select new ArticleDisplay
{
CategoryID = category.CategoryID,
CategoryTitle = category.Title,
ArticleID = article.ArticleID,
ArticleTitle = article.Title,
ArticleDate = article.Date,
ArticleContent = article.Content
};
return result;
}
public Article GetArticle(int id)
{
return db.Articles.SingleOrDefault(d => d.ArticleID == id);
}
public IQueryable<ArticleDisplay> DetailsArticle(int id)
{
var result = from category in db.ArticleCategories
join article in db.Articles on category.CategoryID equals article.CategoryID
where id == article.ArticleID
select new ArticleDisplay
{
CategoryID = category.CategoryID,
CategoryTitle = category.Title,
ArticleID = article.ArticleID,
ArticleTitle = article.Title,
ArticleDate = article.Date,
ArticleContent = article.Content
};
return result;
}
//
// Insert/Delete Methods
public void Add(Article article)
{
db.Articles.InsertOnSubmit(article);
}
public void Delete(Article article)
{
db.Articles.DeleteOnSubmit(article);
}
//
// Persistence
public void Save()
{
db.SubmitChanges();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Portal.Models;
using CMS.Model;
namespace Portal.Areas.CMS.Controllers
{
public class ArticleController : Controller
{
ArticleRepository articleRepository = new ArticleRepository();
ArticleCategoryRepository articleCategoryRepository = new ArticleCategoryRepository();
//
// GET: /Article/
public ActionResult Index()
{
ViewData["categories"] = new SelectList
(
articleCategoryRepository.FindAllCategories().ToList(), "CategoryId", "Title"
);
Article article = new Article()
{
Date = DateTime.Now,
CategoryID = 1
};
HomePageViewModel homeData = new HomePageViewModel(articleRepository.FindAllArticles().ToList(), article);
return View(homeData);
}
//
// GET: /Article/Details/5
public ActionResult Details(int id)
{
var article = articleRepository.DetailsArticle(id).Single();
if (article == null)
return View("NotFound");
return View(article);
}
//
// GET: /Article/Create
//public ActionResult Create()
//{
// ViewData["categories"] = new SelectList
// (
// articleCategoryRepository.FindAllCategories().ToList(), "CategoryId", "Title"
// );
// Article article = new Article()
// {
// Date = DateTime.Now,
// CategoryID = 1
// };
// return View(article);
//}
//
// POST: /Article/Create
[ValidateInput(false)]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Article article)
{
if (ModelState.IsValid)
{
try
{
// TODO: Add insert logic here
articleRepository.Add(article);
articleRepository.Save();
return RedirectToAction("Index");
}
catch
{
return View(article);
}
}
else
{
return View(article);
}
}
//
// GET: /Article/Edit/5
public ActionResult Edit(int id)
{
ViewData["categories"] = new SelectList
(
articleCategoryRepository.FindAllCategories().ToList(), "CategoryId", "Title"
);
var article = articleRepository.GetArticle(id);
return View(article);
}
//
// POST: /Article/Edit/5
[ValidateInput(false)]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection collection)
{
Article article = articleRepository.GetArticle(id);
try
{
// TODO: Add update logic here
UpdateModel(article, collection.ToValueProvider());
articleRepository.Save();
return RedirectToAction("Details", new { id = article.ArticleID });
}
catch
{
return View(article);
}
}
//
// HTTP GET: /Article/Delete/1
public ActionResult Delete(int id)
{
Article article = articleRepository.GetArticle(id);
if (article == null)
return View("NotFound");
else
return View(article);
}
//
// HTTP POST: /Article/Delete/1
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(int id, string confirmButton)
{
Article article = articleRepository.GetArticle(id);
if (article == null)
return View("NotFound");
articleRepository.Delete(article);
articleRepository.Save();
return View("Deleted");
}
[ValidateInput(false)]
public ActionResult UpdateSettings(int id, string value, string field)
{
// This highly-specific example is from the original coder's blog system,
// but you can substitute your own code here. I assume you can pick out
// which text field it is from the id.
Article article = articleRepository.GetArticle(id);
if (article == null)
return Content("Error");
if (field == "Title")
{
article.Title = value;
UpdateModel(article, new[] { "Title" });
articleRepository.Save();
}
if (field == "Content")
{
article.Content = value;
UpdateModel(article, new[] { "Content" });
articleRepository.Save();
}
if (field == "Date")
{
article.Date = Convert.ToDateTime(value);
UpdateModel(article, new[] { "Date" });
articleRepository.Save();
}
return Content(value);
}
}
}
and view:
<%@ Page Title="" Language="C#" MasterPageFile="~/Areas/CMS/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Portal.Models.HomePageViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Index
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<div class="naslov_poglavlja_main">Articles Administration</div>
<%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>
<% using (Html.BeginForm("Create","Article")) {%>
<div class="news_forma">
<label for="Title" class="news">Title:</label>
<%= Html.TextBox("Title", "", new { @class = "news" })%>
<%= Html.ValidationMessage("Title", "*") %>
<label for="Content" class="news">Content:</label>
<div class="textarea_okvir">
<%= Html.TextArea("Content", "", new { @class = "news" })%>
<%= Html.ValidationMessage("Content", "*")%>
</div>
<label for="CategoryID" class="news">Category:</label>
<%= Html.DropDownList("CategoryId", (IEnumerable<SelectListItem>)ViewData["categories"], new { @class = "news" })%>
<p>
<input type="submit" value="Publish" class="form_submit" />
</p>
</div>
<% } %>
<div class="naslov_poglavlja_main"><%= Html.ActionLink("Write new article...", "Create") %></div>
<div id="articles">
<% foreach (var item in Model.ArticleSummaries) { %>
<div>
<div class="naslov_vijesti" id="<%= item.ArticleID %>"><%= Html.Encode(item.ArticleTitle) %></div>
<div class="okvir_vijesti">
<div class="sadrzaj_vijesti" id="<%= item.ArticleID %>"><%= item.ArticleContent %></div>
<div class="datum_vijesti" id="<%= item.ArticleID %>"><%= Html.Encode(String.Format("{0:g}", item.ArticleDate)) %></div>
<a class="news_delete" href="#" id="<%= item.ArticleID %>">Delete</a>
</div>
<div class="dno"></div>
</div>
<% } %>
</div>
</asp:Content>
When trying to post new article I get following error:
System.InvalidOperationException: The
ViewData item that has the key
'CategoryId' is of type 'System.Int32'
but must be of type
'IEnumerable'.
I really don't know what to do cause I'm pretty new to .net and mvc
Any help appreciated!
Ile
EDIT:
I found where I made mistake. I didn't include date.
If in view form I add this line I'm able to add article:
<%=Html.Hidden("Date", String.Format("{0:g}", Model.NewArticle.Date)) %>
But, if I enter wrong datetype or leave title and content empty then I get the same error. In this eample there is no need for date edit, but I will need it for some other forms and validation will be necessary.
EDIT 2:
Error happens when posting!
Call stack:
App_Web_of9beco9.dll!ASP.areas_cms_views_article_create_aspx.__RenderContent2(System.Web.UI.HtmlTextWriter __w = {System.Web.UI.HtmlTextWriter}, System.Web.UI.Control parameterContainer = {System.Web.UI.WebControls.ContentPlaceHolder}) Line 31 + 0x9f bytes C#