Desktop and UI Extensibility

Get Involved. Join the Conversation.

Topic

    Shiloh Madsen
    IContact vs Contact difference/best practiceAnswered
    Topic posted January 3, 2019 by Shiloh MadsenBronze Trophy: 5,000+ Points 
    53 Views, 6 Comments
    Title:
    IContact vs Contact difference/best practice
    Summary:
    Trying to understand when to use which object
    Content:

    This one has tripped me up on a number of occasions and I go down a rabbit hole every time I run into this blocker. I'm trying to understand when you would use I<Object> vs just <Object> It seems like the methods available and even the attributes available to each of these objects change based on cast. You can't cast back and forth between them, so I always end up having a problem where I need to hit an attribute of an i<object> that isn't as clearly exposed, or i need to iterate through an <object> which doesn't have iterable methods. What I want to understand is, is there an appropriate context for each to be used in an addin, or does best practices dictate trying to stick to just the i<object> version, which it seems most code examples speak to. 

    Best Comment

    Ron Van Aken

    Shiloh,

    I agree that it's challenging to use two representations for the same type of object.  They're similar in some respects, but not the same.

    If you're working on an Add-In, your Add-In code is between the workspace and the database.  Interacting with the workspace is done through interfaces (IContact).  You can imagine that the workspace does not need to know about the database schema for a given field, but the workspace interface is sufficient.  Interacting with the database is done through an object-relational mapping (https://en.wikipedia.org/wiki/Object-relational_mapping).  These objects need to be detailed enough to give you access to virtually any column of any table.  It should be rare to be truly stuck in the middle translating data back and forth between the workspace and the database.  Oracle takes care of that if your data is structured well.

    You mentioned as an example that you cannot iterate over a collection of contacts returned by ROQL. The following link shows an example of iterating over a collection of Contacts:

    http://documentation.custhelp.com/euf/assets/devdocs/february2015/Connect_Web_Services_for_SOAP/Default.htm

    Maybe there's an issue with what you are specifically trying to do, but I've done something similar with iterating over a collection of GenericObjects returned from a ROQL query.

    Thinking about your question helped me understand the API better.  I'd be happy to help more.

    Please feel free to share more about the specific issue(s) you're having.

    Thanks,
    Ron

    Comment

     

    • Robert Surujbhan

      Hi Shiloh,
      Do you typically work with both the Desktop Add-In Framework (the .NET API) and the Connect Web Services for SOAP, in the same .NET C# project?  If so, that’s how you can best identify the differences.

      The Add-In Framework (for building agent desktop console Add-Ins) is where you will see the I<Object> interfaces like IContact and IIncident.  In a Visual Studio project, you get access to these types when you declare the below namespace directive in the file.

      using RightNow.AddIns.AddInViews;
      

      Built-in methods of the Add-In Framework like GetWorkspaceRecord() will return interface instances of these objects.  Example:  

      IContact c = _recordContext.GetWorkspaceRecord(RightNow.AddIns.Common.WorkspaceRecordType.Contact) as IContact;
      

      Conversely, in a .NET C# project, when you add a Service Reference with the Service Cloud WSDL, and once the service definition is imported successfully, Visual Studio will generate the necessary "proxy classes" for the various objects defined in the Service Cloud CCOM library. In a class file of your VS project, you get access to these when you declare the namespace of the service reference using the name you assigned.

      using TheProjectNamespace.TheServiceReferenceName;
      

      ...and that’s where you will get access to the <Object> classes (e.g., Contact, Incident, Account, etc).

      Contact c = new Contact();
      

      In summary, the syntax and coding difference is going to depend on using the Add-In Framework or the Connect Web Services (SOAP) API.  Both can be used in the same C# project, or each can be used in their own project – depends on what you are doing.  For example, a desktop console Add-In can retrieve an object reference from a workspace, and then call the SOAP API to perform an operation on that object (like an Update).  In this scenario for a contact record, you’d use both the IContact interface and the Contact object class within your C# code – but you’d access and/or set them separately since they don’t inter-cast across each other. 

      Does this help?

      • Shiloh Madsen

        Yes, it helps.but it leaves me with the problem of retrieving an object collection via ROQL and then working on it within .net. The collection of objects that ROQL retrieves isnt an interface instance so working with it becomes annoyingly challenging. So lets say I use ROQL to retrieve a group of contacts, I then want to iterate over each contact in .net and set some custom field. This process does not seem at all transparent as iteration over objects seems to be limited to the I<object> version, not the roql ones. Am I just approaching this wrong, or is this actually a pain point?

    • Ron Van Aken

      Shiloh,

      I agree that it's challenging to use two representations for the same type of object.  They're similar in some respects, but not the same.

      If you're working on an Add-In, your Add-In code is between the workspace and the database.  Interacting with the workspace is done through interfaces (IContact).  You can imagine that the workspace does not need to know about the database schema for a given field, but the workspace interface is sufficient.  Interacting with the database is done through an object-relational mapping (https://en.wikipedia.org/wiki/Object-relational_mapping).  These objects need to be detailed enough to give you access to virtually any column of any table.  It should be rare to be truly stuck in the middle translating data back and forth between the workspace and the database.  Oracle takes care of that if your data is structured well.

      You mentioned as an example that you cannot iterate over a collection of contacts returned by ROQL. The following link shows an example of iterating over a collection of Contacts:

      http://documentation.custhelp.com/euf/assets/devdocs/february2015/Connect_Web_Services_for_SOAP/Default.htm

      Maybe there's an issue with what you are specifically trying to do, but I've done something similar with iterating over a collection of GenericObjects returned from a ROQL query.

      Thinking about your question helped me understand the API better.  I'd be happy to help more.

      Please feel free to share more about the specific issue(s) you're having.

      Thanks,
      Ron

      • Shiloh Madsen

        Thanks Ron, 

        I've actually solved my issue already, but it is an issue that when I came up against it made me question if I took the right path just from a best practices perspective. Let me outline what I did and you can perhaps indicate if there was a better ideal solution. I needed to retrieve a list of organizations given a list of OIDs. I used ROQL to retrieve this list, which returned the the Object mapping instance of the objects. 

        Once I had my list of ROQL objects, I needed to go through each organization and retrieve a custom field value for display in a grid. Iterating over the returned collection of objects was...challenging to say the least. In tinkering I saw that while iteration was challenging in a collection of Organizations, I saw different problems when I managed to retrieve it as a collection of IOrganizations, namely getting at the addresses was not at all clear...so one representation made the custom fields easier to get to, while the other made the addresses (and one assumes phone numbers) easier to get to. 

        This was frustrating as it felt like I was being pushed to potentially interact with the non ideal representation of an object to get at the data I want most easily, rather than simply saying "I'm doing this in an addin, I should use the object interface". (Assuming of course that this is even the proper mindset). 

        To be clear, at this point my problem is solved, but I find such public discussion of best practices helpful to me trying to always improve as well as hopefully very instructional for new users to the ecosystem who may be experiencing a lot of this for the first time, so your thoughts are certainly illuminating despite the actual initial issue being resolved. 

        • Ron Van Aken

          Shiloh,

          Your approach seems reasonable.

          The only other improvement I can think of would be dependent on a parent/child relationship between an ID your main workspace record and the collection of organizations.  If such a relationship exists OSC will do nearly all the work of collecting the records and displaying them in a list (report) typically on a tab in your workspace.  Without the particulars, I don't know if that applies in your case.

          As an example, I have 2 custom object record types. One is a primary record that corresponds to a workspace.  The other object record type is a child record.  Each child that corresponds to the parent contains the parent's ID.  In the workspace, I do nothing to query the child records.  I only created a report for the child records that filters based on the parent ID, and added that report to a tab in the workspace.  All of the data loads with the workspace.  Given a workspace associated with the child records they can be edited from the report.

          Please let me know what you think.

          Thanks,

          Ron

          • Shiloh Madsen

            Yeah, agreed, in the case of simple display the parent/child behavior avoids all addin work. What I was doing here was changing incident attributes based on a many to many association. I'm trying to strongarm contact-org to be many to many which means I had to build a custom object to store the relationship, build an addin to retrieve the list of related orgs, and then use that addin to associate the org to the incident (then another to keep OSVC from overwriting my org on the incident on save...Oracle really doesnt want a contact to have more than one org...)

            That was what I was doing now, but I've run into the problem a lot in the past where I wanted to iterate through an ROQL result and found that only the I<Object> types are iterable, so I had to jump through hoops to do what i needed.