• venturec3
  • NEWBIE
  • 75 Points
  • Member since 2012

  • Chatter
    Feed
  • 3
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 7
    Questions
  • 7
    Replies
Is there a way to dynamically cast an sobject using the name of that object as a string?

For example, generally if I'm updating a specific sobject, I might do something like:

Account acct = new Account();
acct.Name = "Test Account";

List<Account> accountList = new List<Account>();
accountList.add(acct);

SaveResult[] sr = prodConnection.upsert(accountList.ToArray());

However, I may not know whether the user selects an Account, Contact or Opportunity, etc.?

What solutions have others come up with on this when inserting/upserting records into Salesforce from C#?
How come I can't dynamically cast a QueryResult to an sObject and view the values without have to cast the result to a difinitive sObject? I've been able to view returned values from a query within Microsoft Access, loop through the queryresult and then insert record values into the appropriate tables without having to specifiy whether it is an Account or Contact, or Lead, etc.

Instead of having to do something like:
sObject s = new Account();
Account a = Account(s).

Why can't I just loop through the sObject records and retrieve the values?

I'm working on an integration piece and the sObject type has to be dynamic. I cannot cast it to a specific sobject every single time I need to retrieve records.

try
                    {
                        QueryResult qResult = sfProd.query(strSelectStatement);
                        sObject[] s = qResult.records;
                       
                        Boolean done = false;

                        if (qResult.size > 0)
                        {
                            while (!done)
                            {
                                // foreach statement cannot operate on variables of type QueryResult because QueryResult does not contain a public definition for GetEnumerator
                                //foreach (QueryResult q in qResult)
                                //{
                                //}
                               
                                for (Int32 j = 0; j < qResult.records.Length; j++)
                                {
                                    MessageBox.Show(s[j].GetType().ToString());
                                    MessageBox.Show(s[j].GetType().Name);
                                    //MessageBox.Show(s[j].GetType().GetFields("Name").ToString());
                                    MessageBox.Show(s[j].Id.ToString());
                                }

                                if (qResult.done)
                                {
                                    done = true;
                                }
                                else
                                {
                                    qResult = sfProd.queryMore(qResult.queryLocator);
                                }
                               
                            }
                        }
                    }
                    catch (SoapException e)
                    {
                        MessageBox.Show(e.Message);
                    }

We have an approval process in place where the Next Automated Approver is determined by the Manager. However, at the CEO level, we are trying to submit his expenses for approval to another user who will then approve them. This is for tracking purposes really and we are not expecting him to enter in his own time and expenses. However, since he is at the top level, we can't assign him a manager because when I do, the error message comes up:

 

You cannot set a hierarchy field to point to itself or a child record.

 

Any suggestions on how to allow everyone in the org, including the top maanger, to submit their expenses and timecards for approval? Has anyone else run into this issue before and what did you do?

 

Thanks

public class TaskController {

...
    public Task objTask {
        get
        { 
           if(objTask == null) objTask = new Task();
           return objTask;
        }
        
        set;
    }

...
}


    <apex:form >
        <apex:sectionHeader title="Change Due Date Section" />
        <h1>Enter new Due Date: </h1>
        <apex:inputField value="{!objTask.ActivityDate}"/>
    </apex:form>

 When I run a debug, the objTask.ActivityDate is always returning null no matter what value I put in the Date Picker field.

 

Any ideas why the values is not being returned properly to the custom controller?

 

Thanks.

I have a C# app that is successfully returning and writing the zip file with the Profiles to a folder, but even thought I am setting the objects I would like to retrieve the permissions for, it is only returning the following:

 

<?xml version="1.0" encoding="UTF-8"?> <Profile xmlns="http://soap.sforce.com/2006/04/metadata">     <userLicense>Salesforce</userLicense> </Profile>

 

I should be seeing custom objects and the profile permissions related to these objects.

 

The reason I need to use the C# app is because in the Force.com IDE, only unmanaged objects can be retrieved, and then viewed in the Profile metadata. In the C# application, all objects, whether managed or unmanaged are returned. I've tested this out using the CustomObject and have returned all custom objects in a zip file.

 

So here is a portion my code. Please let me know if there are any questions. Would like to get this figured out. I'm not that Familiar with Java, but if you have some Java code as an example, that would also be very helpful.

 

       

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Windows.Forms;
using SalesforceMetaDataApplication.WebReference;
using SalesforceMetaDataApplication.SFMetadata;
using SForceOfficeToolkitLib4;


namespace SalesforceMetaDataApplication
{
    public partial class MetaInfo : Form
    {

        public const double API_VERSION = 23.0;

        private SalesforceMetaDataApplication.WebReference.SforceService sf { get; set; }
        private SalesforceMetaDataApplication.WebReference.LoginResult lr { get; set; }
        private GetUserInfoResult userInfo { get; set; }

        private MetadataService metaService { get; set; }
        private List<FileProperties> lstFp { get; set; }
        private RetrieveResult result { get; set; }

        private Dictionary<String, SalesforceMetaDataApplication.WebReference.Profile> dictProfile 
            = new Dictionary<String, SalesforceMetaDataApplication.WebReference.Profile>();
        private Dictionary<String, SalesforceMetaDataApplication.WebReference.User> dictUser
            = new Dictionary<String, SalesforceMetaDataApplication.WebReference.User>();

        private List<String> lstSObjects = new List<String>();
        private List<CustomField> lstFields = new List<CustomField>();

        // Initialize the class with parameters from SFLogin. Get the Profiles, Users, and all SObjects in the org.
        public MetaInfo(SforceService sfService, MetadataService ms, LoginResult lResult, GetUserInfoResult uInfo)
        {
            InitializeComponent();
            
            sf = new SalesforceMetaDataApplication.WebReference.SforceService();
            lr = new SalesforceMetaDataApplication.WebReference.LoginResult();
            metaService = new MetadataService();
            userInfo = new GetUserInfoResult();

            this.sf = sfService;
            this.lr = lResult;
            this.userInfo = uInfo;

            this.metaService = ms;

            getProfile();
            getUser();
            retrieveSObjects();
        }

        // Retrieve all SObjects
        private void retrieveSObjects()
        {
            try 
            {
                DescribeGlobalResult dgr = sf.describeGlobal();

                DescribeGlobalSObjectResult[] dgsr = dgr.sobjects;
                foreach (DescribeGlobalSObjectResult d in dgr.sobjects)
                {
                    lstSObjects.Add(d.name);
                }
            } 
            catch (Exception e)
            {
                MessageBox.Show("Could not retrieve the Sobjects from Salesforce. " + e.Message);
            }
        }

        // Package Types
        private void profileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            String strFolder = "Profile";
            String pckgType = "Profile";

            List<ProfileObjectPermissions> lstProfObjPerm = new List<ProfileObjectPermissions>();
            List<PackageTypeMembers> lstPtm = new List<PackageTypeMembers>();
            foreach(String s in lstSObjects) 
            {
                SFMetadata.ProfileObjectPermissions profObjPerm = new SFMetadata.ProfileObjectPermissions();
                profObjPerm.@object = s;
                lstProfObjPerm.Add(profObjPerm);
                
                SFMetadata.PackageTypeMembers objPckTypMembers = new SFMetadata.PackageTypeMembers();
                List<String> lstMembers = new List<String>();
                lstMembers.Add(s);
                objPckTypMembers.members = lstMembers.ToArray();
                lstPtm.Add(objPckTypMembers);

            }

            Package pck = new Package();
            pck.types = lstPtm.ToArray();

            SFMetadata.Profile objProfile = new SFMetadata.Profile();

            objProfile.objectPermissions = lstProfObjPerm.ToArray();

            // Call the methods to retrieve the profiles and zip file
            String[] profileFiles = listPackages(strFolder, pckgType);
            retrievePackages(profileFiles, pckgType, pck);

            MessageBox.Show("Extraction Complete.");
        }


        private String[] listPackages(String strFolder, String strType) {
            // can't use wildcards with reports, so need to fetch the list
            // of ReportFolders first, then fetch all the reports in
            // each folder.
            ListMetadataQuery q = new ListMetadataQuery();
            q.type = strFolder;

            FileProperties[] fp = metaService.listMetadata(new ListMetadataQuery[] { q }, API_VERSION);

            if (fp == null)
            {
                Console.WriteLine("No profile folders returned");
                return new String[0];
            }

            List<String> packageFiles = new List<String>();
            q.type = strType;
            foreach (FileProperties p in fp)
            {
                q.folder = p.fullName;
                // listMetadata can take more than one item at a time
                // left as an exercise for the reader to batch up these calls.
                FileProperties[] rps = metaService.listMetadata(new ListMetadataQuery[] { q }, API_VERSION);
                if (fp == null) continue;
                foreach (FileProperties rp in rps)
                {
                    Console.WriteLine("{0}", rp.fileName);
                    packageFiles.Add(rp.fullName);
                }
            }
            return packageFiles.ToArray();
        }

