Last active
August 29, 2015 14:03
-
-
Save jonathanread/3add49d436dba1fb8fa7 to your computer and use it in GitHub Desktop.
Hubspot post MVC widget
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@model SitefinityWebApp.Mvc.Models.HubSpotPostsModel | |
<div class="sf_cols posts"> | |
@{int column = 1;} | |
@foreach (var item in Model.Posts) | |
{ | |
string colOut = "sf_3cols_" + column + "_3" + ((column == 2) ? "4" : "3"); | |
string colIn = "sf_3cols_" + column + "in_3" + ((column == 2) ? "4" : "3"); | |
<div class="sf_colsOut @colOut"> | |
<div class="sf_colsIn @colIn"> | |
<section class="post"> | |
<a class="image" href="@item.Url" target="_blank" style="background-image:url('@item.ImageSource')"></a> | |
<a href="@item.Url" target="_blank"> | |
<h1 class="postTitle"> | |
@item.Title | |
</h1> | |
</a> | |
<p class="postInfo"> | |
<span class="author-publish">by <a href="http://blog.apterainc.com/?Author=@item.AuthorDisplayName.Replace(" ", "+")" target="_blank">@item.AuthorDisplayName</a> | @item.PublishDate</span> | |
<a href="@item.Url" target="_blank"> | |
<span class="description">@item.MetaDescription</span> | |
</a> | |
</p> | |
</section> | |
</div> | |
</div> | |
column++; | |
} | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Collections.ObjectModel; | |
using System.Dynamic; | |
using System.Linq; | |
using System.Text; | |
using System.Web.Script.Serialization; | |
namespace Aptera.Sitefinity.Models | |
{ | |
public sealed class DynamicJsonConverter : JavaScriptConverter | |
{ | |
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) | |
{ | |
if (dictionary == null) | |
throw new ArgumentNullException("dictionary"); | |
return type == typeof(object) ? new DynamicJsonObject(dictionary) : null; | |
} | |
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) | |
{ | |
throw new NotImplementedException(); | |
} | |
public override IEnumerable<Type> SupportedTypes | |
{ | |
get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); } | |
} | |
#region Nested type: DynamicJsonObject | |
private sealed class DynamicJsonObject : DynamicObject | |
{ | |
private readonly IDictionary<string, object> _dictionary; | |
public DynamicJsonObject(IDictionary<string, object> dictionary) | |
{ | |
if (dictionary == null) | |
throw new ArgumentNullException("dictionary"); | |
_dictionary = dictionary; | |
} | |
public override string ToString() | |
{ | |
var sb = new StringBuilder("{"); | |
ToString(sb); | |
return sb.ToString(); | |
} | |
private void ToString(StringBuilder sb) | |
{ | |
var firstInDictionary = true; | |
foreach (var pair in _dictionary) | |
{ | |
if (!firstInDictionary) | |
sb.Append(","); | |
firstInDictionary = false; | |
var value = pair.Value; | |
var name = pair.Key; | |
if (value is string) | |
{ | |
sb.AppendFormat("{0}:\"{1}\"", name, value); | |
} | |
else if (value is IDictionary<string, object>) | |
{ | |
new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb); | |
} | |
else if (value is ArrayList) | |
{ | |
sb.Append(name + ":["); | |
var firstInArray = true; | |
foreach (var arrayValue in (ArrayList)value) | |
{ | |
if (!firstInArray) | |
sb.Append(","); | |
firstInArray = false; | |
if (arrayValue is IDictionary<string, object>) | |
new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb); | |
else if (arrayValue is string) | |
sb.AppendFormat("\"{0}\"", arrayValue); | |
else | |
sb.AppendFormat("{0}", arrayValue); | |
} | |
sb.Append("]"); | |
} | |
else | |
{ | |
sb.AppendFormat("{0}:{1}", name, value); | |
} | |
} | |
sb.Append("}"); | |
} | |
public override bool TryGetMember(GetMemberBinder binder, out object result) | |
{ | |
if (!_dictionary.TryGetValue(binder.Name, out result)) | |
{ | |
// return null to avoid exception. caller can check for null this way... | |
result = null; | |
return true; | |
} | |
result = WrapResultObject(result); | |
return true; | |
} | |
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) | |
{ | |
if (indexes.Length == 1 && indexes[0] != null) | |
{ | |
if (!_dictionary.TryGetValue(indexes[0].ToString(), out result)) | |
{ | |
// return null to avoid exception. caller can check for null this way... | |
result = null; | |
return true; | |
} | |
result = WrapResultObject(result); | |
return true; | |
} | |
return base.TryGetIndex(binder, indexes, out result); | |
} | |
private static object WrapResultObject(object result) | |
{ | |
var dictionary = result as IDictionary<string, object>; | |
if (dictionary != null) | |
return new DynamicJsonObject(dictionary); | |
var arrayList = result as ArrayList; | |
if (arrayList != null && arrayList.Count > 0) | |
{ | |
return arrayList[0] is IDictionary<string, object> | |
? new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x))) | |
: new List<object>(arrayList.Cast<object>()); | |
} | |
return result; | |
} | |
} | |
#endregion | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net.Http; | |
using System.Net.Http.Headers; | |
using System.Text; | |
using System.Threading.Tasks; | |
using System.Web.Script.Serialization; | |
namespace Aptera.Sitefinity.Models | |
{ | |
public class HubSpotPost | |
{ | |
private String _imgSrc = ""; | |
private String _comments = ""; | |
private String _publishDate = ""; | |
public String Title { get; set; } | |
public String Guid { get; set; } | |
public String Body { get; set; } | |
public Boolean Draft { get; set; } | |
public String AuthorDisplayName {get; set;} | |
public String MetaDescription { get; set; } | |
public String PublishTimestamp { get; set; } | |
public String PublishDate | |
{ | |
get { return _publishDate; } | |
set | |
{ | |
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0); | |
double ticks; | |
if (double.TryParse(value, out ticks)) | |
{ | |
_publishDate = origin.AddMilliseconds(ticks).ToLocalTime().ToString("MMM dd, yyyy"); | |
} | |
else | |
{ | |
_publishDate = DateTime.UtcNow.ToString(); | |
} | |
} | |
} | |
public String Comments | |
{ | |
get { return _comments; } | |
set | |
{ | |
_comments = GetCommentsCount(value); | |
} | |
} | |
private string GetCommentsCount(string value) | |
{ | |
string count = "0"; | |
using (var client = new HttpClient()) | |
{ | |
client.BaseAddress = new Uri("https://api.hubapi.com/blog/v1/"); | |
client.DefaultRequestHeaders.Accept.Clear(); | |
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); | |
HttpResponseMessage response = client.GetAsync(string.Format("posts/{0}/comments.json?hapikey=a45ec77f-66e2-437e-b3f9-e772b622d36b",value)).Result; | |
if (response.IsSuccessStatusCode) | |
{ | |
JavaScriptSerializer serializer = new JavaScriptSerializer(); | |
serializer.RegisterConverters(new[] { new DynamicJsonConverter() }); | |
dynamic i = serializer.Deserialize(response.Content.ReadAsStringAsync().Result, typeof(object)); | |
count = i.Length.ToString(); | |
} | |
} | |
return count; | |
} | |
public String Url { get; set; } | |
public String ImageSource | |
{ | |
get { return _imgSrc; } | |
set { _imgSrc = GetImageSrc(value); } | |
} | |
public List<String> Tags { get; set; } | |
private static string GetImageSrc(string data) | |
{ | |
string source = ""; | |
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument(); | |
if (!string.IsNullOrWhiteSpace(data)) | |
{ | |
doc.LoadHtml(data); | |
if (doc != null) | |
{ | |
if(doc.DocumentNode.SelectSingleNode("//img") != null) | |
{ | |
source = doc.DocumentNode.SelectSingleNode("//img").Attributes["src"].Value; | |
if(source.IndexOf("http://blog.apterainc.com") < 0) | |
{ | |
source = "http://blog.apterainc.com" +source; | |
} | |
} | |
} | |
} | |
return source; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.ComponentModel; | |
using System.Linq; | |
using System.Web.Mvc; | |
using Telerik.Sitefinity.Mvc; | |
using SitefinityWebApp.Mvc.Models; | |
using System.Net; | |
using System.IO; | |
using System.Xml.Linq; | |
using Aptera.Sitefinity.Models; | |
using System.Net.Http; | |
using System.Net.Http.Headers; | |
using System.Web.Script.Serialization; | |
using System.Collections.Generic; | |
namespace SitefinityWebApp.Mvc.Controllers | |
{ | |
[ControllerToolboxItem(Name = "HubSpotPosts", Title = "HubSpotPosts", SectionName = "MvcWidgets")] | |
public class HubSpotPostsController : Controller | |
{ | |
/// <summary> | |
/// This is the default Action. | |
/// </summary> | |
[OutputCache(CacheProfile="CacheHubSpot")] | |
public ActionResult Index() | |
{ | |
var model = new HubSpotPostsModel(); | |
model.Posts = GetBlogPosts().Select(p => new HubSpotPost() { | |
Title = p.Title, | |
Body = p.Body, | |
AuthorDisplayName = p.AuthorDisplayName, | |
PublishDate = p.PublishTimestamp, | |
MetaDescription = p.MetaDescription, | |
ImageSource = p.Body, | |
Draft = p.Draft, | |
Guid = p.Guid, | |
Tags = p.Tags, | |
Url = p.Url | |
}).Take(3); | |
return View("Default", model); | |
} | |
private static IEnumerable<HubSpotPost> GetBlogPosts(int skip = 0) | |
{ | |
IEnumerable<HubSpotPost> posts; | |
using (var client = new HttpClient()) | |
{ | |
client.BaseAddress = new Uri("https://api.hubapi.com/blog/v1/"); | |
client.DefaultRequestHeaders.Accept.Clear(); | |
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); | |
// New code: | |
HttpResponseMessage response = client.GetAsync(string.Format("d2d4d48e-3653-4958-b0ff-2e43ac3a8539/posts.json?hapikey=a45ec77f-66e2-437e-b3f9-e772b622d36b&offset={0}", skip)).Result; | |
if (response.IsSuccessStatusCode) | |
{ | |
JavaScriptSerializer serializer = new JavaScriptSerializer(); | |
posts = serializer.Deserialize<IEnumerable<HubSpotPost>>(response.Content.ReadAsStringAsync().Result).Where(p => !p.Draft); | |
if (posts.Count() < 5) | |
{ | |
var take = 5 - posts.Count(); | |
var ps = GetBlogPosts(10).Where(p => !p.Draft).Take(take); | |
posts.Union(ps); | |
if (posts.Count() < 5) | |
{ | |
var take2 = 5 - posts.Count(); | |
var ps2 = GetBlogPosts(10).Where(p => !p.Draft).Take(take2); | |
posts.Union(ps2); | |
return posts.Take(5); | |
} | |
return posts.Take(5); | |
} | |
return posts.Take(5); | |
} | |
} | |
return null; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Aptera.Sitefinity.Models; | |
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace SitefinityWebApp.Mvc.Models | |
{ | |
public class HubSpotPostsModel | |
{ | |
public IEnumerable<HubSpotPost> Posts { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment