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 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
    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
    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
    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 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 :) 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? 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
    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? 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
    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 .