tags:

views:

84

answers:

3

I ask because I cannot get this code to work. I get an exception; "The model of type 'ITOC.WebUI.Models.Contract' could not be updated." Which does not seem very helpful.

** EDIT ** The above exception has been resolved because of a spelling mistake in the prefix, a classic "Magic String". Now the problem is that NOTHING GETS UPDATED! ** END EDIT **

I have to admit I am not clear how UpdateModel works, and I am not clear how the prefix works. The viewmodel is specified in the webpage;

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

and the ViewModelClass is

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

        }
    }
}

The Controller is;

[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();
}
+1  A: 

try using TryUpdateModel in an if/ else statement

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

TryUpdateModel and UpdateModel are intended to be used to merge an object with a posted model object.

Updates the specified model instance using values from the controller's current value provider.

Try reading this post about these two methods.


try changing your Post Action Method to match your Model Object

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

if the id's on your form match to the properties of your ContractViewModel object then model will post with those values

hunter
Yes, when I do that one of the object properties returns a null exception. does this show what the problem is, that I have to populate every field with a required field validator, even though that field is not in the form?
arame3333
If you have a hidden input on the form with the ID you're using you can load that object based on that ID. Then call UpdateModel(myloadedobject) and it will merge items on the submitted page and ignore properties that aren't.
hunter
I have made the fields HiddenFor on my form. However in the Controller ModelView, I still get a null exception for one of these fields
arame3333
can you update your code above and give me a vote?
hunter
A: 

A few things I noticed right off:

  1. You don't have a ViewModel specified in your view. This line here means a View with no type specific model:

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

  2. Without seeing the view, we can't be sure what you're trying to bind to here, or even if you should be using a prefix.

  3. You're not actually passing in the FormValues collection into UpdateModel. Try:UpdateModel(contract, "Contract", formValues)

CubanX
there's a ViewModel there
hunter
There is something funny about the markup. I tried to edit it, but in the edit view the markup is correct!So what you need to see is this;<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ITOC.WebUI.Models.ContractViewModel>" %>
arame3333
I have just edited the question after finding a bug...
arame3333
Did you try passing the formValues to UpdateModel? Also, can you post the View code?
CubanX
I tried passing on the formValues. The formValues are correct, but they do not seem to update the class.
arame3333
I think at this point we really need to see the View code to be able to help further, can you add that to the question?
CubanX
+1  A: 

To see what failed look at your Controller.ModelState entries. That will tell you what failed to bind. In my experience its usually a datatype mismatch.


1 and 3 of CubanX's answer don't really have any impact on ModelBinding errors. 2 can be ignored because if your getting a bind error you know its probably binding and probably don't have to worry about the Prefix.

jfar
The Controller.ModelState only contains the ContractId. Is this the problem do you think?
arame3333