        // Overload methods to retrieve the different package types and write them to disk.
        // TODO: compress these methods into more reusable methods.
        private void retrievePackages(String[] packageFiles, String strMetaName, Package objPackage) 
        {
            // build up an unpackaged retrieve request for the list of reports.
            RetrieveRequest r = new RetrieveRequest();
            r.apiVersion = API_VERSION;
            //r.unpackaged = new Package();
            r.unpackaged = objPackage;

            PackageTypeMembers m = new PackageTypeMembers();
            m.name = strMetaName;
            m.members = packageFiles;
            r.unpackaged.types = new PackageTypeMembers[] { m };

            // start the retrieve request
            AsyncResult ar = metaService.retrieve(r);

            // wait for it to complete, sleeping as necassary.
            while (!ar.done)
            {
                System.Threading.Thread.Sleep(1000);
                ar = metaService.checkStatus(new String[] { ar.id })[0];
            }

            // did it work ?
            if (ar.state == AsyncRequestState.Error)
                Console.WriteLine("{0} {1}", ar.statusCode, ar.message);
            else
            {
                // now actually go get the results 
                RetrieveResult rr = metaService.checkRetrieveStatus(ar.id);
                if (rr.messages != null)
                    foreach (RetrieveMessage rm in rr.messages)
                        Console.WriteLine("{0} : {1}", rm.fileName, rm.problem);

                // write the zipFile out to a disk file.
                using (System.IO.FileStream fs = new System.IO.FileStream("c:\\Temp\\" + strMetaName + ".zip", System.IO.FileMode.Create))
                    fs.Write(rr.zipFile, 0, rr.zipFile.Length);
            }
        }

        private void retrievePackages(String[] packageFiles, String strMetaName)
        {
            // build up an unpackaged retrieve request for the list of reports.
            RetrieveRequest r = new RetrieveRequest();
            r.apiVersion = API_VERSION;
            r.unpackaged = new Package();

            PackageTypeMembers m = new PackageTypeMembers();
            m.name = strMetaName;
            m.members = packageFiles;
            r.unpackaged.types = new PackageTypeMembers[] { m };

            // start the retrieve request
            AsyncResult ar = metaService.retrieve(r);

            // wait for it to complete, sleeping as necassary.
            while (!ar.done)
            {
                System.Threading.Thread.Sleep(1000);
                ar = metaService.checkStatus(new String[] { ar.id })[0];
            }

            // did it work ?
            if (ar.state == AsyncRequestState.Error)
                Console.WriteLine("{0} {1}", ar.statusCode, ar.message);
            else
            {
                // now actually go get the results 
                RetrieveResult rr = metaService.checkRetrieveStatus(ar.id);
                if (rr.messages != null)
                    foreach (RetrieveMessage rm in rr.messages)
                        Console.WriteLine("{0} : {1}", rm.fileName, rm.problem);

                // write the zipFile out to a disk file.
                using (System.IO.FileStream fs = new System.IO.FileStream("c:\\Temp\\" + strMetaName + ".zip", System.IO.FileMode.Create))
                    fs.Write(rr.zipFile, 0, rr.zipFile.Length);
            }
        }
    }
}

 

Does anyone have any suggestions on how to troubleshoot a timeout issue with Queryresult? No matter what batch size I set the queryoptions to, it times out whether 5 records or 500 records.

 

I'm able to log in successfully, but when I run the query, the operation always times out.

Have any of you worked with the EncodingUtil.base64Decode() method? I have a client Carte Financial who is wanting to send an email automatically when a new file attachment has been added. The Body of the file attachment is in Base64 format. But all the examples that I've researched on the Salesforce blogs don't work. My current code is:

 

    for(Attachment attch : attchSubset) {

          

           // Create the attachment

           Messaging.Emailfileattachment efa = new Messaging.Emailfileattachment();

           efa.setFileName(attch.Name);

 

Get an error here stating that there is an invalid Base64 character and can’t convert it. If I just add the attachment with the Body in its Salesforce format, it doesn’t show properly.

           // Decrypt the attachment body and then set it.

           Blob body = EncodingUtil.base64Decode(attch.body.ToString());

           efa.setBody(body);

                   

           Messaging.Singleemailmessage mail = new Messaging.Singleemailmessage();

           list<String> emailAddr = new list<String>();

           emailAddr.add(mapContact.get(attch.ParentId).Email);

           mail.setToAddresses(emailAddr);

           mail.setPlainTextBody('Hi!');

           mail.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});

          

           // Send the Email Message

           Messaging.SendEmailResult[] r = Messaging.sendEmail(new  Messaging.Singleemailmessage[] {mail});

    }

