2010-08-19 8 views
1

Je demande parce que je ne peux pas obtenir ce code pour travailler. Je reçois une exception; "Le modèle de type 'ITOC.WebUI.Models.Contract' n'a pas pu être mis à jour." Ce qui ne semble pas très utile.MVC 2 UpdateModel - comment ça marche?

** EDIT ** L'exception ci-dessus a été résolue en raison d'une faute d'orthographe dans le préfixe, une "chaîne magique" classique. Maintenant, le problème est que rien n'est mis à jour! ** END EDIT **

Je dois admettre que je ne suis pas clair comment UpdateModel fonctionne, et je ne suis pas clair comment fonctionne le préfixe. Le viewmodel est spécifié dans la page Web;

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

et la ViewModelClass est

public class ContractViewModel 
{ 
    //private ITOCEntities db = new ITOCEntities(); 
    public Contract contract { get; set; } 
    public IList<ContractType> contractTypes { get; set; } 
    public IEnumerable<SelectListItem> contractTypesSelectList 
    { 
     get 
     { 
      return this.contractTypes.Select(item => new SelectListItem 
      { 
       Text = item.ContractType1, 
       Value = item.ContractTypeId.ToString() 
      }); 
     } 
    } 


    public Contact clientContact { get; set; } 
    public Contact contractAdministratorContact { get; set; } 

    public ContractViewModel() 
    { 
     using (var db = new ITOCEntities()) 
     { 
      this.contractTypes = db.ContractTypes.ToList(); 

      this.clientContact = new Contact(); 
      this.contractAdministratorContact = new Contact(); 
      this.clientContact.ContactTypeId = 
       db.ContactTypes.Where(x => x.ContactType1 == "Client").SingleOrDefault().ContactTypeId; 
      this.contractAdministratorContact.ContactTypeId = 
       db.ContactTypes.Where(x => x.ContactType1 == "CA").SingleOrDefault().ContactTypeId; 
     } 
    } 
    public ContractViewModel(int contractId) 
    { 
     using (var db = new ITOCEntities()) 
     { 
      this.contractTypes = db.ContractTypes.ToList(); 
      this.contract = db.Contracts.Where(x => x.ContractId == contractId).SingleOrDefault(); 
      this.clientContact = 
       db.Contacts.Where(x => x.ContactId == this.contract.ClientContactId).SingleOrDefault(); 
      this.contractAdministratorContact = 
       db.Contacts.Where(x => x.ContactId == this.contract.ContractAdministratorContactId).SingleOrDefault(); 

     } 
    } 
} 

le contrôleur est;

[Authorize(Roles = "Inputter")] 
[HttpPost] 
public ActionResult Edit(int contractId, FormCollection formValues) 
{ 
    if (ModelState.IsValid) 
    { 
     using (var db = new ITOCEntities()) 
     { 
      var contract = db.Contracts.Single(x => x.ContractId == contractId); 
      string letter = contract.ContractNo_Letter; 

      UpdateModel(contract, "Contracts"); 

      var clientContact = db.Contacts.Single(x => x.ContactId == contract.ClientContactId); 
      UpdateModel(clientContact, "Contact"); 
      var contractAdministrationContact = 
       db.Contacts.Single(x => x.ContactId == contract.ContractAdministratorContactId); 
      UpdateModel(contractAdministrationContact, "Contact"); 
      db.SaveChanges(); 
     } 

     return RedirectToAction("List"); 
    } 
    return View(); 
} 
+0

avez-vous essayé ce que j'ai suggéré? – hunter

+0

Oui, voir le commentaire sous votre nom. – arame3333

+0

Je pense que le problème est le nom du préfixe. Le nom de la classe est "Contract", mais cela génère une exception, tout comme "contract". "Contrats" ne lance pas d'exception, mais n'est pas mis à jour non plus. – arame3333

Répondre

3

essayez d'utiliser TryUpdateModel dans une instruction if/else

if (TryUpdateModel(contract)) 
{ 
    // save changes 
} 
else 
{ 
    // handle 
} 

TryUpdateModel et UpdateModel sont destinés à être utilisés pour fusion un objet avec un objet modèle affiché.

Met à jour l'instance de modèle spécifié en utilisant des valeurs de fournisseur de valeur actuelle du contrôleur.

Essayez de lire this post au sujet de ces deux méthodes.


essayez de changer votre méthode d'action post pour correspondre à votre modèle objet

[Authorize(Roles = "Inputter")] 
[HttpPost] 
public ActionResult Edit(ContractViewModel model) 
{ 
    // 
} 

si les id sur votre match de formulaire pour les propriétés de votre objet ContractViewModel puis model affichera avec ces valeurs

+0

Oui, quand je le fais, l'une des propriétés de l'objet renvoie une exception nulle. Est-ce que cela montre quel est le problème, que je dois remplir chaque champ avec un validateur de champ obligatoire, même si ce champ n'est pas dans le formulaire? – arame3333

+0

Si vous avez une entrée masquée dans le formulaire avec l'ID que vous utilisez, vous pouvez charger cet objet en fonction de cet ID. Puis appelez UpdateModel (myloadedobject) et il fusionnera les éléments sur la page soumise et ignorera les propriétés qui ne le sont pas. – hunter

+0

J'ai fait les champs HiddenFor sur mon formulaire. Cependant dans le Controller ModelView, je reçois toujours une exception nulle pour l'un de ces champs – arame3333

0

Quelques choses que j'ai remarquées tout de suite:

  1. Vous ne disposez pas d'un ViewModel spécifié dans votre affichage. Cette ligne signifie ici une vue avec aucun type modèle spécifique:

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

  2. Sans voir la vue, nous ne pouvons pas être sûr de ce que vous essayez de lier ici, ou même si vous devez utiliser un préfixe.

  3. Vous ne passez pas la collection FormValues ​​dans UpdateModel.Essayez: UpdateModel(contract, "Contract", formValues)

+0

il y a un ViewModel là – hunter

+0

Il y a quelque chose de marrant dans le balisage. J'ai essayé de l'éditer, mais dans la vue d'édition le balisage est correct! Donc, ce que vous devez voir est ceci; <% @ Page Title = "" Language = "C#" MasterPageFile = "~/Vues/Partagé/Site.Master" Inherits = "System.Web.Mvc.ViewPage "%> – arame3333

+0

Je viens d'éditer la question après avoir trouvé un bug ... – arame3333

1

Pour voir ce qui a échoué, regardez vos entrées Controller.ModelState. Cela vous dira ce qui n'a pas réussi à lier. Dans mon expérience, il s'agit généralement d'une discordance de type de données.


1 et 3 de la réponse de CubanX n'ont pas vraiment d'impact sur les erreurs ModelBinding. 2 peut être ignoré parce que si vous obtenez une erreur de liaison, vous savez qu'elle est probablement contraignante et que vous n'avez probablement pas à vous soucier du préfixe.

+0

Le Controller.ModelState contient uniquement le ContractId. Est-ce le problème pensez-vous? – arame3333