sendgrid/sendgrid-csharp

Put request works on sendgrid website but does not in the application code.

ajitgoel opened this issue ยท 8 comments

I am using the code generated at https://sendgrid.com/docs/api-reference/=> PUT
/marketing/contacts to add a marketing contact. The .net code generated is and it returns a 302 response when sending the request on the website. I however get a Response status code does not indicate success: 400 (Bad Request). when I run it through my unit test project. What am I missing?

var client = new RestClient("https://api.sendgrid.com/v3/marketing/contacts");
var request = new RestRequest(Method.PUT);
request.AddHeader("content-type", "application/json");
request.AddHeader("authorization", "Bearer <ClientId>");
request.AddParameter("application/json", "{\"list_ids\":[\"bbb6445d-0d52-488e-ac38-55176369b9f4\"],\"contacts\":[{\"alternate_emails\":[\"ajitgoel@gmail.com\"],\"email\":\"ajitgoel@gmail.com\"}]}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

@ajitgoel doesn't look like you are using our SDK. I recommend going through the docs if you want to use our helper and to answer your question, I would double check the data you are sending through.

I have already integrated with SendGrid for sending emails. i am now trying to integrate the "PUT
/marketing/contacts" using the dcumentation at https://sendgrid.com/docs/api-reference/ => PUT
/marketing/contacts to add a marketing contact.

The documentation says that I need the following request:
{
"list_ids": [
"string"
],
"contacts": [
{
"address_line_1": "string (optional)",
"address_line_2": "string (optional)",
"alternate_emails": [
"string"
],
"city": "string (optional)",
"country": "string (optional)",
"email": "string (required)",
"first_name": "string (optional)",
"last_name": "string (optional)",
"postal_code": "string (optional)",
"state_province_region": "string (optional)",
"custom_fields": {}
}
]
}
based on this, I am creating the following request from the sendgrid website, and copying the code to my application. Question why does it work on your website but not in the application? Is there a particular version of RestClient package that SendGrid requires?

image

@ajitgoel Same problem here. I cannot even make it work with the sendgrid library using RequestAsync.

It's a shame that nobody has replied. Have you managed to make it work?

My code using the sendgrid library is:

var sendGridClient = new SendGridClient("SG....");

var response = await sendGridClient
    .RequestAsync(
        method: BaseClient.Method.PUT,
        requestBody: "{\"contacts\":[{\"email\":\"myrecipient@example.org\"}]}",
        queryParams: null,
        urlPath: "/marketing/contacts/")
    .ConfigureAwait(false);

Console.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));

The output from the above always is:

{
  "StatusCode": 401,
  "IsSuccessStatusCode": false,
  "Body": {
    "Headers": [
      {
        "Key": "Content-Type",
        "Value": [
          "application/json"
        ]
      },
      {
        "Key": "Content-Length",
        "Value": [
          "52"
        ]
      }
    ]
  },
  "Headers": [
    {
      "Key": "Server",
      "Value": [
        "nginx"
      ]
    },
    {
      "Key": "Date",
      "Value": [
        "Fri, 23 Jul 2021 12:03:26 GMT"
      ]
    },
    {
      "Key": "Connection",
      "Value": [
        "keep-alive"
      ]
    },
    {
      "Key": "x-envoy-upstream-service-time",
      "Value": [
        "53"
      ]
    },
    {
      "Key": "Referrer-Policy",
      "Value": [
        "strict-origin-when-cross-origin"
      ]
    },
    {
      "Key": "X-Content-Type-Options",
      "Value": [
        "nosniff"
      ]
    },
    {
      "Key": "x-ratelimit-limit",
      "Value": [
        "100000000"
      ]
    },
    {
      "Key": "x-ratelimit-remaining",
      "Value": [
        "99999999"
      ]
    },
    {
      "Key": "x-ratelimit-reset",
      "Value": [
        "1"
      ]
    }
  ]
}

Not really sure what @'m doing wrong or what else to try. I have a full permissioned API key and i'm on the free plan until i can make this work.

Can anyone help please?

