2

我正在使用 AJAX 表单将项目更新到数据库。完成后,它会返回一个局部视图,重新列出所有项目并将它们全部显示在一个表格中。当我必须在控制器操作中添加模型状态错误时,就会出现问题。当出现模型状态错误时,我不想返回项目列表,因为我想使用 ValidationMessage 向用户显示错误。我的想法是我可以在我的控制器中做这样的事情:

       [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult UpdateNewsItem(int newsID, string newsTitle, string newsDescription, string newsBeginningDate, string newsEndingDate)
    {
        List<Models.News> lstNewsItem = new List<News>();

        //we need to grab the member so we can capture the user id 
        //for the corresponding news property
        MembershipUser member = Membership.GetUser(User.Identity.Name);

        //the news instance to use in case the viewdata is invalid
        Models.News newsError = new Models.News();

        //create the datetime objects
        DateTime dtBeginningDate = DateTime.MinValue;
        DateTime dtEndingDate = DateTime.MaxValue;

        //the message we want to send whenever the user enters an invalid date
        string strInvalidDateError = "Invalid date.  Please use a format like '12/25/2008'";

        //clean user input
        newsTitle = Models.clsGlobals.CleanString(newsTitle);
        newsDescription = Models.clsGlobals.CleanParagraph(newsDescription);

        //newsTitle 
        if (string.IsNullOrEmpty(newsTitle))
        {
            newsError.Title = string.Empty;
            ModelState.AddModelError("newsTitle", "You must enter a news title.");
        }

        //description
        if (string.IsNullOrEmpty(newsDescription))
        {
            newsError.Description = string.Empty;
            ModelState.AddModelError("newsDescription", "You must enter a news description.");
        }

        //beginningDate
        if (string.IsNullOrEmpty(newsBeginningDate))
        {
            ModelState.AddModelError("newsBeginningDate", "You must enter a beginning date.");
        }

        //endingDate
        if (string.IsNullOrEmpty(newsEndingDate))
        {
            ModelState.AddModelError("newsEndingDate", "You must enter an ending date.");
        }

        //set the beginning date 
        try
        {
            dtBeginningDate = DateTime.Parse(newsBeginningDate);
            newsError.BeginningDate = dtBeginningDate;
        }

        catch (FormatException)
        {
            ModelState.AddModelError("newsBeginningDate", strInvalidDateError);
        }

        //set the ending date
        try
        {
            dtEndingDate = DateTime.Parse(newsEndingDate);
            newsError.EndingDate = dtEndingDate;
        }

        catch (FormatException)
        {
            ModelState.AddModelError("newsEndingDate", strInvalidDateError);
        }

        //data is validated, so we can begin the update
        if (ModelState.IsValid == true)
        {

            try
            {
                //use to perform actions on db
                Models.NewsDataContext dcNews = new Models.NewsDataContext();

                //fetch the items that match what the user requested to edit
                lstNewsItem = this.GetNewsItem(newsID);

                //set news properties
                foreach (Models.News news in lstNewsItem)
                {

                    news.UserId = (Guid)member.ProviderUserKey;
                    news.Title = newsTitle;
                    news.Description = newsDescription;
                    news.EntryDate = DateTime.Now;
                    news.BeginningDate = dtBeginningDate;
                    news.EndingDate = dtEndingDate;

                }//next

                //update the transaction
                dcNews.SubmitChanges();

                //update the news list
                return PartialView("NewsList", this.GetNewsItems());

            }

            //just to make sure everything goes as planned,
            // catch any unhandled exceptions
            catch (Exception ex)
            {
                ModelState.AddModelError("_FORM", ex);
            }//end catch

        }//end if valid modelstate


        //invalid modelstate, so repopulate the viewdata and
        //send it back

        //the list to hold the entries
        List<Models.News> lstErrorNewsItems = new List<Models.News>();

        //set the remaining error properties
        newsError.UserId = (Guid)member.ProviderUserKey;
        newsError.NewsID = newsID;
        newsError.EntryDate = DateTime.Now;

        //add the item--there will only be one
        //but the view is expecting a list so we will
        //treat it like one
        lstErrorNewsItems.Add(newsError);

        return PartialView("EditNews", lstErrorNewsItems);

    }//end actionresult

问题是当发生模型状态错误时,模型状态视图数据不会被返回。我怀疑这可能是因为我没有指定更新目标 ID。但是我不能设置另一个 updatetargetid 因为我已经有了一个。有任何想法吗?

4

2 回答 2

5
 if (!Model.IsValid)  {
    return PartialView("YourEditForm");
    }
    else 
    {
    return View("YourIndexView");
    }

应该可以很好地重新显示带有验证错误和所有内容的编辑表单。ViewData 从 Post 数据中填充。

大更新

我做了一些测试来弄清楚。并提出了一个有效的测试项目。以下是一些清单:

我的测试控制器

 public class TestController : Controller
    {
                 //
        // GET: /Test/
        List<TestData> data;
        public TestController()
        {
            data = new List<TestData>();
            for (var i = 0; i < 10; i++)
            {
                data.Add(new TestData(){Name=string.Format("TestData{0}",i.ToString().PadLeft(4,'0'))});
            }
        }

        public ActionResult Index()
        {


            return View( data);
        }

        public ActionResult Edit(string name)
        {
            if (Request.IsAjaxRequest())
            {
                return PartialView("AjaxEdit", new TestData() { Name = name });
            }

            return View(new TestData() { Name = name });
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(TestData testData)
        {
            ModelState.AddModelError("name", "incorrect name");
            if (!ModelState.IsValid)
            {
                if (Request.IsAjaxRequest())
                {
                    return PartialView("AjaxEdit");
                }


            }

            return View();
        }
    }

我的编辑视图:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<AjaxValidationPartial.Models.TestData>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Edit
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Edit</h2>
    <div id="editForm">
<% Html.RenderPartial("AjaxEdit",Model );%>
</div>
</asp:Content>

我的 Ajax 部分编辑视图

" %>

<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>

<% using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "editForm" }))
   {%>

    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="Name">Name:</label>
            <%= Html.TextBox("Name")%>
            <%= Html.ValidationMessage("Name", "*")%>
        </p>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>

<% } %>

<div>
    <%=Html.ActionLink("Back to List", "Index") %>
</div>

还有我的 TestData 模型类

  public class TestData
    {
        public string Name { get; set; }
    }

使用此代码,它可以按您的意愿工作。 请注意,我没有在“发布”编辑操作中将任何模型传递给局部视图。被渲染的视图从发布请求中获取它需要的所有值。

于 2009-03-23T13:40:25.037 回答
0

好吧,我已经想通了。感谢您的回复。为了将来参考,我必须做的是设置一个主分隔器,我的所有内容都放入其中。然后,我总是将 updateTargetID 设置为该分隔符,以便它显示的内容无关紧要,只需显示它即可。这实际上更容易,因为您不必浪费 Javascript 函数来打开和关闭其他 div 标签,因为您只使用一个不断更新的标签。

于 2009-03-25T00:30:36.150 回答