.NET API client for ButterCMS (https://buttercms.com)
Switch branches/tags
Nothing to show
Clone or download
jakelumetta Merge pull request #17 from bgnicoll/master
Tests for examples & a screenshot of Page type definition
Latest commit 959d3bd Jun 15, 2018

README.md

buttercms-csharp

.NET Library for ButterCMS API.

Documentation

For a comprehensive list of examples, check out the API documentation.

Installation

To install ButterCMS, run the following command in the Package Manager Console

PM> Install-Package ButterCMS

The library can also be installed to the project via .NET CLI

dotnet add package ButterCMS

Or by adding the package manually to the project file

<ItemGroup>
<PackageReference Include="ButterCMS" Version="1.3.4" />
</ItemGroup>

Usage

To get started with the Butter API, instantiate the ButterCMSClient with the API key found in the Butter Admin Settings. An optional timeout parameter can be passed as a TimeSpan; the default is 10 seconds.

using ButterCMS;
...
var butterClient = new ButterCMSClient("API KEY");

If the application will be making many Butter API calls, it is recommended to store and re-use the client object.

Each Butter client method has a synchronous version and an asynchronous version. Asynchronous methods are appended with the word "Async".

Sections

Posts

List Posts

Listing posts returns a PostsResponse object. This object consists of a metadata object and IEnumerable<Post>

ListPosts() Parameters

Parameter Default Description
page(optional) 1 Used to paginate through older posts.
pageSize(optional) 10 Used to set the number of blog posts shown per page.
excludeBody(optional) false When true, does not return the full post body. Useful for keeping response size down when showing a list of blog posts.
authorSlug(optional) Filter posts by an author’s slug.
categorySlug(optional) Filter posts by a category’s slug.

Examples

PostsResponse posts = butterClient.ListPosts();

PostsResponse filteredPosts = await butterClient.ListPostsAsync(page: 2, pageSize: 5, excludeBody: true, authorSlug: "alice", categorySlug: "dot-net");

Retrieving a Single Post

Retrieving a single Post will return a PostResponse object. This object consists of a single Post and Post Metadata. Post Metadata offers hints about the Previous and Next posts.

RetrievePost() Parameters

Parameter Description
slug The slug of the post to be retrieved.

Examples

PostResponse controversialPost = butterClient.RetrievePost("tabs-vs-spaces-throwdown");

PostResponse safePost = await butterClient.RetrievePostAsync("puppies-and-kittens");

Searching Posts

Searching posts will return the same object as listing posts, PostsResponse

SearchPosts() Parameters

Parameter Default Description
query Search query
page(optional) 1 Used to paginate through older posts.
pageSize(optional) 10 Used to set the number of blog posts shown per page.

Examples

PostsResponse posts = butterClient.SearchPosts("spaceships");

PostsResponse caffeinePosts = await butterClient.SearchPostsAsync(query: "coffee", page: 3, pageSize: 5);

Authors

List Authors

Listing Authors returns IEnumerable<Author>

ListAuthors() Parameters

Parameter Description
includeRecentPosts(optional) If true, will return the author's recent posts in the response

Examples

IEnumerable<Author> authors = butterClient.ListAuthors();

IEnumerable<Author> authorsWithPosts = await butterClient.ListAuthorsAsync(includeRecentPosts: true);

Retrieve a Single Author

Retrieving an author returns an Author object

RetrieveAuthor() Parameters

Parameter Description
authorSlug The slug of the author to be retrieved.
includeRecentPosts(optional) If true, will return the author's recent posts in the response

Examples

Author sally = butterClient.RetrieveAuthor("sally");

Author tylerAndPosts = await butterClient.RetrieveAuthorAsync(authorSlug: "tyler", includeRecentPosts: true);

Categories

List Categories

Listing Categories returns IEnumerable<Category>

ListCategories() Parameters

Parameter Description
includeRecentPosts(optional) If true, will return recent posts along with categories

Examples

IEnumerable<Category> categories = butterClient.ListCategories();

IEnumerable<Category> categoriesWithPosts = await butterClient.ListCategoriesAsync(includeRecentPosts: true);

Retrieve a Single Category

Retrieving a single category returns Category

RetrieveCategory() Parameters

Parameter Description
categorySlug The slug of the category to be retrieved.
includeRecentPosts(optional) If true, will return recent posts along with category

Examples

 Category dotnetCategory = butterClient.RetrieveCategory("dotnet");

 Category fsharpCategoryWithPosts = await butterClient.RetrieveCategoryAsync(categorySlug: "fsharp", includeRecentPosts: true);

Feeds

Each of the feeds methods returns an XmlDocument.

RSS Feed

Retrieve a fully generated RSS feed for your blog.

Examples

 XmlDocument rssFeed = butterClient.GetRSSFeed();

 XmlDocument rssFeed = await butterClient.GetRSSFeedAsync();

Atom Feed

Retrieve a fully generated Atom feed for your blog.

Examples

 XmlDocument atomFeed = butterClient.GetAtomFeed();

 XmlDocument atomFeed = await butterClient.GetAtomFeedAsync();

Sitemap

Retrieve a fully generated sitemap for your blog.

Examples

 XmlDocument siteMap = butterClient.GetSitemap();

 XmlDocument siteMap = await butterClient.GetSitemapAsync();

Content Fields

New in version 1.3.0

By the power of .NET generics, Content Fields can now be deserialized by the library! The former method that would defer deserialization is still available to ease transition.

RetrieveContentFields() Parameters

Parameter Description
keys String array of desired keys
parameterDictionary(optional) Dictionary of additional parameters, such as "locale" or "test"

RetrieveContentFields() Exceptions:

Exception Description
ContentFieldObjectMismatchException This exception will be thrown when the library can't fit the returned data into the passed object class.

Examples

var keys = new string[2] { "team_members[name=Elon]", "homepage_headline" };
var dict = new Dictionary<string, string>()
            {
                { "locale", "de" },
                { "test", "1" }
            };
var teamMembersAndHeadline = butterClient.RetrieveContentFields<TeamMembersHeadline>(keys, dict);

** Content Fields JSON documentation** :

As demonstrated in the Content Fields documentation, any number of user-defined content fields can be retrieved from the API, these can get complicated in C# and you may choose to handle the response yourself. The RetrieveContentFieldsJSON() method will return the raw JSON response from the Butter API.

RetrieveContentFieldsJSON() Parameters

Parameter Description
keys String array of desired keys
parameterDictionary(optional) Dictionary of additional parameters, such as "locale" and "test"

Examples

var keys = new string[2] { "team_members[name=Elon]", "homepage_headline" };
var dict = new Dictionary&lt;string, string&gt;()
            {
                { "locale", "de" },
                { "test", "1" }
            };
var contentFields = await butterClient.RetrieveContentFieldsJSONAsync(keys, dict);

Pages

ButterCMS Pages can be retrieved by first defining the custom Page Type as a class. These custom Page Types are defined in the Butter admin.

List Pages

Listing Pages returns a PagesResponse<T> object. Full API documentation can be found at https://buttercms.com/docs/api/#list-pages-for-a-page-type.

ListPages() Parameters

Parameter Description
pageType Desired page type
parameterDictionary Dictionary of additional parameters. These options are described in greater detail in the full API documentation.

ListPages() Exceptions

Exception Description
PagesObjectMismatchException This exception will be thrown when the library can't fit the returned data into the passed object class.

Retrieve a Single Page

Retrieving a single page returns a PageResponse<T> object

RetrievePage() Parameters

Parameter Description
pageType Desired page type
pageSlug Slug of the desired page
parameterDictionary Dictionary of additional parameters

RetrievePage() Exceptions:

Exception Description
PagesObjectMismatchException This exception will be thrown when the library can't fit the returned data into the passed object class.

Examples

Page Type Definition in the Butter Admin

alt text

Controller and ViewModel examples
public namespace HungryDevApp
{
    public class RecipePage
    {
        public string category { get; set; }
        public string recipe_name { get; set; }
        public string main_ingredient { get; set; }
        public double estimated_cooking_time_in_minutes { get; set; }
        public string ingredient_list { get; set; }
        public string instructions { get; set; }
    }

    public class RecipesController : Controller
    {
        [Route(recipes/)]
        public virtual ActionResult Index(int page = 1, int pageSize = 10)
        {
            var butterClient = new ButterCMSClient("API KEY");

            var parameterDict = new Dictionary<string, string>()
            {
                {"page", page.ToString()},
                {"page_size", pageSize.ToString()}
            };

            PagesResponse<RecipePage> recipePages = butterClient.ListPages<RecipePage>("recipe", parameterDict);

            var viewModel = new RecipesViewModel();
            viewModel.PreviousPageNumber = recipePages.Meta.PreviousPage;
            viewModel.NextPageNumber = recipePages.Meta.NextPage;
            viewModel.PagesCount = recipePages.Meta.Count;

            viewModel.Recipes = new List<RecipeViewModel>();
            foreach (Page<RecipePage> recipe in recipePages.Data)
            {
                RecipeViewModel recipeViewModel = new RecipeViewModel();
                recipeViewModel.Category = recipe.Fields.category;
                recipeViewModel.RecipeName = recipe.Fields.recipe_name;
                recipeViewModel.MainIngredient = recipe.Fields.main_ingredient;
                recipeViewModel.EstimatedCookingTimeInMinutes = recipe.Fields.estimated_cooking_time_in_minutes;
                recipeViewModel.IngredientList = recipe.Fields.ingredient_list;
                recipeViewModel.Instructions = recipe.Fields.instructions;

                viewModel.Recipes.Add(recipeViewModel);
            }

            return View(viewModel);
        }

        [Route(recipe/{slug})]
        public virtual ActionResult Recipe(string slug)
        {
            var butterClient = new ButterCMSClient("API KEY");

            PageResponse<RecipePage> recipe = butterClient.RetrievePage<RecipePage>("recipe", slug);

            var viewModel = new RecipeViewModel();
            viewModel.Category = recipe.Data.Fields.category;
            viewModel.RecipeName = recipe.Data.Fields.recipe_name;
            viewModel.MainIngredient = recipe.Data.Fields.main_ingredient;
            viewModel.EstimatedCookingTimeInMinutes = recipe.Data.Fields.estimated_cooking_time_in_minutes;
            viewModel.IngredientList = recipe.Data.Fields.ingredient_list;
            viewModel.Instructions = recipe.Data.Fields.instructions;

            return View(viewModel);
        }
    }

    public class RecipesViewModel
    {
        public List<RecipeViewModel> Recipes { get; set; }
        public int? PreviousPageNumber { get; set; }
        public int? NextPageNumber { get; set; }
        public int PagesCount { get; set; }
    }

    public class RecipeViewModel
    {
        public string Category { get; set; }
        public string RecipeName { get; set; }
        public string MainIngredient { get; set; }
        public double EstimatedCookingTimeInMinutes { get; set; }
        public string IngredientList { get; set; }
        public string Instructions { get; set; }
    }
    
}

Example View usage for ListPages
@using HungryDevApp
@{
Layout = "~/Views/Shared/Layouts/_Layout.cshtml";
}
@model RecipesViewModel
<div>
    <a href="/recipes/?page=@{Model.PreviousPageNumber}&pageSize=10">Previous page</a>
    <a href="/recipes/?page=@{Model.NextPageNumber}&pageSize=10">Next page</a>
</div>
<div>
    <p>@{Model.PagesCount} recipes total</p>
</div>
<div>
    <ul>
        @foreach(var page in Model.Recipes)
        {
            <li>
                <a href="/recipe/@{page.Slug}">@{page.RecipeName}
            </li>
        }
    </ul>
</div>
Example View usage for RetrievePage
@using HungryDevApp
@{
Layout = "~/Views/Shared/Layouts/_Layout.cshtml";
}
@model RecipeViewModel
<div>
    <h2>@{Model.RecipeName}</h2>
    <p>Estimated cooking time: @{Model.EstimatedCookingTimeInMinutes} minutes</p>
    <h3>Ingredients:</h3>
    <p>@{Model.IngredientList}</p>
    <h3>Instructions:</h3>
    <p>@{Model.Instructions}</p>
</div>

Class Definitions

PostsResponse Class

Property Type
Meta PostsMeta
Data IEnumerable<Post>

PostsMeta Class

Property Type
Count int
NextPage int?
PreviousPage int?

Post Class

Property Type
Url string
Created DateTime
Published DateTime
Author Author
Categories IEnumerable<Category>
FeaturedImage string
Slug string
Title string
Body string
Summary string
SeoTitle string
MetaDescription string
Status PostStatusEnum

PostStatusEnum

Constant Value
Unknown 0
Draft 1
Published 2

PostResponse Class

Property Type
Meta PostMeta
Data Post

PostMeta Class

Property Type
NextPost PostLight
PreviousPost PostLight

PostLight Class

Property Type
Slug string
Title string
FeaturedImage string

Author Class

Property Type
FirstName string
LastName string
Email string
Slug string
Bio string
Title string
LinkedinUrl string
FacebookUrl string
InstagramUrl string
PinterestUrl string
TwitterHandle string
ProfileImage string
RecentPosts IEnumerable<Post>

Category Class

Property Type
Name string
Slug string
RecentPosts IEnumerable<Post>

PagesResponse Class

Property Type
Meta PageMeta
Data IEnumerable<Page<T>>

PageMeta Class

Property Type
Count int
PreviousPage int?
NextPage int?

PageResponse Class

Property Type
Data Page<T>

Page Class

Property Type
Slug string
Fields T

Exceptions

InvalidKeyException

The library throws this exception when the Butter API key used to instatiate the client was not valid.

ContentFieldObjectMismatchException

This exception will be thrown when the library can't fit the returned data from a Content Field request into the passed object class.

PagesObjectMismatchException

This exception will be thrown when the library can't fit the returned data from a Pages request into the passed object class.