1

Mandrill

I am using RestSharp for making an API call to the Mandrill for sending emails.

public List<EmailResult> SendMessageTemplate(MandrillApi mapiResponse, string templateName, EmailMessage emailMessage)
    {
        //if (mapiResponse != null && !string.IsNullOrEmpty(mapiResponse.ApiKey) && !string.IsNullOrEmpty(mapiResponse.BaseUrl)
        //                         && !string.IsNullOrEmpty(templateName) && templateContent != null && templateContent.Count > 0 && emailMessage != null)
        if (mapiResponse != null && !string.IsNullOrEmpty(mapiResponse.ApiKey) && !string.IsNullOrEmpty(mapiResponse.BaseUrl)
                                 && !string.IsNullOrEmpty(templateName) && emailMessage != null)
        {

            List<EmailResult> emailResult = new List<EmailResult>();

            var soEmailMessage = JsonConvert.SerializeObject(emailMessage);
            restRequest = new RestSharp.RestRequest
            {
                RequestFormat = DataFormat.Json,
                Method = RestSharp.Method.POST,
                //Resource = string.Format("{0}/send-template.json", "messages")
                Resource = string.Format("{0}/send.json", "messages")
            };
            restRequest.AddBody(new { key = mapiResponse.ApiKey, template_name = templateName, message = soEmailMessage });

            restClient = new RestSharp.RestClient(mapiResponse.BaseUrl);
            var response = restClient.Execute(restRequest);

            emailResult = JsonConvert.DeserializeObject<List<EmailResult>>(response.Content);

            return emailResult;
        }

        else
            return null;
    }

However I get the response as

"Please enter an array".

 {"status":"error","code":-2,"name":"ValidationError","message":"Validation error: {\"message\":\"Please enter an array\"}"}

The JSON generated after serialization is as follows:

"message": {
"attachments": [],
"auto_html": null,
"auto_text": true,
"bcc_address": null,
"from_email": "test@gmail.com",
"from_name": "ABC",
"global_merge_vars": [{
    "content": "test",
    "name": "ffname"
}],
"google_analytics_campaign": null,
"google_analytics_domains": null,
"headers": null,
"html": null,
"images": null,
"important": null,
"inline_css": null,
"merge": null,
"merge_vars": null,
"metadata": null,
"preserve_recipients": false,
"raw_message": null,
"raw_to": null,
"recipient_metadata": null,
"return_path_domain": null,
"signing_domain": null,
"subaccount": null,
"subject": "Test",
"merge_language": null,
"tags": ["Sep-2019"],
"text": null,
"to": [{
    "email": "shubhamtest@gmail.com",
    "name": "Test Email Address",
    "type": null
}],
"track_clicks": true,
"track_opens": true,
"tracking_domain": null,
"url_strip_qs": null,
"view_content_link": null }

The EmailMessage class is part of the Mandrill assembly and it contains:

enter image description here

Mandrill Assembly: I installed it via NugetPackage. Please find the below link:

https://www.nuget.org/packages/Mandrill/

I tried few solutions like adding the emailmessage object into a list and then converting it into an array. But it gives the response as "[]".

Can anyone please suggest for the same?

Thanks

