2009-03-23 18 views
2

J'utilise un formulaire AJAX pour mettre à jour un élément dans la base de données. Quand cela est fait, il retourne une vue partielle qui liste de nouveau tous les éléments et les affiche tous dans une table. Le problème se produit lorsque je dois ajouter une erreur modelstate dans mon action de contrôleur. Je ne veux pas renvoyer la liste d'éléments lorsqu'il y a une erreur modelstate car je veux montrer l'erreur à l'utilisateur en utilisant le message ValidationMessage. Ma pensée est que je pouvais faire quelque chose comme ça dans mon contrôleur:Modelstate avec Ajax Form

 [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 

Le problème est que lorsqu'une erreur de ModelState se produit, le vidéotex ModelState n'est pas retourné. Je soupçonne que c'est peut-être parce que je ne spécifie pas un ID cible de mise à jour. Mais je ne peux pas mettre un autre updatetargetid parce que j'en ai déjà un. Des idées?

Répondre

0

Très bien, je l'ai compris. Merci pour la réponse. Pour référence future, ce que je devais faire était de mettre en place un diviseur maître que tout mon contenu va dans. Ensuite, je fixe toujours updateTargetID à ce diviseur pour que le contenu qu'il affiche ne soit pas important, juste qu'il l'affiche. Cela s'avère en fait plus facile parce que vous n'avez pas à gaspiller les fonctions JavaScript en activant et désactivant d'autres balises div parce que vous n'en utilisez qu'une qui est continuellement mise à jour.

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

Doit fonctionner correctement pour réafficher votre formulaire d'édition avec des erreurs de validation et tous. ViewData est rempli à partir des données de publication.

Big mise à jour

J'ai fait quelques tests pour comprendre. Et est venu avec un projet de test de travail. voici quelques annonces:

Mon contrôleur d'essai

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

Mon Modifier Voir:

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

Mon Ajax partiel Modifier Voir

"%>

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

Et mon modèle TestData classe

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

avec ce code, il fonctionne exactement comme vous le souhaitiez. Notez que je ne transmets aucun modèle à une vue partielle dans mon action "Publier". L'affichage obtenu obtient toutes les valeurs dont il a besoin à partir d'une demande de publication.

+1

Merci. J'ai essayé ceci, mais le problème est que je pense que "return PartialView" retourne une nouvelle instance, qui n'est pas affichée sur la page. Comment puis-je l'afficher? – Austin

+0

Merci! Cela fonctionne, mais j'ai toujours un problème - changer le updatetargetid casse mon ancien updatetargetid. Lorsque la soumission du formulaire est valide, je souhaite réafficher les éléments d'actualité à l'aide de updatetargetid de "newsTable". Il n'y a aucun moyen d'avoir plusieurs ID de cible. – Austin