3

I have created a visualforce page that displays both opportunity and contact fields that I want users to be able to edit and save. I am using the opporutnity standard controller and added the following extension so as to be able to override (or add to) the standard save functionality with the 'SaveBoth' method (below). I am having trouble populating the contact object with the correct related record data.

I am recieveing the following error:

"Invalid foreign key relationship: Opportunity.AccountId"

public with sharing class NewLeadControllerExtension 
{
    ApexPages.StandardController controller;
    public Opportunity oppt {get; set;}
    public Contact cont {get; set;}

    public NewLeadControllerExtension(ApexPages.StandardController controller)
    {
        this.controller = controller;
        oppt = (Opportunity)controller.getRecord();
        cont = new Contact();
        cont.Id = oppt.Account.Contact.Id;
        //cont.AccountId = oppt.AccountId;
    }
    public PageReference SaveBoth()
    {
        controller.Save();
        update cont; 
        return null;
    }
}

I also tried using the line commented out in the code above instead of the line above it

cont.AccountId = oppt.AccountId

and received an

"MISSING_ARGUMENT, Id not specified in an update call"

Any advice on how to populate the contact Id correctly?

Thanks!

I have researched everything I could find on this subject but still haven't managed to solve it. The code base I started from initially can be found at Visualforce - Display fields from multiple objects

2 Answers 2

2

From the code you have posted, I see two issues with these lines of code:

cont = new Contact();
cont.Id = oppt.Account.Contact.Id;

Firstly, you aren't supposed to use an ID field that way. (EDIT:I should have said you SHOULDN'T use an ID field that way for an edit page. It is a perfectly valid way of doing it in some situations, as pointed out below). If it is an existing contact you should query it:

cont = [select id, whatever from Contact where Id = :x];

Which brings me to the second issue. You can't go from Account down to a contact, unless you have an additional lookup relationship to Contact (though I wouldn't really recommend that). I'm not even sure what you are trying to do with that line.

5
  • Thank you for your response! What I am attempting to do is to instantiate a contact object, populate it with the correct values that are related to the opportunity (through Id relationship) , and then update it with any changes from the user Visualforce page. Basically I want the save operation to save both the standard primary object (Opportunity) AND the related object (Contact) at the same time. Hope that makes sense. Regards Commented Apr 23, 2015 at 3:24
  • Hey raffters, setting an id like this is actually a legit way to do updates. Very useful in situations where you're close to the SOQL query limit for instance and is more performant overall.
    – Matt Lacey
    Commented Apr 23, 2015 at 3:54
  • 1
    Thanks @LaceySnr I didn't mean to mislead anyone. I personally find that way to be of rather limited use, but opinions will vary.
    – raffters
    Commented Apr 23, 2015 at 14:12
  • @DavidLeckenby - The question I intended raise (though didn't do well reading it while more awake), was: How are the Opportunity and Contact related?
    – raffters
    Commented Apr 23, 2015 at 14:15
  • Thanks @raffters Opportunity is related to Contact through the Account object. From the Opportunity there is a many to one relationship with Account and from Account to Contact there is a one to many relationship. Also Contact records can be queried as they have the exact same name as the Account record. Regards Commented Apr 24, 2015 at 0:40
1

Do you have a lookup to contact from the Account or are you using person accounts?

If the former, then your field would be called something like Contact__c at a guess and you'd want to do:

cont.Id = oppt.Account.Contact__c;

If the latter, then the field will be oppt.Account.ContactId if I remember correctly.

If you're not using either of those approaches then you need to query for a contact to use, as contacts are child records of accounts, not the other way around, meaning an account could have many contacts and not just one.

6
  • Many Thanks Matt! Our org is not configured for Personal Accounts (even though they use Business and Personal Account record types). Anyhow I think what you suggested is right about querying the contact. So I declared and instantiated an Account object and then added the following code acct.id = oppt.AccountId; cont.Id = [SELECT Contact.id FROM Contact WHERE Contact.Name = Account.Name]; I am now getting an invalid binding expression error....Thanks so much for your help :) Commented Apr 23, 2015 at 7:37
  • Hi Matt. I have worked more on this issue but still have not succeeded in being able to update the contact object (the opportunity saves no problem). I have with your assistance added a query statement that enables me to acquire the correct contact id, but I still cannot mange to update any contact fields on the visualforce page? Commented Apr 24, 2015 at 4:20
  • Is the page writing to that contact object which is initiated in the controller? Looks like it should be working, just make sure you're not creating a new contact in memory on save.
    – Matt Lacey
    Commented Apr 24, 2015 at 4:26
  • There is only one visualforce page which has a standard opportunity controller and the controller extension shown above. Could I post you the page to look at? If so, where would be the best place to do that, in this comment field? Commented Apr 29, 2015 at 23:58
  • The best bet is to edit the question, but I suspect you don't have the rep for that. If you can't, post it as a comment and I'll do it for you.
    – Matt Lacey
    Commented Apr 30, 2015 at 0:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .