Состояние модели с формой Ajax - PullRequest
2 голосов
/ 23 марта 2009

Я использую форму 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

Проблема заключается в том, что при возникновении ошибки состояния модели данные представления состояния модели не возвращаются. Я подозреваю, что это возможно, потому что я не указываю идентификатор цели обновления. Но я не могу установить другой updatetargetid, потому что он у меня уже есть. Есть идеи?

Ответы [ 2 ]

5 голосов
/ 23 марта 2009
 if (!Model.IsValid)  {
    return PartialView("YourEditForm");
    }
    else 
    {
    return View("YourIndexView");
    }

Должно работать нормально для повторного отображения формы редактирования с ошибками проверки и прочим. ViewData заполняется из данных Post.

Большое обновление

Я провел некоторое тестирование, чтобы понять это. И придумали рабочий тестовый проект. вот некоторые списки:

Контроллер My Testing

 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>

My Ajax Partial Edit View

"%>

<%= 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; }
    }

с этим кодом он работает так, как вы хотели. обратите внимание, что я не передаю какую-либо модель частичному просмотру в своем действии "Редактировать". Представление, которое обрабатывается, получает все необходимые значения из запроса на публикацию.

0 голосов
/ 25 марта 2009

Хорошо, я понял это. Спасибо за ответ. Для дальнейшего использования мне нужно было установить один главный разделитель, в который входит весь мой контент. Затем я всегда устанавливаю updateTargetID для этого делителя, чтобы не имело значения, какой контент он отображает, только то, что он отображает его. На самом деле это оказывается проще, потому что вам не нужно тратить функции Javascript на включение и выключение других тегов div, потому что вы используете только тот, который постоянно обновляется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...