Last active
June 28, 2020 18:14
-
-
Save timw255/529867a01c080dda811f30c18eb6d256 to your computer and use it in GitHub Desktop.
Model, Views, and Controller to return a Sitefinity Blog Post as valid AMP content. (Uses timw255.AMP)
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.Web.Mvc; | |
@using Telerik.Sitefinity.Frontend.Mvc.Helpers; | |
@using Telerik.Sitefinity.Modules.Pages; | |
@using Telerik.Sitefinity.UI.MVC; | |
@using Telerik.Sitefinity.Services; | |
<!doctype html> | |
<html amp @Html.RenderLangAttribute()> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> | |
<meta content="IE=Edge" http-equiv="X-UA-Compatible"> | |
@RenderSection("meta", false) | |
<title>@ViewBag.Title</title> | |
<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Open+Sans:300,400'> | |
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript> | |
@RenderSection("components", false) | |
<script async src="https://cdn.ampproject.org/v0.js"></script> | |
<style amp-custom> | |
.logo,footer nav li,footer nav ul{display:inline-block}.by,.logo span,footer nav li a{text-transform:uppercase}.clearfix:after,.content p{clear:both}body{font:400 14px/24px 'Open Sans',Arial,sans-serif}body>header{border-bottom:1px solid #eee;padding:12px 25px 6px}.container{padding:30px;max-width:900px;margin:0 auto}header .container{padding:0}.logo{font-size:20px;line-height:20px;color:#000;padding:0 0 0 50px;background:url(/static/img/logo.png) left center no-repeat;background-size:40px 40px;letter-spacing:-1px;text-decoration:none}.logo span{letter-spacing:0;line-height:10px;color:#888;font-size:10px}.content h1{font-weight:300;font-size:30px;line-height:38px;margin:0 0 20px;letter-spacing:-2px}.by{font-size:12px}.social-share{margin-top:10px}.summary{padding:10px 20px;border:1px solid #eee;font-size:13px;font-style:italic;background:#f4f4f4;margin:10px 0}.content p{font-size:14px;color:#666;line-height:24px}.copyright{text-align:center;font-size:11px}footer{padding:10px}footer nav{text-align:center;margin:10px 0 0}footer nav ul{padding:0;margin:0;list-style:none}footer nav li a{display:block;padding:0 5px;font-size:12px;color:#00b4c9;text-decoration:none}.clearfix:after,.clearfix:before{content:" ";display:table}amp-social-share span{height:40px;width:40px}amp-social-share a{padding:8px}amp-video,amp-youtube{margin:20px 0} | |
</style> | |
</head> | |
<body> | |
<header> | |
<div class="container"><a class="logo" href="/">Quantum<br><span>More than Computers</span></a></div> | |
</header> | |
<div class="container"> | |
<div class="content main"> | |
@RenderBody() | |
</div> | |
</div> | |
<footer> | |
<nav> | |
<ul class="clearfix"> | |
<li><a href="/products">Products</a></li> | |
<li><a href="/online-shop">Online Shop</a></li> | |
<li><a href="/inside-quantum">Inside Quantum</a></li> | |
<li><a href="/about-us">About Us</a></li> | |
<li><a href="/store-locator">Store Locator</a></li> | |
</ul> | |
</nav> | |
<p class="copyright">Copyright © 2002-2013 Quantum. All rights reserved.</p> | |
</footer> | |
</body> | |
</html> |
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.Web; | |
using Telerik.Sitefinity.News.Model; | |
using timw255.AMP; | |
namespace SitefinityWebApp.Mvc.Models | |
{ | |
public class BlogPostDetailViewModel | |
{ | |
public NewsItem Item { get; set; } | |
public string Content { get; set; } | |
public string ThumbnailUrl { get; set; } | |
public int ThumbnailHeight { get; set; } | |
public int ThumbnailWidth { get; set; } | |
public string CanonicalUrl { get; set; } | |
public List<Component> RequiredComponents { get; set; } | |
} | |
} |
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 HtmlAgilityPack; | |
using SitefinityWebApp.Mvc.Models; | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Web; | |
using System.Web.Mvc; | |
using Telerik.Sitefinity.Frontend.Mvc.Models; | |
using Telerik.Sitefinity.Frontend.News.Mvc.Models; | |
using Telerik.Sitefinity.GenericContent.Model; | |
using Telerik.Sitefinity.Libraries.Model; | |
using Telerik.Sitefinity.Modules.GenericContent; | |
using Telerik.Sitefinity.Modules.News; | |
using Telerik.Sitefinity.News.Model; | |
using Telerik.Sitefinity.RelatedData; | |
using Telerik.Sitefinity.Services; | |
using Telerik.Sitefinity.Web.Utilities; | |
using timw255.AMP; | |
namespace SitefinityWebApp.Mvc.Controllers | |
{ | |
public class BlogPostsController : Controller | |
{ | |
public ActionResult Index(string id) | |
{ | |
var item = GetNewsItem(id); | |
if (item == null) | |
{ | |
return HttpNotFound(); | |
} | |
var model = new NewsItemDetailViewModel(); | |
model.Item = item; | |
DynamicLinksParser parser = new DynamicLinksParser(true, false); | |
var content = parser.Apply(item.Content); | |
AMP amp = new AMP(); | |
amp.LoadHtml(content); | |
model.Content = amp.ConvertToAmpHtml(); | |
model.RequiredComponents = amp.RequiredComponents; | |
var thumbnail = item.GetRelatedItems<Image>("Thumbnail").FirstOrDefault(); | |
if (thumbnail != null) | |
{ | |
model.ThumbnailUrl = thumbnail.ThumbnailUrl; | |
model.ThumbnailHeight = thumbnail.Thumbnail.Height; | |
model.ThumbnailWidth = thumbnail.Thumbnail.Width; | |
} | |
model.CanonicalUrl = GetItemDefaultLocationById(item.Id); | |
return View(model); | |
} | |
private NewsItem GetNewsItem(string urlName) | |
{ | |
NewsManager newsManager = NewsManager.GetManager(); | |
NewsItem item = newsManager.GetNewsItems().Where(newsItem => newsItem.UrlName == urlName && newsItem.Status == ContentLifecycleStatus.Live && newsItem.Visible).FirstOrDefault(); | |
return item; | |
} | |
public static string GetItemDefaultLocationById(Guid itemId, string itemProvider = null) | |
{ | |
var clService = SystemManager.GetContentLocationService(); | |
var location = clService.GetItemDefaultLocation(typeof(NewsItem), itemProvider, itemId); | |
if (location != null) | |
{ | |
return location.ItemAbsoluteUrl; | |
} | |
return string.Empty; | |
} | |
} | |
} |
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.NewsItemDetailViewModel | |
@using timw255.AMP; | |
@using Telerik.Sitefinity.Frontend.Mvc.Helpers; | |
@using Telerik.Sitefinity.Web.DataResolving; | |
@{ | |
Layout = "~/Mvc/Views/Shared/_AMP.cshtml"; | |
ViewBag.Title = Model.Item.Title; | |
} | |
@section meta { | |
<meta name="description" content="@Model.Item.Description" /> | |
<link rel="canonical" href="@Model.CanonicalUrl"> | |
<!-- Schema.org markup for Google+ --> | |
<meta itemprop="name" content="@Model.Item.Title"> | |
<meta itemprop="description" content="@Model.Item.Description"> | |
<meta itemprop="image" content="@Model.ThumbnailUrl"> | |
<!-- Twitter Card data --> | |
<meta name="twitter:card" content="summary_large_image"> | |
<meta name="twitter:site" content="Quantum"> | |
<meta name="twitter:creator" content="@DataResolver.Resolve(@Model.Item, "Author", null)"> | |
<meta name="twitter:title" content="@Model.Item.Title"> | |
<meta name="twitter:description" content="@Model.Item.Description"> | |
<meta name="twitter:image" content="@Model.ThumbnailUrl"> | |
<!-- Open Graph data --> | |
<meta property="og:title" content="@Model.Item.Title" /> | |
<meta property="og:type" content="article" /> | |
<meta property="og:image" content="@Model.ThumbnailUrl" /> | |
<meta property="og:url" content="@Model.CanonicalUrl" /> | |
<meta property="og:description" content="@Model.Item.Description" /> | |
<meta property="og:site_name" content="Quantum" /> | |
<meta property="article:published_time" content="@Model.Item.PublicationDate.ToUniversalTime()" /> | |
<meta property="article:modified_time" content="@Model.Item.LastModified.ToUniversalTime()" /> | |
<!-- Metadata required by Google for AMP files --> | |
<script type="application/ld+json"> | |
{ | |
"@@context": "http://schema.org", | |
"@@type": "NewsArticle", | |
"mainEntityOfPage": "@Model.CanonicalUrl", | |
"headline": "@Model.Item.Title", | |
"datePublished": "@Model.Item.PublicationDate.ToUniversalTime()", | |
"dateModified": "@Model.Item.LastModified.ToUniversalTime()", | |
"description": "@Model.Item.Description", | |
"author": { | |
"@@type": "Person", | |
"name": "@DataResolver.Resolve(@Model.Item, "Author", null)" | |
}, | |
"publisher": { | |
"@@type": "Organization", | |
"name": "Quantum", | |
"logo": { | |
"@@type": "ImageObject", | |
"url": "http://amp.sitefinity.com/static/img/logo.png", | |
"width": "57", | |
"height": "64" | |
} | |
}, | |
"image": { | |
"@@type": "ImageObject", | |
"url": "@Model.ThumbnailUrl", | |
"height": "@Model.ThumbnailHeight", | |
"width": "@Model.ThumbnailWidth" | |
} | |
} | |
</script> | |
} | |
@section components { | |
@foreach (Component c in Model.RequiredComponents) | |
{ | |
<script async custom-element="@c.ElementName" src="@c.ScriptPath"></script> | |
} | |
<script async custom-element="amp-social-share" src="https://cdn.ampproject.org/v0/amp-social-share-0.1.js"></script> | |
} | |
<h1>@Model.Item.Title</h1> | |
<div class="by"> | |
@Html.Resource("By") @DataResolver.Resolve(@Model.Item, "Author", null) | @Model.Item.PublicationDate.ToUniversalTime() | |
</div> | |
<div class="social-share"> | |
<amp-social-share type="twitter" width="40" height="40" data-text="@Model.Item.Title"></amp-social-share> | |
<amp-social-share type="facebook" width="40" height="40" data-text="@Model.Item.Title" data-attribution="AMPHtml"></amp-social-share> | |
<amp-social-share type="pinterest" width="40" height="40" data-text="@Model.Item.Title"></amp-social-share> | |
<amp-social-share type="linkedin" width="40" height="40" data-text="@Model.Item.Title"></amp-social-share> | |
<amp-social-share type="gplus" width="40" height="40" data-text="@Model.Item.Title"></amp-social-share> | |
<amp-social-share type="email" width="40" height="40"></amp-social-share> | |
</div> | |
<article> | |
<div class="summary"> | |
@Html.Raw(Model.Item.Summary) | |
</div> | |
<div class="body"> | |
@Html.Raw(Model.Content) | |
</div> | |
</article> |
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
public static void RegisterRoutes(RouteCollection routes) | |
{ | |
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); | |
routes.MapRoute( | |
name: "AMP", | |
url: "amp/{controller}/{id}", | |
defaults: new { action = "Index", id = (string)null }, | |
namespaces: new[] { "SitefinityWebApp.Mvc.Controllers" } | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a plain old MVC controller (not a widget) that returns a blog post (identified by the title) and returns it as an AMP document. Example route is in snippet_for_Global.asax.cs.