How come I can't dynamically cast a QueryResult to an sObject and view the values without have to cast the result to a difinitive sObject? I've been able to view returned values from a query within Microsoft Access, loop through the queryresult and then insert record values into the appropriate tables without having to specifiy whether it is an Account or Contact, or Lead, etc.

Instead of having to do something like:
sObject s = new Account();
Account a = Account(s).

Why can't I just loop through the sObject records and retrieve the values?

I'm working on an integration piece and the sObject type has to be dynamic. I cannot cast it to a specific sobject every single time I need to retrieve records.

try
                    {
                        QueryResult qResult = sfProd.query(strSelectStatement);
                        sObject[] s = qResult.records;
                       
                        Boolean done = false;

                        if (qResult.size > 0)
                        {
                            while (!done)
                            {
                                // foreach statement cannot operate on variables of type QueryResult because QueryResult does not contain a public definition for GetEnumerator
                                //foreach (QueryResult q in qResult)
                                //{
                                //}
                               
                                for (Int32 j = 0; j < qResult.records.Length; j++)
                                {
                                    MessageBox.Show(s[j].GetType().ToString());
                                    MessageBox.Show(s[j].GetType().Name);
                                    //MessageBox.Show(s[j].GetType().GetFields("Name").ToString());
                                    MessageBox.Show(s[j].Id.ToString());
                                }

                                if (qResult.done)
                                {
                                    done = true;
                                }
                                else
                                {
                                    qResult = sfProd.queryMore(qResult.queryLocator);
                                }
                               
                            }
                        }
                    }
                    catch (SoapException e)
                    {
                        MessageBox.Show(e.Message);
                    }

public class TaskController {

...
    public Task objTask {
        get
        { 
           if(objTask == null) objTask = new Task();
           return objTask;
        }
        
        set;
    }

...
}


    <apex:form >
        <apex:sectionHeader title="Change Due Date Section" />
        <h1>Enter new Due Date: </h1>
        <apex:inputField value="{!objTask.ActivityDate}"/>
    </apex:form>

 When I run a debug, the objTask.ActivityDate is always returning null no matter what value I put in the Date Picker field.

 

Any ideas why the values is not being returned properly to the custom controller?

 

Thanks.

I have a C# app that is successfully returning and writing the zip file with the Profiles to a folder, but even thought I am setting the objects I would like to retrieve the permissions for, it is only returning the following:

 

<?xml version="1.0" encoding="UTF-8"?> <Profile xmlns="http://soap.sforce.com/2006/04/metadata">     <userLicense>Salesforce</userLicense> </Profile>

 

I should be seeing custom objects and the profile permissions related to these objects.

 

The reason I need to use the C# app is because in the Force.com IDE, only unmanaged objects can be retrieved, and then viewed in the Profile metadata. In the C# application, all objects, whether managed or unmanaged are returned. I've tested this out using the CustomObject and have returned all custom objects in a zip file.

 

So here is a portion my code. Please let me know if there are any questions. Would like to get this figured out. I'm not that Familiar with Java, but if you have some Java code as an example, that would also be very helpful.

 

       

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Windows.Forms;
using SalesforceMetaDataApplication.WebReference;
using SalesforceMetaDataApplication.SFMetadata;
using SForceOfficeToolkitLib4;


namespace SalesforceMetaDataApplication
{
    public partial class MetaInfo : Form
    {

        public const double API_VERSION = 23.0;

        private SalesforceMetaDataApplication.WebReference.SforceService sf { get; set; }
        private SalesforceMetaDataApplication.WebReference.LoginResult lr { get; set; }
        private GetUserInfoResult userInfo { get; set; }

        private MetadataService metaService { get; set; }
        private List<FileProperties> lstFp { get; set; }
        private RetrieveResult result { get; set; }

        private Dictionary<String, SalesforceMetaDataApplication.WebReference.Profile> dictProfile 
            = new Dictionary<String, SalesforceMetaDataApplication.WebReference.Profile>();
        private Dictionary<String, SalesforceMetaDataApplication.WebReference.User> dictUser
            = new Dictionary<String, SalesforceMetaDataApplication.WebReference.User>();