My guess is that there is something about your JSON payload that the SendGrid API does not like but it's hard to say what exactly. Rather that attempting to figure it out, I suggest an alternative: you should use the StrongGrid .NET client to make your life much easier (disclaimer: I'm the author of this library). It has methods for all of SendGrid's API endpoints with strongly-typed parameters and it takes care of automatically crafting the proper JSON string.

Here's an example that demonstrates how to "upsert" a contact using this library (meaning: either create a new contact or update an existing one if a matching contact already exist):

var email = "111@example.com";
var firstName = "John";
var lastName = "Doe";
var addressLine1 = "123 Main Street";
var addressLine2 = "Suite 123";
var city = "Tinytown";
var stateOrProvince = "Florida";
var country = "USA";
var postalCode = "12345";
var alternateEmails = new[] { "222@example.com", "333@example.com" };

var apiKey = "<... your api key ...>";
var strongGridClient = new Client(apiKey);
await strongGridClient.Contacts.UpsertAsync(email, firstName, lastName, addressLine1, addressLine2, city, stateOrProvince, country, postalCode, alternateEmails, null, null, cancellationToken).ConfigureAwait(false);

If you have questions about using this library, feel free to start a discussion or raise an issue if you face any problem.

Hope this helps.

@ajitgoel Same problem here. I cannot even make it work with the sendgrid library using RequestAsync.

It's a shame that nobody has replied. Have you managed to make it work?

My code using the sendgrid library is:

var sendGridClient = new SendGridClient("SG....");

var response = await sendGridClient
    .RequestAsync(
        method: BaseClient.Method.PUT,
        requestBody: "{\"contacts\":[{\"email\":\"myrecipient@example.org\"}]}",
        queryParams: null,
        urlPath: "/marketing/contacts/")
    .ConfigureAwait(false);

Console.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));

The output from the above always is:

{
  "StatusCode": 401,
  "IsSuccessStatusCode": false,
  "Body": {
    "Headers": [
      {
        "Key": "Content-Type",
        "Value": [
          "application/json"
        ]
      },
      {
        "Key": "Content-Length",
        "Value": [
          "52"
        ]
      }
    ]
  },
  "Headers": [
    {
      "Key": "Server",
      "Value": [
        "nginx"
      ]
    },
    {
      "Key": "Date",
      "Value": [
        "Fri, 23 Jul 2021 12:03:26 GMT"
      ]
    },
    {
      "Key": "Connection",
      "Value": [
        "keep-alive"
      ]
    },
    {
      "Key": "x-envoy-upstream-service-time",
      "Value": [
        "53"
      ]
    },
    {
      "Key": "Referrer-Policy",
      "Value": [
        "strict-origin-when-cross-origin"
      ]
    },
    {
      "Key": "X-Content-Type-Options",
      "Value": [
        "nosniff"
      ]
    },
    {
      "Key": "x-ratelimit-limit",
      "Value": [
        "100000000"
      ]
    },
    {
      "Key": "x-ratelimit-remaining",
      "Value": [
        "99999999"
      ]
    },
    {
      "Key": "x-ratelimit-reset",
      "Value": [
        "1"
      ]
    }
  ]
}

Not really sure what @'m doing wrong or what else to try. I have a full permissioned API key and i'm on the free plan until i can make this work.

Can anyone help please?

I ran into the same problem as you using the SDK. After a bit of frustration I've figured out the issue. 401 error is not authorized which seemed odd. I know the api key was valid and had full access.

urlPath: "/marketing/contacts/" is not a valid endpoint due to how the uri is built internally

urlPath: "marketing/contacts" is correct and works

Hi @ajitgoel,

I'm not sure if this is relevant but I seem to remember that there is an issue when using the alternate_emails property in JSON.

We had a problem when we first started using SendGrid a couple of years ago with bad requests and it turned out that the SG API was having a problem with that particular tag.

This was confirmed by the SG tech we were dealing with at the time but I don't know if they've fixed it or not. as we never use it ๐Ÿ˜ƒ

Just thought I'd mention it as I noticed you're using that tag in you original post.

Thank you @Jericho, I was able to use your nuget library and get my code working. Thank you once again.