Skip to content

Instantly share code, notes, and snippets.

@kevev22
Last active May 29, 2018 04:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevev22/74c72e56c0829d47a29c to your computer and use it in GitHub Desktop.
Save kevev22/74c72e56c0829d47a29c to your computer and use it in GitHub Desktop.
NationBuilder API Usage Example
This Gist shows an example of how we would call the NationBuilder API to:
- Create an event
- Update an event
- Create a person
- Update a person
- Delete a person
EventService and PersonService are the classes that actually make the calls to the API. They inherit from Service.
PersonSamples and EventSamples call the Service classes to make the changes to the data.
The following classes are serialized to create the JSON requests for events:
- Event
- EventContact
- EventContainer
- EventRsvpForm
- EventVenue
- EventVenueAddress
The following classes are serialized to create the JSON requests for people:
- Person
- PersonContainer
internal class Event
{
private int? _timeZoneOffset = (int) TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).TotalHours;
[JsonIgnore]
public TimeZone TimeZone
{
set { _timeZoneOffset = (int) value.GetUtcOffset(DateTime.Now).TotalHours; }
}
[JsonProperty("id", DefaultValueHandling = DefaultValueHandling.Ignore)]
public int? Id { get; set; }
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("headline")]
public string Headline { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("intro")]
public string Intro { get; set; }
[JsonProperty("time_zone")]
public string TimeZoneDisplay
{
get { return _timeZoneOffset != null ? _timeZoneOffset.Value.ToString("+00;-00") : null; }
}
[JsonProperty("start_time")]
public DateTime? StartTime { get; set; }
[JsonProperty("end_time")]
public DateTime? EndTime { get; set; }
[JsonProperty("contact")]
public EventContact Contact { get; set; }
[JsonProperty("rsvp_form")]
public EventRsvpForm RsvpForm { get; set; }
[JsonProperty("show_guests")]
public bool? ShowGuests { get; set; }
[JsonProperty("capacity")]
public short? Capacity { get; set; }
[JsonProperty("venue")]
public EventVenue Venue { get; set; }
}
internal class EventContact
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("phone")]
public string Phone { get; set; }
[JsonProperty("show_phone")]
public bool ShowPhone { get; set; }
[JsonProperty("email")]
public string Email { get; set; }
[JsonProperty("show_email")]
public bool ShowEmail { get; set; }
}
internal class EventContainer
{
public EventContainer(Event @event)
{
Event = @event;
}
[JsonProperty("event")]
public Event Event { get; set; }
}
internal class EventRsvpForm
{
[JsonProperty("phone")]
public string PhoneRequirementLevel { get; set; }
[JsonProperty("address")]
public string AddressRequirementLevel { get; set; }
[JsonProperty("allow_guests")]
public bool AllowGuests { get; set; }
[JsonProperty("accept_rsvps")]
public bool AcceptRsvps { get; set; }
[JsonProperty("gather_volunteers")]
public bool GatherVolunteers { get; set; }
}
internal static class EventSamples
{
public static void RunSamples()
{
// Create the event
Event createdEvent = CreateEvent();
// Update the event
UpdateEvent(createdEvent);
}
/// <summary>
/// Creates a sample event using the NationBuilder API.
/// </summary>
/// <returns>The event that was created.</returns>
private static Event CreateEvent()
{
Event @event = GetNewEvent();
var eventService = new EventService();
return eventService.CreateEvent(@event);
}
/// <summary>
/// Updates an event using the NationBuilder API.
/// </summary>
/// <param name="event">The event to update.</param>
private static void UpdateEvent(Event @event)
{
// Set a new name
@event.Name = "Updated Name";
var eventService = new EventService();
eventService.UpdateEvent(@event);
}
/// <summary>
/// Creates the object that will be send to the Create Event API method.
/// </summary>
/// <returns>The EventContainer that will be sent to the API.</returns>
private static Event GetNewEvent()
{
DateTime startTime = DateTime.Now.AddHours(2);
DateTime endTime = startTime.AddMinutes(120);
return new Event
{
Capacity = 10,
Contact = new EventContact
{
Email = "test@test.com",
Phone = "5555555555",
Name = "My Contact",
ShowEmail = true,
ShowPhone = true
},
Headline = "Test Headline",
Intro = "Test Intro",
Name = "Test Name",
RsvpForm = new EventRsvpForm
{
AcceptRsvps = true,
AddressRequirementLevel = RequirementLevel.Required,
AllowGuests = true,
GatherVolunteers = true,
PhoneRequirementLevel = RequirementLevel.Required
},
ShowGuests = true,
StartTime = startTime,
EndTime = endTime,
Status = EventStatus.Unlisted,
TimeZone = TimeZone.CurrentTimeZone,
Title = "Test Title",
Venue = new EventVenue("Test venue", new EventVenueAddress("Test Address 1", "Test City", "CA"))
};
}
}
internal class EventService : Service
{
public Event CreateEvent(Event @event)
{
var endpoint = EndPointProvider.GetCreateEventEndPoint();
var container = new EventContainer(@event);
var request = new ServiceRequest<EventContainer>(endpoint, container);
var result = PostWithResult<EventContainer, EventContainer>(request);
return result.Event;
}
public void UpdateEvent(Event @event)
{
var endpoint = EndPointProvider.GetUpdateEventEndPoint(@event.Id.Value);
var container = new EventContainer(@event);
var request = new ServiceRequest<EventContainer>(endpoint, container);
Put(request);
}
}
internal class EventVenue
{
public EventVenue(string name, EventVenueAddress address)
{
Name = name;
Address = address;
}
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("address")]
public EventVenueAddress Address { get; set; }
}
internal class EventVenueAddress
{
public EventVenueAddress(string address1, string city, string state)
{
Address1 = address1;
City = city;
State = state;
}
[JsonProperty("address1")]
public string Address1 { get; set; }
[JsonProperty("city")]
public string City { get; set; }
[JsonProperty("state")]
public string State { get; set; }
}
internal class Person
{
[JsonProperty("id", DefaultValueHandling = DefaultValueHandling.Ignore)]
public int? Id { get; private set; }
[JsonProperty("first_name", DefaultValueHandling = DefaultValueHandling.Ignore)]
public string FirstName { get; set; }
[JsonProperty("last_name", DefaultValueHandling = DefaultValueHandling.Ignore)]
public string LastName { get; set; }
[JsonProperty("email", DefaultValueHandling = DefaultValueHandling.Ignore)]
public string Email { get; set; }
[JsonProperty("is_deceased", DefaultValueHandling = DefaultValueHandling.Ignore)]
public bool? IsDeceased { get; set; }
[JsonProperty("mobile", DefaultValueHandling = DefaultValueHandling.Ignore)]
public string PhoneNumberMobile { get; set; }
[JsonProperty("phone", DefaultValueHandling = DefaultValueHandling.Ignore)]
public string PhoneNumberHome { get; set; }
[JsonProperty("work_phone_number", DefaultValueHandling = DefaultValueHandling.Ignore)]
public string PhoneNumberWork { get; set; }
[JsonProperty("support_level", DefaultValueHandling = DefaultValueHandling.Ignore)]
public int? SupportLevel { get; private set; }
[JsonProperty("is_volunteer", DefaultValueHandling = DefaultValueHandling.Ignore)]
public bool? IsVolunteer { get; set; }
[JsonProperty("do_not_call", DefaultValueHandling = DefaultValueHandling.Ignore)]
public bool? DoNotCall { get; set; }
[JsonProperty("do_not_contact", DefaultValueHandling = DefaultValueHandling.Ignore)]
public bool? DoNotContact { get; set; }
}
internal class PersonContainer
{
public PersonContainer(Person person)
{
Person = person;
}
[JsonProperty("person")]
public Person Person { get; set; }
}
internal static class PersonSamples
{
public static void RunSamples()
{
// Create the person
var person = CreatePerson();
// Update the person
UpdatePerson(person);
// Delete the person
DeletePerson(person.Id.Value);
}
private static Person CreatePerson()
{
var person = GetNewPerson();
var service = new PersonService();
return service.CreatePerson(person);
}
private static void UpdatePerson(Person person)
{
person.FirstName = "NewFirstName";
person.LastName = "NewLastName";
var service = new PersonService();
service.UpdatePerson(person);
}
private static void DeletePerson(int id)
{
var service = new PersonService();
service.DeletePerson(id);
}
private static Person GetNewPerson()
{
return new Person
{
FirstName = "OrigFirstName",
LastName = "OrigLastName",
Email = "test@test.com",
IsVolunteer = true
};
}
}
internal class PersonService : Service
{
public Person CreatePerson(Person person)
{
string endpoint = EndPointProvider.GetCreatePersonEndPoint();
var container = new PersonContainer(person);
var request = new ServiceRequest<PersonContainer>(endpoint, container);
PersonContainer result = PostWithResult<PersonContainer, PersonContainer>(request);
return result.Person;
}
public void UpdatePerson(Person person)
{
string endpoint = EndPointProvider.GetUpdatePersonEndPoint(person.Id.Value);
var container = new PersonContainer(person);
var request = new ServiceRequest<PersonContainer>(endpoint, container);
Put(request);
}
public void DeletePerson(int personId)
{
string endpoint = EndPointProvider.GetDeletePersonEndPoint(personId);
Delete(endpoint);
}
}
internal abstract class Service
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
protected void Delete(string endPoint)
{
var request = new ServiceRequest<object>(endPoint, null);
SendRequest(request, client => client.DeleteAsync(endPoint));
}
protected void Put<T>(ServiceRequest<T> request) where T : class
{
SendRequest(request, client => client.PutAsJsonAsync(request.Endpoint, request.Payload));
}
protected TResponse PostWithResult<TPayload, TResponse>(ServiceRequest<TPayload> request)
where TPayload : class
where TResponse : class
{
return SendRequestWithResponse<TPayload, TResponse>(request,
client => client.PostAsJsonAsync(request.Endpoint, request.Payload));
}
private void SendRequest<T>(ServiceRequest<T> request, Func<HttpClient, Task<HttpResponseMessage>> sendFunc)
where T : class
{
using (var client = new HttpClient())
{
client.Timeout = ConfigProvider.ServiceTimeout;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Task<HttpResponseMessage> postTask = sendFunc(client);
Task.WaitAll(postTask);
HttpResponseMessage response = postTask.Result;
if (response.IsSuccessStatusCode)
{
return;
}
Task<string> responseTask = response.Content.ReadAsStringAsync();
Task.WaitAll(responseTask);
string responseText = responseTask.Result;
string payloadString = request.Payload != null ? JsonConvert.SerializeObject(request.Payload) : null;
Logger.Error("Error sending {0} to: {1}. Response: {2}", payloadString, request.Endpoint, responseText);
throw new InvalidOperationException("API call failed.");
}
}
private TResponse SendRequestWithResponse<TPayload, TResponse>(ServiceRequest<TPayload> request,
Func<HttpClient, Task<HttpResponseMessage>> sendFunc) where TPayload : class where TResponse : class
{
using (var client = new HttpClient())
{
client.Timeout = ConfigProvider.ServiceTimeout;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Task<HttpResponseMessage> postTask = sendFunc(client);
Task.WaitAll(postTask);
HttpResponseMessage response = postTask.Result;
Task<string> responseTask = response.Content.ReadAsStringAsync();
Task.WaitAll(responseTask);
string responseText = responseTask.Result;
if (response.IsSuccessStatusCode)
{
return JsonConvert.DeserializeObject<TResponse>(responseText);
}
string payloadString = JsonConvert.SerializeObject(request.Payload);
Logger.Error("Error sending {0} to: {1}. Response: {2}", payloadString, request.Endpoint, responseText);
throw new InvalidOperationException("API call failed.");
}
}
}
@stanleyliu1006
Copy link

Hi Kevev22

We are trying to connect NationBuilder with C# application.

Can you please provide us the entire solution code of this project, we try to run your sample code, it does not work due to missing context definition (such as EndPointProvider does not exist in the current context, might be missing files).

Looking forward to your reply.

My email address is: stanleyliu1006@outlook.com

Regards
Stanley

@MikeStall
Copy link

Stanley - are you still interested in this? We have a C# client that we can share out.

@rodram
Copy link

rodram commented May 15, 2018

Hello Mike.. are you able to share that project with me... interested. Thank you! @MikeStall

@peterfalconer
Copy link

I too would be interested in that project if you were able to share it. Thank you. @MikeStall

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment