I’m using an AJAX form to update an item to the database. When it gets done, it returns a partial view that re-lists all the items and displays them all in a table. The problem occurs when I have to add a modelstate error in my controller action. I don’t want to return the list of items when there is a modelstate error because I want to show the user the error using the ValidationMessage. My thinking is that I could do something like this in my controller:
[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
The problem is that when a modelstate error occurs, the modelstate viewdata isn’t returned. I suspect it’s possibly because I’m not specifying an update target id. But I can’t set another updatetargetid because I already have one. Any ideas?
Alright, I’ve figured it out. Thanks for the response. For future reference, what I had to do was set up one master divider that all of my content goes into. Then, I always set the updateTargetID to that divider so that it doesn’t matter what content it displays, just that it displays it. This actually turns out to be easier because you don’t have to waste Javascript functions setting other div tags on and off because you’re only using one that is continuously updated.