        private List<String> lstSObjects = new List<String>();
        private List<CustomField> lstFields = new List<CustomField>();

        // Initialize the class with parameters from SFLogin. Get the Profiles, Users, and all SObjects in the org.
        public MetaInfo(SforceService sfService, MetadataService ms, LoginResult lResult, GetUserInfoResult uInfo)
        {
            InitializeComponent();
            
            sf = new SalesforceMetaDataApplication.WebReference.SforceService();
            lr = new SalesforceMetaDataApplication.WebReference.LoginResult();
            metaService = new MetadataService();
            userInfo = new GetUserInfoResult();

            this.sf = sfService;
            this.lr = lResult;
            this.userInfo = uInfo;

            this.metaService = ms;

            getProfile();
            getUser();
            retrieveSObjects();
        }

        // Retrieve all SObjects
        private void retrieveSObjects()
        {
            try 
            {
                DescribeGlobalResult dgr = sf.describeGlobal();

                DescribeGlobalSObjectResult[] dgsr = dgr.sobjects;
                foreach (DescribeGlobalSObjectResult d in dgr.sobjects)
                {
                    lstSObjects.Add(d.name);
                }
            } 
            catch (Exception e)
            {
                MessageBox.Show("Could not retrieve the Sobjects from Salesforce. " + e.Message);
            }
        }

        // Package Types
        private void profileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            String strFolder = "Profile";
            String pckgType = "Profile";

            List<ProfileObjectPermissions> lstProfObjPerm = new List<ProfileObjectPermissions>();
            List<PackageTypeMembers> lstPtm = new List<PackageTypeMembers>();
            foreach(String s in lstSObjects) 
            {
                SFMetadata.ProfileObjectPermissions profObjPerm = new SFMetadata.ProfileObjectPermissions();
                profObjPerm.@object = s;
                lstProfObjPerm.Add(profObjPerm);
                
                SFMetadata.PackageTypeMembers objPckTypMembers = new SFMetadata.PackageTypeMembers();
                List<String> lstMembers = new List<String>();
                lstMembers.Add(s);
                objPckTypMembers.members = lstMembers.ToArray();
                lstPtm.Add(objPckTypMembers);

            }

            Package pck = new Package();
            pck.types = lstPtm.ToArray();

            SFMetadata.Profile objProfile = new SFMetadata.Profile();

            objProfile.objectPermissions = lstProfObjPerm.ToArray();

            // Call the methods to retrieve the profiles and zip file
            String[] profileFiles = listPackages(strFolder, pckgType);
            retrievePackages(profileFiles, pckgType, pck);

            MessageBox.Show("Extraction Complete.");
        }


        private String[] listPackages(String strFolder, String strType) {
            // can't use wildcards with reports, so need to fetch the list
            // of ReportFolders first, then fetch all the reports in
            // each folder.
            ListMetadataQuery q = new ListMetadataQuery();
            q.type = strFolder;

            FileProperties[] fp = metaService.listMetadata(new ListMetadataQuery[] { q }, API_VERSION);

            if (fp == null)
            {
                Console.WriteLine("No profile folders returned");
                return new String[0];
            }

            List<String> packageFiles = new List<String>();
            q.type = strType;
            foreach (FileProperties p in fp)
            {
                q.folder = p.fullName;
                // listMetadata can take more than one item at a time
                // left as an exercise for the reader to batch up these calls.
                FileProperties[] rps = metaService.listMetadata(new ListMetadataQuery[] { q }, API_VERSION);
                if (fp == null) continue;
                foreach (FileProperties rp in rps)
                {
                    Console.WriteLine("{0}", rp.fileName);
                    packageFiles.Add(rp.fullName);
                }
            }
            return packageFiles.ToArray();
        }

