9

I'm looking to set up a RestResource endpoint that accepts some URL parameters and creates a lead record. Here's the basic gist of my code:

@RestResource(urlMapping='/createLead/*')
global with sharing class CreateLeadRest{
 @HttpPost
 global static void doPost() {   

   string id = RestContext.request.params.get('id');
   Lead newLead = new Lead();
   newLead.Company='test';
   newLead.LastName='test';
   newLead.Description=id;
   insert newLead;
   }
}

When I call this endpoint, I get this error:

UNKNOWN_EXCEPTION, invalid parameter value: []

Interestingly enough, if I create a new record of any object other than Lead or Case, the code works fine. But specifically for leads and cases, it doesn't like the ID parameter in the query string.

Anyone experience this?

  • what if you change id parameter to something like leadId or caseId ? – Mohith Shrivastava Aug 23 '16 at 15:16
  • @MohithShrivastava That would work well, but unfortunately, I'm setting this up as a webhook from a third-party system, so I have no control over the name of the ID parameter. – emroc Aug 23 '16 at 15:53
  • Sounds like an SFDC bug to me .What happens if you comment newLead.Description=id; – Mohith Shrivastava Aug 23 '16 at 16:01
  • @MohithShrivastava Same result. – emroc Aug 23 '16 at 16:21
  • Can you try like this string Leadid = RestContext.request.params.get('id'); – Mohith Shrivastava Aug 23 '16 at 17:14
5
+50

Update

I was also able to make your HttpPost method work by moving the creation to a @future method.

@RestResource(urlMapping='/createLead/*')
global with sharing class CreateLeadRest{
    @HttpPost
    global static void doPost()
    {
        insertLead(RestContext.request.params.get('id'));
    }
    @future
    public static void insertLead(String id)
    {
        Lead newLead = new Lead();
        newLead.Company='test';
        newLead.LastName='test';
        newLead.Description=id;
        insert newLead;
    }
}

If you have conflicting @future calls getting in the way, consider using a Queueable implementation. You probably should develop a defensive asynchronous framework if you plan on executing asynchronous logic directly in your triggers. I know Dan Appleman has written a lot of material on the subject, and how to properly use an asynchronous framework is somewhat outside the scope of this question.


Original Answer

First of all, you should also look at this Stack Overflow post: How are parameters sent in an HTTP POST request? URI parameters and POST requests are fundamentally incompatible.

Instead, you should shoot for a pattern more similar to how the documentation lays out POST requests in Creating REST APIs using Apex REST (Using POST, PUT and PATCH).

The way you would normally access POST parameters via Apex REST is more like:

@RestResource(urlMapping='/createLead/*')
global with sharing class CreateLeadRest{
    @HttpPost
    global static void doPost(String id) {   
        Lead newLead = new Lead();
        newLead.Company='test';
        newLead.LastName='test';
        newLead.Description=id;
        insert newLead;
    }
}

Then if you pass the parameters through the Body, your request should succeed:

Summary

Method: POST
Endpoint: /services/apexrest/createLead/
Payload: {"id": 123}

Screenshot

Method:POST;Endpoint:/services/apexrest/createLead/;Payload:{"id":123}

Whereas any attempt to pass parameters via the URI should fail:

Summary

Method: POST
Endpoint: /services/apexrest/createLead/?id=123
Payload: {"id": 123}

Screenshot

Method:POST;Endpoint:/services/apexrest/createLead/?id=123;Payload:{"id":123}

  • Thanks for this @AdrianLarson. I do understand that you would not normally pass URL parameters for POST requests, but I am unfortunately at the mercy of the third-party provider in that regard. The provider allows for specifying a URL to which a webhook POST request will be passed, and the ID in question is not in the body of the request but in a URL parameter. – emroc Aug 25 '16 at 16:30
  • @emroc Then it cannot be a POST request. The two are incompatible. See also: How are parameters sent in an HTTP POST request? If they insist on sending you request parameters via the URI then you should insist on using a different vendor, because they don't understand how HTTP requests work. – Adrian Larson Aug 25 '16 at 16:31
  • That's what I was afraid of. I'm trying to find a workaround for this, and the only one I can think of is to call off to the SF REST API inside of my RestResource class to create the lead, instead of doing it directly in the class itself. – emroc Aug 25 '16 at 16:36
  • You could abuse GET to pass parameters via the URI, but it sounds like whoever you're working with is not very flexible. – Adrian Larson Aug 25 '16 at 16:37
  • 2
    Their API sends a POST request specifically, so doing a GET instead is simply not possible. What I find interesting is that this is only a problem if I attempt to create a lead or a case in the class. Any other object works fine. I'm guessing that this has something to do with SF web-to-lead/web-to-case, but that's just an assumption. – emroc Aug 25 '16 at 16:42
4

The reason you're getting this error, is that Lead has required field LastName.

It seems that tool you're using is not providing full info, I would recommend to use Chrome extension Postman. That will give HTTP 500 and:

[ { "errorCode": "APEX_ERROR", "message": "System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [LastName]: [LastName]\n\nClass.CreateLeadRest.doPost: line 12, column 1" } ]

or you can add to your code something like:

url: https://naxx.salesforce.com/services/apexrest/createLead?id=50036000000xxxx

global static String doPost() { 
//..
try {
    insert newLead;
} catch (exception e){
    return e.getMessage();
}

return newLead.id;
  • Sorry @IlyaLepesh, the code I provided doesn't have last name but my actual code does. I've run the code in an anonymous apex window and can confirm that it does indeed create the lead as expected. I've updated my original question. – emroc Aug 23 '16 at 19:28
  • @emroc, is it working now? How do you execute this from anonymous window? – Ilya Lepesh Aug 23 '16 at 20:58
  • it isn't working, no. I meant to say that my original code does include the last name, I just forgot to include it in the original question. If I just run the lead creation bit in an anonymous window, a lead gets created, but the same code doesn't create a lead in the RestResource class. – emroc Aug 23 '16 at 21:58
  • You code works fine, how are you reaching RestResource class? – Ilya Lepesh Aug 23 '16 at 22:58
  • Just with a simple post request. I've been using Postman in Chrome for testing. – emroc Aug 24 '16 at 12:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.