ASP.NET MVC - 下拉列表提交处理问题

3

我已经遇到了几天的麻烦,无法处理包含下拉列表的表单。我尝试了迄今为止学到的所有方法,但都没有帮助。这是我的代码:

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);
        }


    }
}

并查看:

    <%@ 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>

尝试发布新文章时出现以下错误:

System.InvalidOperationException: 键为“CategoryId”的 ViewData 项类型为“System.Int32”,但必须为“IEnumerable”类型。

我真的不知道该怎么办,因为我对 .net 和 mvc 都很陌生。 任何帮助都将不胜感激! Ile 编辑: 我找到了我的错误所在。我没有包含日期。 如果在视图表单中添加此行,则可以添加文章:
<%=Html.Hidden("Date", String.Format("{0:g}", Model.NewArticle.Date)) %> 

但是,如果我输入错误的日期类型或者标题和内容为空,则会得到相同的错误。在这个例子中不需要日期编辑,但是在其他表单中我将需要它,并且需要进行验证。



编辑2: 错误发生在发布时!
调用堆栈:
    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})第31行+0x9f字节    C#

3个回答

3
解决了!问题出在这里:
public ActionResult Create()
        {
            ViewData["categories"] = new SelectList
            (
                articleCategoryRepository.FindAllCategories().ToList(), "CategoryID", "Title"
            );

            Article article = new Article()
            {
                Date = DateTime.Now,
                CategoryID = 1
            };

            return View(article);
        }

我将CategoryID设置为整数,这就是问题所在。如果我删除这行代码,一切都正常运作。但问题是如何在下拉列表中设置默认类别?


0

我遇到了同样的错误。最后发现是Combobox没有被填充。

对我来说解决方案是:在Create方法(响应GET请求的方法)中填充了一个DropDownList,并使用ViewData/ViewBag将其传递给视图。

当调用dataContext.SaveChanges()时,Create方法(响应POST请求的方法)抛出异常,catch语句只包含这个异常:

catch 
        {
            return View(companyRating);
        }

这还不够,View 期望一个 ViewData.Ratings SelectList,但它已经没有被填充了。所以我将其更改为

catch (Exception ex)
        {
            // Errormessage for now, of course should be made user-friendly
            ModelState.AddModelError("_FORM", ex.InnerException.Message);

            string[] list = new string[] { "1", "2", "3", "4", "5" };
            SelectList ratings = new SelectList(list);
            ViewBag.Ratings = ratings;

            return View(companyRating);
        }

0

看看这是否修复了它:

<label for="CategoryID" class="news">Category:</label>
<%= Html.DropDownList("CategoryId", null, "-- Select Category --", new { @class = "news" })%>

你能发布在 View 中准确的错误位置吗?这可能有助于我们更清楚地查看它。

另外,您能告诉我们在页面呈现时还是在提交后发生错误吗? - Ashok
在包含下拉列表的视图页面中进行发布时出现错误。我编辑了我的问题。 - ilija veselica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接