Error executing template "Designs/Website/Paragraph/ParagraphLinkedInFeeds.cshtml"
System.Net.WebException: The remote server returned an error: (404) Not Found.
at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
at System.Net.WebClient.DownloadString(Uri address)
at CompiledRazorTemplates.Dynamic.RazorEngine_b57abcabc0e14c48a1bf02d3936ab2ec.LinkedInAPI.GetCompanyUpdates(String& json) in E:\dynamicweb.net\solutions\Skabertrang\tytex.dw9.dynamicweb-cms.com\files\Templates\Designs\Website\Paragraph\ParagraphLinkedInFeeds.cshtml:line 257
at CompiledRazorTemplates.Dynamic.RazorEngine_b57abcabc0e14c48a1bf02d3936ab2ec.Execute() in E:\dynamicweb.net\solutions\Skabertrang\tytex.dw9.dynamicweb-cms.com\files\Templates\Designs\Website\Paragraph\ParagraphLinkedInFeeds.cshtml:line 395
at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.b__0(TextWriter writer)
at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @using System.IO
2 @functions {
3 string GetImage(string image, int width, int height, int compression, int crop, string colorSpace, bool doNotUpscale) {
4 // Crop
5 // 0 = Center
6 // 1 = From upper left
7 // 2 = From lower left
8 // 3 = From lower right
9 // 4 = From upper right
10 // 5 = Keep aspect ratio
11 // 6 = Fit image
12
13 // ColorSpace
14 // rgb
15 // cmyk
16 // grayscale
17
18 var param = new List<string>();
19
20 param.Add("Image=" + image);
21 param.Add("Format=" + Path.GetExtension(image).Substring(1));
22
23 if (width > 0) {
24 param.Add("Width=" + width);
25 }
26
27 if (height > 0) {
28 param.Add("Height=" + height);
29 }
30
31 param.Add("Compression=" + compression);
32 param.Add("Crop=" + crop);
33 param.Add("ColorSpace=" + colorSpace);
34 param.Add("DoNotUpscale=" + (doNotUpscale ? "True" : "False"));
35
36 return "/Admin/Public/GetImage.ashx?" + string.Join("&", param);
37 }
38
39 string GetImagePlaceholder(int width, int height) {
40 return GetImagePlaceholder(width, height, null, null, null);
41 }
42
43 string GetImagePlaceholder(int width, int height, string backgroundColor, string textColor, string text) {
44 var r = "https://placehold.it/" + width;
45
46 if (height > 0) {
47 r += "x" + height;
48 }
49
50 if (!string.IsNullOrWhiteSpace(backgroundColor) && !string.IsNullOrWhiteSpace(textColor)) {
51 r += "/" + backgroundColor;
52 r += "/" + textColor;
53 }
54
55 if (!string.IsNullOrWhiteSpace(text)) {
56 r += "?text=" + text.Replace(" ", "+");
57 }
58
59 return r;
60 }
61
62
63 T LoadContextItem<T>(string key) {
64 var pw = Dynamicweb.Frontend.PageView.Current();
65 var obj = pw != null && pw.Context != null ? pw.Context.GetValue(key) : null;
66
67 return obj == null ? default(T) : (T)obj;
68 }
69
70 void SaveContextItem(string key, object value) {
71 var pw = Dynamicweb.Frontend.PageView.Current();
72
73 if (pw == null) {
74 return;
75 }
76
77 if (pw.Context == null) {
78 pw.Context = new Dynamicweb.Frontend.PageViewContext();
79 }
80
81 pw.Context.SetValue(key, value);
82 }
83
84 string PathCombine(params string[] paths) {
85 return Path.Combine(paths);
86 }
87
88 string NullIfEmpty(string value) {
89 return string.IsNullOrEmpty(value) ? null : value;
90 }
91
92 string NullIfWhiteSpace(string value) {
93 return string.IsNullOrWhiteSpace(value) ? null : value;
94 }
95
96 string ToJson(object value) {
97 return ToJson(value, false);
98 }
99
100 string ToJson(object value, bool indented) {
101 return Newtonsoft.Json.JsonConvert.SerializeObject(
102 value,
103 indented ? Newtonsoft.Json.Formatting.Indented : Newtonsoft.Json.Formatting.None,
104 new Newtonsoft.Json.Converters.IsoDateTimeConverter { DateTimeFormat = "yyyyMMdd'T'HHmmss" }
105 );
106 }
107
108 void AddCssFile(params string[] files) {
109 var list = LoadContextItem<List<string>>("SB.CssFiles");
110
111 if (list == null) {
112 list = new List<string>();
113 }
114
115 foreach (var file in files) {
116 if (!list.Contains(file, StringComparer.OrdinalIgnoreCase)) {
117 list.Add(file);
118 }
119 }
120
121 SaveContextItem("SB.CssFiles", list);
122 }
123
124 void AddJsFile(params string[] files) {
125 var list = LoadContextItem<List<string>>("SB.JsFiles");
126
127 if (list == null) {
128 list = new List<string>();
129 }
130
131 foreach (var file in files) {
132 if (!list.Contains(file, StringComparer.OrdinalIgnoreCase)) {
133 list.Add(file);
134 }
135 }
136
137 SaveContextItem("SB.JsFiles", list);
138 }
139 }
140 @using System.Collections.Specialized
141 @using System.Globalization
142 @using System.IO
143 @using System.Net
144 @using System.Text
145 @functions {
146 public class LinkedInAPI {
147 public string DesignBaseUrl { get; set; }
148 public string CompanyId { get; set; }
149 public string State { get; set; }
150 public string ClientId { get; set; }
151 public string ClientSecret { get; set; }
152 public string AuthorizedRedirectURL { get; set; }
153
154 private string TokenPath;
155 private Newtonsoft.Json.Linq.JObject _Token;
156
157 private Newtonsoft.Json.Linq.JObject Token {
158 get {
159 if (_Token == null) {
160 var json = default(string);
161
162 if (File.Exists(TokenPath)) {
163 json = File.ReadAllText(TokenPath);
164 }
165
166 if (!string.IsNullOrWhiteSpace(json)) {
167 _Token = Newtonsoft.Json.Linq.JObject.Parse(json);
168 }
169 }
170 return _Token;
171 }
172 }
173
174 public string AccessToken {
175 get {
176 return (string)Token["access_token"];
177 }
178 }
179
180 public int ExpiresIn {
181 get {
182 return (int)Token["expires_in"];
183 }
184 }
185
186 public DateTime Expires {
187 get {
188 return DateTime.ParseExact((string)Token["_expires"], "yyyyMMdd'T'HHmmss", CultureInfo.InvariantCulture);
189 }
190 }
191
192 public LinkedInAPI(string designbaseurl, string companyid, string state, string clientid, string clientsecret, string authorizedredirecturl) {
193 DesignBaseUrl = designbaseurl;
194 CompanyId = companyid;
195 State = state;
196 ClientId = clientid;
197 ClientSecret = clientsecret;
198 AuthorizedRedirectURL = authorizedredirecturl;
199
200 TokenPath = Dynamicweb.Context.Current.Server.MapPath(DesignBaseUrl + "LinkedIn-Token.txt");
201 }
202
203 public void Auth() {
204 var scope = "r_liteprofile";
205
206 Dynamicweb.Context.Current.Response.Redirect(
207 "https://www.linkedin.com/oauth/v2/authorization?response_type=code" +
208 "&client_id=" + ClientId +
209 "&state=" + State +
210 "&redirect_uri=" + AuthorizedRedirectURL +
211 "&scope=" + scope,
212 true
213 );
214 }
215
216 public void SetToken(string code) {
217 using (var wc = new WebClient()) {
218 var nvc = new NameValueCollection();
219 nvc.Add("grant_type", "authorization_code");
220 nvc.Add("code", code);
221 nvc.Add("client_id", ClientId);
222 nvc.Add("client_secret", ClientSecret);
223 nvc.Add("redirect_uri", AuthorizedRedirectURL);
224
225 var result = wc.UploadValues("https://www.linkedin.com/oauth/v2/accessToken", nvc);
226 var json = Encoding.UTF8.GetString(result);
227 var jObj = Newtonsoft.Json.Linq.JObject.Parse(json);
228 var expires = DateTime.Now.AddSeconds((int)jObj["expires_in"]);
229
230 jObj["_code"] = code;
231 jObj["_expires"] = expires.ToString("yyyyMMdd'T'HHmmss");
232
233 File.WriteAllText(TokenPath, jObj.ToString());
234
235 _Token = null;
236 }
237 }
238
239 public CompanyUpdate[] GetCompanyUpdates(out string json) {
240 json = null;
241
242 var cached = Dynamicweb.Caching.Cache.Current.Get<Tuple<string, DateTime, string, string>[]>("LinkedInAPI.GetCompanyUpdates2");
243
244 if (cached != null) {
245 return cached.Select(o => new CompanyUpdate {
246 Comment = o.Item1,
247 Date = o.Item2,
248 Image = o.Item3,
249 Url = o.Item4
250 }).ToArray();
251 }
252
253 using (var wc = new WebClient()) {
254 wc.Encoding = Encoding.UTF8;
255 wc.Headers[HttpRequestHeader.Authorization] = "Bearer " + AccessToken;
256
257 json = wc.DownloadString("https://api.linkedin.com/v1/companies/" + CompanyId + "/updates?format=json");
258 }
259
260 //Dynamicweb.Context.Current.Response.Write(json);
261 //Dynamicweb.Context.Current.Response.End();
262
263 if (!string.IsNullOrWhiteSpace(json)) {
264 var jObj = Newtonsoft.Json.Linq.JObject.Parse(json);
265 var list = new List<Tuple<string, DateTime, string, string>>();
266
267 foreach (var item in jObj["values"]) {
268 var share = item["updateContent"] != null && item["updateContent"]["companyStatusUpdate"] != null ? item["updateContent"]["companyStatusUpdate"]["share"] : null;
269 var content = share != null ? share["content"] : null;
270
271 if (content == null) {
272 continue;
273 }
274
275 list.Add(new Tuple<string, DateTime, string, string>(
276 (string)share["comment"],
277 LinkedInAPI.JavaTimeStampToDateTime((double)share["timestamp"]),
278 (string)content["submittedImageUrl"],
279 (string)content["shortenedUrl"]
280 ));
281 }
282
283 var result = list.ToArray();
284
285 Dynamicweb.Caching.Cache.Current.AddOrUpdate<Tuple<string, DateTime, string, string>[]>(
286 "LinkedInAPI.GetCompanyUpdates2",
287 result,
288 new Dynamicweb.Caching.CacheItemPolicy() {
289 AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(30)
290 }
291 );
292
293 return list.Select(o => new CompanyUpdate {
294 Comment = o.Item1,
295 Date = o.Item2,
296 Image = o.Item3,
297 Url = o.Item4
298 }).ToArray();
299 }
300
301 return null;
302 }
303
304 private static DateTime JavaTimeStampToDateTime(double javaTimeStamp) {
305 var result = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
306 result = result.AddMilliseconds(javaTimeStamp).ToLocalTime();
307 return result;
308 }
309
310 public class CompanyUpdate {
311 public string Comment { get; set; }
312 public DateTime Date { get; set; }
313 public string Image { get; set; }
314 public string Url { get; set; }
315 }
316 }
317 }
318 @{
319 var paragraphId = GetInteger("ParagraphID");
320
321 var maxFeeds = GetInteger("Item.MaxFeeds");
322
323 // Advanced
324 var cssClassName = GetString("Item.CssClassName");
325 var clearfix = GetBoolean("Item.Clearfix");
326 var unwrap = GetBoolean("Item.Unwrap");
327
328 // Bootstrap
329 var phones = GetString("Item.Phones");
330 var tablets = GetString("Item.Tablets");
331 var mediumDesktops = GetString("Item.MediumDesktops");
332 var largeDesktops = GetString("Item.LargeDesktops");
333
334 var offsetPhones = GetString("Item.OffsetPhones");
335 var offsetTablets = GetString("Item.OffsetTablets");
336 var offsetMediumDesktops = GetString("Item.OffsetMediumDesktops");
337 var offsetLargeDesktops = GetString("Item.OffsetLargeDesktops");
338
339 var pushPhones = GetString("Item.PushPhones");
340 var pushTablets = GetString("Item.PushTablets");
341 var pushMediumDesktops = GetString("Item.PushMediumDesktops");
342 var pushLargeDesktops = GetString("Item.PushLargeDesktops");
343
344 var pullPhones = GetString("Item.PullPhones");
345 var pullTablets = GetString("Item.PullTablets");
346 var pullMediumDesktops = GetString("Item.PullMediumDesktops");
347 var pullLargeDesktops = GetString("Item.PullLargeDesktops");
348
349 phones = !string.IsNullOrWhiteSpace(phones) ? "col-xs-" + phones : string.Empty;
350 tablets = !string.IsNullOrWhiteSpace(tablets) ? "col-sm-" + tablets : string.Empty;
351 mediumDesktops = !string.IsNullOrWhiteSpace(mediumDesktops) ? "col-md-" + mediumDesktops : string.Empty;
352 largeDesktops = !string.IsNullOrWhiteSpace(largeDesktops) ? "col-lg-" + largeDesktops : string.Empty;
353
354 offsetPhones = !string.IsNullOrWhiteSpace(offsetPhones) ? "col-xs-offset-" + offsetPhones : string.Empty;
355 offsetTablets = !string.IsNullOrWhiteSpace(offsetTablets) ? "col-sm-offset-" + offsetTablets : string.Empty;
356 offsetMediumDesktops = !string.IsNullOrWhiteSpace(offsetMediumDesktops) ? "col-md-offset-" + offsetMediumDesktops : string.Empty;
357 offsetLargeDesktops = !string.IsNullOrWhiteSpace(offsetLargeDesktops) ? "col-lg-offset-" + offsetLargeDesktops : string.Empty;
358
359 pushPhones = !string.IsNullOrWhiteSpace(pushPhones) ? "col-xs-push-" + pushPhones : string.Empty;
360 pushTablets = !string.IsNullOrWhiteSpace(pushTablets) ? "col-sm-push-" + pushTablets : string.Empty;
361 pushMediumDesktops = !string.IsNullOrWhiteSpace(pushMediumDesktops) ? "col-md-push-" + pushMediumDesktops : string.Empty;
362 pushLargeDesktops = !string.IsNullOrWhiteSpace(pushLargeDesktops) ? "col-lg-push-" + pushLargeDesktops : string.Empty;
363
364 pullPhones = !string.IsNullOrWhiteSpace(pullPhones) ? "col-xs-pull-" + pullPhones : string.Empty;
365 pullTablets = !string.IsNullOrWhiteSpace(pullTablets) ? "col-sm-pull-" + pullTablets : string.Empty;
366 pullMediumDesktops = !string.IsNullOrWhiteSpace(pullMediumDesktops) ? "col-md-pull-" + pullMediumDesktops : string.Empty;
367 pullLargeDesktops = !string.IsNullOrWhiteSpace(pullLargeDesktops) ? "col-lg-pull-" + pullLargeDesktops : string.Empty;
368
369 // init
370 var clsCol = string.Join(" ", (new[] {
371 phones, tablets, mediumDesktops, largeDesktops,
372 offsetPhones, offsetTablets, offsetMediumDesktops, offsetLargeDesktops,
373 pushPhones, pushTablets, pushMediumDesktops, pushLargeDesktops,
374 pullPhones, pullTablets, pullMediumDesktops, pullLargeDesktops
375 }).Where(o => !string.IsNullOrWhiteSpace(o)).ToList());
376
377 if (string.IsNullOrWhiteSpace(clsCol)) {
378 clsCol = "col-xs-12";
379 }
380
381 if (maxFeeds <= 0) {
382 maxFeeds = 10;
383 }
384
385 var linkedInAPI = new LinkedInAPI(
386 GetString("Template:DesignBaseUrl"),
387 (string)Pageview.Area.Item["LinkedIn_CompanyId"],
388 (string)Pageview.Area.Item["LinkedIn_State"],
389 (string)Pageview.Area.Item["LinkedIn_ClientId"],
390 (string)Pageview.Area.Item["LinkedIn_ClientSecret"],
391 (string)Pageview.Area.Item["LinkedIn_AuthorizedRedirectURL"]
392 );
393
394 var json = default(string);
395 var feeds = linkedInAPI.GetCompanyUpdates(out json);
396
397 if (feeds != null && feeds.Any()) {
398 feeds = feeds.Take(maxFeeds).ToArray();
399 }
400 }
401 @if (clearfix) {
402 <div class="clearfix"></div>
403 }
404 @if (feeds != null && feeds.Any()) {
405 if (!unwrap) {
406 @: <div class="@(clsCol)">
407 }
408
409 <div class="paragraphlinkedinfeeds-block @(cssClassName)">
410 @foreach (var item in feeds) {
411 if (item.Image != item.Url) {
412 <a href="@(item.Url)" class="paragraphlinkedinfeeds-item">
413 <div class="paragraphlinkedinfeeds-item-image">
414 <img src="@(item.Image)" alt="">
415 </div>
416
417 <div class="paragraphlinkedinfeeds-item-content">
418 <i class="fa fa-linkedin-square" aria-hidden="true"></i> <small>@(item.Date.ToString("d MMMM yyyy"))</small>
419 <p>@(item.Comment)</p>
420 </div>
421 </a>
422 } else {
423 <div class="paragraphlinkedinfeeds-item">
424 <div class="paragraphlinkedinfeeds-item-image">
425 <img src="@(item.Image)" alt="">
426 </div>
427
428 <div class="paragraphlinkedinfeeds-item-content">
429 <i class="fa fa-linkedin-square" aria-hidden="true"></i> <small>@(item.Date.ToString("d MMMM yyyy"))</small>
430 <p>@(item.Comment)</p>
431 </div>
432 </div>
433 }
434 }
435 </div>
436
437 if (!unwrap) {
438 @: </div>
439 }
440 }