Question

I am having trouble updating templates over Templates API (Web API). Here is my code:

CURL (user and password removed):

$ curl -d '{"name":"NameRemoved","html_content":"<%body%>",
  "plain_content":"<%body%>","subject":"<%subject%>"}' 
  https://api.sendgrid.com/v3/templates/GuidRemoved/versions

Getting a 400 error BAD REQUEST

{"error": "A <%body%> tag is required in html content"}

Similarly, my C# code results in same error:

using (var client = new HttpClient())
{
  client.BaseAddress = new Uri("https://api.sendgrid.com/");
  client.DefaultRequestHeaders.Accept.Clear();
  client.DefaultRequestHeaders.Accept.Add(
         new MediaTypeWithQualityHeaderValue("application/json"));
  client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
    "Basic",
    Convert.ToBase64String(
    Encoding.ASCII.GetBytes(String.Format("{0}:{1}", 
      credentials.UserName, credentials.Password))));

  var data = new NewTemplate()
  {
    html_content = "<%body%>",
    name = template.name + "_" + template.Versions.Count(),
    plain_content = "<%body%>",
    subject = "<%subject%>"
  };

  var content = JsonConvert.SerializeObject(data) as string;
  var response = await client.PostAsync(
      String.Format("v3/templates/{0}/versions", template.id), 
      new StringContent(content));
}

I did notice that when I retrieve the current default template, the content is somewhat encoded.

{"id":"GuidRemoved",
 "template_id":"GuidRemoved",
 "active":1,
 "name":"NameRemoved", 
 "html_content":"\u003c%body%\u003e",
 "plain_content":"\u003c%body%\u003e",
 "subject":"\u003c%subject%\u003e",
 "updated_at":"2014-06-03 21:40:43"}

So I tried to encode it like that as well, but it did not work either.

Any help is greatly appreciated.

UPDATE

After specifying ContentType of StringContent, the C# code works:

new StringContent(content,Encoding.UTF8,"application/json")
Was it helpful?

Solution

Here is a sample code, which can be used for various task to interact with SendGrid:

GET REQUEST:

    private static async Task<TReturn> GetAsync<TReturn>(string getString)
    {
        TReturn data = default(TReturn);
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri("https://api.sendgrid.com/");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                "Basic",
                Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", credentials.UserName, credentials.Password))));
            HttpResponseMessage response = await client.GetAsync(getString);
            if (response.IsSuccessStatusCode)
            {
                string t = await response.Content.ReadAsStringAsync();
                data = JsonConvert.DeserializeObject<TReturn>(t);
            }
        }
        return data;
    }

POST REQUEST:

    private static async Task<TReturn> PostAsync<TReturn>(string postUri, object data)
    {
        TReturn ret = default(TReturn);
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri("https://api.sendgrid.com/");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                "Basic",
                Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", credentials.UserName, credentials.Password))));
            HttpResponseMessage response = await client.PostAsync(postUri, new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json"));
            if (response.IsSuccessStatusCode)
            {
                string t = await response.Content.ReadAsStringAsync();
                ret = JsonConvert.DeserializeObject<TReturn>(t);
            }
        }
        return ret;
    }

Sample usage

Get All Templates

GetAsync<TemplatesCollection>("v3/templates");

Get Active Template

GetAsync<TemplateVersion>(String.Format("v3/templates/{0}/versions/{1}", template.id, template.Versions.Single(s1 => s1.active.Equals("1")).id));

upload new version of a Template

    private static async Task<TemplateVersion> UpdateTemplate(Template template, string fileName)
    {
        var data = new BaseTemplate
                   {
                       html_content = File.ReadAllText(fileName),
                       name = String.Format("{0}_{1:yyyyMMddHHmmss}", template.name, DateTime.Now),
                       plain_content = "<%body%>",
                       subject = "<%subject%>"
                   };
        return await PostAsync<TemplateVersion>(String.Format("v3/templates/{0}/versions", template.id), data);
    }

Supporting classes

internal class TemplatesCollection
{
    #region Public Properties

    public List<Template> templates { get; set; }

    #endregion
}

internal class TemplateVersion : BaseTemplate
{
    #region Public Properties

    public string id { get; set; }

    public string updated_at { get; set; }

    #endregion
}

internal class BaseTemplate
{
    #region Public Properties

    public string html_content { get; set; }

    public string name { get; set; }

    public string plain_content { get; set; }

    public string subject { get; set; }

    #endregion
}

internal class Template
{
    #region Public Properties

    public Version[] Versions { get; set; }

    public string default_version_id { get; set; }

    public string id { get; set; }

    public string name { get; set; }

    #endregion
}

internal class Version
{
    #region Public Properties

    public string active { get; set; }

    public string id { get; set; }

    public string name { get; set; }

    public string template_id { get; set; }

    public string updated_at { get; set; }

    #endregion
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top