        // Overload methods to retrieve the different package types and write them to disk.
        // TODO: compress these methods into more reusable methods.
        private void retrievePackages(String[] packageFiles, String strMetaName, Package objPackage) 
        {
            // build up an unpackaged retrieve request for the list of reports.
            RetrieveRequest r = new RetrieveRequest();
            r.apiVersion = API_VERSION;
            //r.unpackaged = new Package();
            r.unpackaged = objPackage;

            PackageTypeMembers m = new PackageTypeMembers();
            m.name = strMetaName;
            m.members = packageFiles;
            r.unpackaged.types = new PackageTypeMembers[] { m };

            // start the retrieve request
            AsyncResult ar = metaService.retrieve(r);

            // wait for it to complete, sleeping as necassary.
            while (!ar.done)
            {
                System.Threading.Thread.Sleep(1000);
                ar = metaService.checkStatus(new String[] { ar.id })[0];
            }

            // did it work ?
            if (ar.state == AsyncRequestState.Error)
                Console.WriteLine("{0} {1}", ar.statusCode, ar.message);
            else
            {
                // now actually go get the results 
                RetrieveResult rr = metaService.checkRetrieveStatus(ar.id);
                if (rr.messages != null)
                    foreach (RetrieveMessage rm in rr.messages)
                        Console.WriteLine("{0} : {1}", rm.fileName, rm.problem);

                // write the zipFile out to a disk file.
                using (System.IO.FileStream fs = new System.IO.FileStream("c:\\Temp\\" + strMetaName + ".zip", System.IO.FileMode.Create))
                    fs.Write(rr.zipFile, 0, rr.zipFile.Length);
            }
        }

        private void retrievePackages(String[] packageFiles, String strMetaName)
        {
            // build up an unpackaged retrieve request for the list of reports.
            RetrieveRequest r = new RetrieveRequest();
            r.apiVersion = API_VERSION;
            r.unpackaged = new Package();

            PackageTypeMembers m = new PackageTypeMembers();
            m.name = strMetaName;
            m.members = packageFiles;
            r.unpackaged.types = new PackageTypeMembers[] { m };

            // start the retrieve request
            AsyncResult ar = metaService.retrieve(r);

            // wait for it to complete, sleeping as necassary.
            while (!ar.done)
            {
                System.Threading.Thread.Sleep(1000);
                ar = metaService.checkStatus(new String[] { ar.id })[0];
            }

            // did it work ?
            if (ar.state == AsyncRequestState.Error)
                Console.WriteLine("{0} {1}", ar.statusCode, ar.message);
            else
            {
                // now actually go get the results 
                RetrieveResult rr = metaService.checkRetrieveStatus(ar.id);
                if (rr.messages != null)
                    foreach (RetrieveMessage rm in rr.messages)
                        Console.WriteLine("{0} : {1}", rm.fileName, rm.problem);

                // write the zipFile out to a disk file.
                using (System.IO.FileStream fs = new System.IO.FileStream("c:\\Temp\\" + strMetaName + ".zip", System.IO.FileMode.Create))
                    fs.Write(rr.zipFile, 0, rr.zipFile.Length);
            }
        }
    }
}

 

Does anyone have any suggestions on how to troubleshoot a timeout issue with Queryresult? No matter what batch size I set the queryoptions to, it times out whether 5 records or 500 records.

 

I'm able to log in successfully, but when I run the query, the operation always times out.

Have any of you worked with the EncodingUtil.base64Decode() method? I have a client Carte Financial who is wanting to send an email automatically when a new file attachment has been added. The Body of the file attachment is in Base64 format. But all the examples that I've researched on the Salesforce blogs don't work. My current code is:

 

    for(Attachment attch : attchSubset) {

          

           // Create the attachment

           Messaging.Emailfileattachment efa = new Messaging.Emailfileattachment();

           efa.setFileName(attch.Name);

 

Get an error here stating that there is an invalid Base64 character and can’t convert it. If I just add the attachment with the Body in its Salesforce format, it doesn’t show properly.

           // Decrypt the attachment body and then set it.

           Blob body = EncodingUtil.base64Decode(attch.body.ToString());

           efa.setBody(body);

                   

           Messaging.Singleemailmessage mail = new Messaging.Singleemailmessage();

           list<String> emailAddr = new list<String>();

           emailAddr.add(mapContact.get(attch.ParentId).Email);

           mail.setToAddresses(emailAddr);

           mail.setPlainTextBody('Hi!');

           mail.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});

          

           // Send the Email Message

           Messaging.SendEmailResult[] r = Messaging.sendEmail(new  Messaging.Singleemailmessage[] {mail});

    }

I built a very simple apex class, based on a test class, to add a row of data to a database table:

 

Private class Invoice_Balance_Record_Inserter {
static void validateInvoice_Payment() {
Invoice_Balance__c i = new
Invoice_Balance__c(Name='I110811EP3-1', 
Invoice__c = 'a00U00000020IgSIAU',
Invoice_Balance_Amount__c=300);
insert i;
 }
}

 The code will run, either in system log or in force ide, but I don't end up with a record in Invoice_Balace__c.   Is there a way I can run this code that will result in a record being added?  thanks