3

I am trying to create an attachment in Salesforce using a Apex method which is exposed as Rest resource. I am trying to create a merchandise record where the attachment should be attached to the notes & attachment section of the record. Below is my Apex class exposed as REST:

@RestResource(urlMapping='/Merchandise/*')
global with sharing class MerchandiseManager {

    @HttpGet
    global static Merchandise__c getMerchandiseById() {
        RestRequest req = RestContext.request;        
        String merchId = req.requestURI.substring(
                                  req.requestURI.lastIndexOf('/')+1);
        Merchandise__c result = 
                       [SELECT Name,Description__c,Price__c,Total_Inventory__c
                        FROM Merchandise__c 
                        WHERE Id = :merchId];
        return result;
    }

    @HttpPost
    global static String createMerchandise(String name,
        String description, Decimal price, Double inventory, String id,List<Attachment> attachs) {
        Merchandise__c m = new Merchandise__c(
            Name=name,
            Description__c=description,
            Price__c=price,
            Total_Inventory__c=inventory,Warehouse__c=id);
        insert m;
    list<attachment> attachmentToInsert = new list<attachment>();

    for (Attachment att :attachs) {
        attachmentToInsert.add(
            new Attachment(parentId = m.Id, name = att.name, 
                ContentType = att.ContentType, 
                Body = EncodingUtil.base64Decode(att.body)));
    }
        return m.Id;
    }
}

I am using workbench to test whether an attachment is getting created or not. Here is my JSON( with out attachment parameter):

      {
  "name" : "Pencil",
  "description" : "White eraser",
  "price" : 0.75,
  "inventory" : 1000,
"id" : "a0e37000000lKep",
"attachs": {
    "Body": "d29ybGQ=",
    "ContentType": "text/plain",
    "Name": "hello.txt"
}
}

I get an error:

errorCode: APEX_ERROR
message: System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Body]: [Body] Class.MerchandiseManager.createMerchandise: line 26, column 1

How can I pass an attachment( the body etc) in the above JSON , I would like to pass multiple attachment in the JSON also. What change I have to make in Apex method - createMerchandise . I have read through some reference but it not clear how I can implement that in my scenario. I have passed the attachment but unable to get the body of the attachment. Please advice

1

1 Answer 1

4

In the following example custom wrapper class Merchandise has been created. It contains custom object reference and list of custom attachments. Json contains name, which can be deserialized as custom object and array of attachments. Body is a base64 representation of 'World' word.

Json:

{
    "merchandise": {
        "Name": "Eraser"
    },
    "attachments": [{
        "Body": "d29ybGQ=",
        "ContentType": "text/plain",
        "Name": "hello.txt"
    }, {
        "Body": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAMSURBVBhXY3growIAAycBLhVrvukAAAAASUVORK5CYII=",
        "ContentType": "image/png",
        "Name": "picture.png"
    }]
}

Apex:

@RestResource(urlMapping='/Merchandise/*')
global with sharing class MerchandiseResource {

private class Attach {
    String Body;
    String ContentType;
    String Name;
}
private class Merchandise {
    Merchandise__c merchandise;
    list<Attach> attachments;
} 

@HttpPost
global static String doPost() {
    //json will be taken directly from RestContext
    Merchandise container = (Merchandise)System.JSON.deserialize(
        RestContext.request.requestBody.tostring(), 
        Merchandise.class);

    Merchandise__c merch = container.merchandise;
    insert merch;

    list<attachment> attachmentToInsert = new list<attachment>();

    for (Attach att :container.attachments) {
        attachmentToInsert.add(
            new Attachment(parentId = merch.Id, name = att.name, 
                           ContentType = att.ContentType, 
                           Body = EncodingUtil.base64Decode(att.body)));
    }
    insert attachmentToInsert;

    return merch.id;
}}

Rest utility (in my case Postman) will return object id, so attachment can be checked in Salesforce:

enter image description here

9
  • 1
    Nice work Ilya. +1
    – Adrian Larson
    Jul 11, 2016 at 21:53
  • Thanks. can I pass the attachments as a variable to doPost() method , how do get the attachment inside the doPost method? It will be great if you can show this example using my code to understand better
    – SfdcBat
    Jul 11, 2016 at 22:00
  • A little confused in how to put this code in my code. I am not using JSON.deserilize and I am just taking the values as parameters
    – SfdcBat
    Jul 11, 2016 at 22:02
  • I changeed my code accordingly(please see my edited question) , but I am getting an error - Compile Error: Method does not exist or incorrect signature: EncodingUtil.base64Decode(Blob) at line 31 column 24, can you suggest if my apex class is correct?
    – SfdcBat
    Jul 11, 2016 at 22:22
  • I changed the version and edited - Body = System.EncodingUtil.base64Decode(att.body)) , to include System class there , but I still get the error - Compile Error: Method does not exist or incorrect signature: System.EncodingUtil.base64Decode(Blob) at line 31 column 24, seems like base64Decode() takes a string according to documentation?
    – SfdcBat
    Jul 11, 2016 at 22:31

You must log in to answer this question.

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