Community
  • 1
  • 1
  • are you using a specific client SDK for this, or did you write the C# classes yourself? I'm just wondering if it's something _within_ the message which is not an array. Per https://mandrillapp.com/api/docs/messages.JSON.html#method=send, "message" itself should indeed be an object, but within that are several properties which, if defined, need to be arrays. Maybe one of those is the issue (and the error message from the API is not very useful!). It would make sense to show us the JSON you're generating and/or the relevant C# classes. – ADyson Sep 09 '19 at 10:43
  • The SendMessageTemplate method is custom that I wrote. However the EmailMessage class that is passed as parameter is present inside the Mandrill assembly. I have edited my question and updated the JSON – Shubham Khandelwal Sep 09 '19 at 10:53
  • " the Mandrill assembly" ...which one? From a quick search it looks like there are a few competing .NET client libraries for this API – ADyson Sep 09 '19 at 11:04
  • P.S. I can't see anything obviously wrong with that JSON. Have you tried attempting to send the request via a tool like PostMan? So we can try and determine whether the issue is truly with the request data, or with something else in the C# code. – ADyson Sep 09 '19 at 11:08
  • Yes, I tried with Postman and getting the correct response. For mandrill assemble I have update my question. Kindly please see the edited question. – Shubham Khandelwal Sep 09 '19 at 11:08
  • when you tested with PostMan did you use the exact same JSON as your code is creating? Otherwise it's not really a valid comparison. – ADyson Sep 09 '19 at 11:09
  • In terms of the assembly I'm not really interested in where it's stored on your disk. I was really asking where you got it from (and therefore where the documentation is) - a hyperlink to that would be useful. – ADyson Sep 09 '19 at 11:11
  • Yes, actually they are same. The JSON that was serialized in the code, I took the same JSON and ran it in the POSTMAN. So yes, they are same. Also added hyperlink for the Mandrill assembly. – Shubham Khandelwal Sep 09 '19 at 11:11
  • @Chrᴉz `EmailResult` is the response, not the request, so not sure how that's relevant? And the code which creates the request **is creating an object already**. – ADyson Sep 09 '19 at 11:27
  • @ADyson My fault. I meat EmailMessage. See here: Guess you need to use `List emailMessages = new List() { emailMessage }; var soEmailMessage = JsonConvert.SerializeObject(emailMessages);`. `emailMessage` is a object, not an array as stated in the error message. Just following the error message the direct way: \"message\":\"Please enter an array\" – Chrᴉz remembers Monica Sep 09 '19 at 11:29
  • @Chrᴉz yes but the API documentation clearly states that message should be an object. That's why we're trying to figure out what's really going on. OP states also they used the exact same JSON to create a request successfully with PostMan. – ADyson Sep 09 '19 at 11:34
  • @Chrᴉz actually I think I spotted the issue. See answer below. – ADyson Sep 09 '19 at 11:47
  • @ADyson Just reading. Good try, lets hope it fits :) – Chrᴉz remembers Monica Sep 09 '19 at 11:48

1 Answers1

0

I think I can see the problem now:

You are double-serialising your message data. How so, you might ask? Well, here goes:

var soEmailMessage = JsonConvert.SerializeObject(emailMessage);

converts emailMessage into JSON. So soEmailMessage is a string. You then add this within another object when you create your message body:

new { key = mapiResponse.ApiKey, template_name = templateName, message = soEmailMessage }

This creates another C# object containing 3 properties, one of which is your message. And you can't send a C# object in a HTTP request. So RestSharp will, per your DataFormat.Json instruction, serialise that whole object to JSON. But at this point, message is already a JSON string. So what you'll end up with being sent to the server is a property called "message" which is a single string, containing the JSON data with its properties etc escaped, so to the server it just looks like one big line of text, not the object it was expecting. It cannot spot this and deserialise the data.


The simple solution is:

Don't serialise manually, just let RestSharp serialise the whole request body for you:

new { key = mapiResponse.ApiKey, template_name = templateName, message = emailMessage }

But also, the client library you're using provides a class for you to wrap your message already - you don't need to define your own object. Use the SendMessageRequest class:

restRequest.AddBody(new SendMessageRequest() { key = mapiResponse.ApiKey, message = emailMessage });

Alternatively if you want to send with a Template you can use the SendMessageRequestTemplate class instead.

I also don't think you actually need to use RestSharp yourself either. According to the MandrillApi class there are methods there to automatically send the right type of request to the API endpoints.


P.S. See also RestSharp JSON Parameter Posting for a similar question where someone is double-serialising their data when using RestSharp.

P.P.S. I don't know why the API error is complaining about arrays, but it seems pretty clear to me that the above must be what is causing the problem.

ADyson
  • 57,178
  • 14
  • 51
  • 63