-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
448 lines (264 loc) · 283 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Sitecorn</title>
<subtitle>offering a few kernels of knowledge</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://www.sitecorn.be/"/>
<updated>2017-03-25T10:19:31.090Z</updated>
<id>http://www.sitecorn.be/</id>
<author>
<name>Ruben Verschueren</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>fixing WFFM tracking field</title>
<link href="http://www.sitecorn.be/2017/03/24/fixing-WFFM-tracking-field/"/>
<id>http://www.sitecorn.be/2017/03/24/fixing-WFFM-tracking-field/</id>
<published>2017-03-24T14:55:44.215Z</published>
<updated>2017-03-25T10:19:31.090Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>After installing a the new version of WFFM (8.2) we were seeing broken links on existing form items. Thanks to the lovely broken links gutter, to guide us to this mistake.</p><p>After some googling, as any self respecting developer does when facing a problem for the first time, I found this <a href="https://reasoncodeexample.com/2015/03/26/sitecore-linkdatabase-unrecognized-guid-format/" target="_blank" rel="external">blog post</a>. It seems that the custom XML being stored as the raw value of the Tracking field has had an update in the newer WFFM versions. As suggested in the blog, one way to fix this is by opening the attributes and goals of the tracking field and clicking OK, without making any changes. This updates the XML and as if by magic the gutter disappears.</p><p>So what changed in the raw values? Well in the new version, the events now have an ID attribute. Here is an example of the raw values before the “fix”:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><tracking> </span><br><span class="line"><event name="Field Changed" /> </span><br><span class="line"><event name="Field Completed" /> </span><br><span class="line"><event name="Field Not Completed" /> </span><br><span class="line"><event name="Field Out of Boundary" /> </span><br><span class="line"><event name="Invalid Field Syntax" /></span><br><span class="line"></tracking></span><br></pre></td></tr></table></figure><p>And the raw values afer the “fix”:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><tracking></span><br><span class="line"><event id="{7E86B2F5-ACEC-4C60-8922-4EB5AE5D9874}" name="Field Not Completed" /></span><br><span class="line"><event id="{F3D7B20C-675C-4707-84CC-5E5B4481B0EE}" name="Field Out of Boundary" /></span><br><span class="line"><event id="{844BBD40-91F6-42CE-8823-5EA4D089ECA2}" name="Invalid Field Syntax" /></span><br><span class="line"><event id="{AA3AE715-E87D-4B4D-80C7-4290546F770F}" name="Field Changed" /></span><br><span class="line"><event id="{F0113A93-570A-4F69-8C7C-BA08037D1E34}" name="Field Completed" /></span><br><span class="line"></tracking></span><br></pre></td></tr></table></figure><p>Since I didn’t feel like clicking a thousand times to update 400+ forms (older versions are forms too!) I wrote an admin page to fix it. Here’s the code I used. It might not be the cleanest, but it gets the job done. Just save it as an .ASPX file in your site under /sitecore/admin and you are good to go.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br></pre></td><td class="code"><pre><span class="line"><%@ Page Language=<span class="string">"C#"</span> %></span><br><span class="line"><%@ Import Namespace=<span class="string">"System"</span> %></span><br><span class="line"><%@ Import Namespace=<span class="string">"System.Collections.Generic"</span> %></span><br><span class="line"><%@ Import Namespace=<span class="string">"System.Linq"</span> %></span><br><span class="line"><%@ Import Namespace=<span class="string">"Sitecore.ContentSearch"</span> %></span><br><span class="line"><%@ Import Namespace=<span class="string">"Sitecore.ContentSearch.SearchTypes"</span> %></span><br><span class="line"><%@ Import Namespace=<span class="string">"Sitecore.Data"</span> %></span><br><span class="line"><%@ Import Namespace=<span class="string">"Sitecore.Data.Items"</span> %></span><br><span class="line"> <script runat=<span class="string">"server"</span> type=<span class="string">"text/C#"</span>></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">bool</span> authorized = <span class="keyword">false</span>;</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">string</span> UnauthorizedMessage = <span class="string">"You are not authorized to view this page"</span>;</span><br><span class="line"> <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">Page_Load</span>(<span class="params"><span class="keyword">object</span> sender, EventArgs e</span>)</span><br><span class="line"> </span>{ </span><br><span class="line"> <span class="keyword">if</span> (!(<span class="keyword">true</span></span><br><span class="line"> <span class="comment">//&& Request.IsSecureConnection // Check for HTTPS </span></span><br><span class="line"> && Request.UserHostAddress == <span class="string">"127.0.0.1"</span></span><br><span class="line"> && Sitecore.Context.IsLoggedIn</span><br><span class="line"> && Sitecore.Context.IsAdministrator</span><br><span class="line"> <span class="comment">//&& Sitecore.Context.User.IsInRole(@"sitecore\Developer") //check for specific role</span></span><br><span class="line"> ))</span><br><span class="line"> {</span><br><span class="line"> Response.StatusCode = (<span class="keyword">int</span>) System.Net.HttpStatusCode.Forbidden;</span><br><span class="line"> Response.Write(UnauthorizedMessage);</span><br><span class="line"> Response.TrySkipIisCustomErrors = <span class="keyword">true</span>;</span><br><span class="line"> Response.End();</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> authorized = <span class="keyword">true</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> } </span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">FixFields_OnClick</span>(<span class="params"><span class="keyword">object</span> sender, EventArgs e</span>)</span><br><span class="line"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (!authorized)</span><br><span class="line"> {</span><br><span class="line"> output.InnerHtml = <span class="keyword">string</span>.Format(<span class="string">"<div style=\"color:red;\">{0}"</span>, UnauthorizedMessage);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> ID formTemplateId = <span class="keyword">new</span> ID(<span class="string">"{FFB1DA32-2764-47DB-83B0-95B843546A7E}"</span>);</span><br><span class="line"> ID contenTreeId = <span class="keyword">new</span> ID(<span class="string">"{0DE95AE4-41AB-4D01-9EB0-67441B7C2450}"</span>);</span><br><span class="line"> ISearchIndex index = ContentSearchManager.GetIndex(<span class="string">"sitecore_master_index"</span>);</span><br><span class="line"> <span class="keyword">string</span> TrackingFieldName = <span class="string">"__tracking"</span>;</span><br><span class="line"> <span class="keyword">int</span> changeCount = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">int</span> errorCount = <span class="number">0</span>;</span><br><span class="line"> output.InnerHtml += <span class="string">"<div>Starting update of fields</div>"</span>;</span><br><span class="line"></span><br><span class="line"> Dictionary<<span class="keyword">string</span>, <span class="keyword">string</span>> replacements = GetReplacements();</span><br><span class="line"> List<Item> indexResults = <span class="keyword">null</span>;</span><br><span class="line"> <span class="keyword">using</span> (IProviderSearchContext context = index.CreateSearchContext())</span><br><span class="line"> {</span><br><span class="line"> indexResults = context.GetQueryable<SearchResultItem>()</span><br><span class="line"> .Where(x => x.TemplateId == formTemplateId</span><br><span class="line"> && x.Paths.Contains(contenTreeId))</span><br><span class="line"> .Select(x => x.GetItem()).ToList();</span><br><span class="line"></span><br><span class="line"> indexResults = indexResults.Where(x => x != <span class="keyword">null</span>).Where(x => x.Fields[TrackingFieldName] != <span class="keyword">null</span>).ToList();</span><br><span class="line"> <span class="keyword">if</span> (!indexResults.Any())</span><br><span class="line"> {</span><br><span class="line"> output.InnerHtml += <span class="string">"<div>No Form items found to modify. </div>"</span>;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">foreach</span> (Item item <span class="keyword">in</span> indexResults)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">try</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">string</span> <span class="keyword">value</span> = item.Fields[TrackingFieldName].Value;</span><br><span class="line"> <span class="keyword">foreach</span> (<span class="keyword">var</span> dictionaryItem <span class="keyword">in</span> replacements)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">value</span> = <span class="keyword">value</span>.Replace(dictionaryItem.Key, dictionaryItem.Value);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> item.Editing.BeginEdit();</span><br><span class="line"> <span class="keyword">using</span> (<span class="keyword">new</span> EditContext(item))</span><br><span class="line"> {</span><br><span class="line"> item.Fields[TrackingFieldName].Value = <span class="keyword">value</span>;</span><br><span class="line"> output.InnerHtml += <span class="keyword">string</span>.Format(<span class="string">"<div>Item - {0} - changed</div>"</span>, item.Name);</span><br><span class="line"> }</span><br><span class="line"> item.Editing.EndEdit();</span><br><span class="line"> changeCount++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">catch</span> (Exception ex)</span><br><span class="line"> {</span><br><span class="line"> output.InnerHtml += <span class="keyword">string</span>.Format(<span class="string">"<div>Item - {0} - {1}</div>"</span>, item.Name, ex.Message);</span><br><span class="line"> errorCount++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> output.InnerHtml += <span class="keyword">string</span>.Format(<span class="string">"<div>Update of tracking fields finished. {0} items modified, {1} errors ocurred. </div>"</span>, changeCount, errorCount);</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> Dictionary<<span class="keyword">string</span>, <span class="keyword">string</span>> GetReplacements()</span><br><span class="line"> {</span><br><span class="line"> Dictionary<<span class="keyword">string</span>, <span class="keyword">string</span>> replacements = <span class="keyword">new</span> Dictionary<<span class="keyword">string</span>, <span class="keyword">string</span>>();</span><br><span class="line"> replacements.Add(<span class="string">"<event name=\"Field Changed\" />"</span>, <span class="string">"<event id=\"{AA3AE715-E87D-4B4D-80C7-4290546F770F}\" name=\"Field Changed\" />"</span>);</span><br><span class="line"> replacements.Add(<span class="string">"<event name=\"Field Completed\" />"</span>, <span class="string">"<event id=\"{F0113A93-570A-4F69-8C7C-BA08037D1E34}\" name=\"Field Completed\" />"</span>);</span><br><span class="line"> replacements.Add(<span class="string">"<event name=\"Field Not Completed\" />"</span>, <span class="string">"<event id=\"{7E86B2F5-ACEC-4C60-8922-4EB5AE5D9874}\" name=\"Field Not Completed\" />"</span>);</span><br><span class="line"> replacements.Add(<span class="string">"<event name=\"Field Out of Boundary\" />"</span>, <span class="string">"<event id=\"{F3D7B20C-675C-4707-84CC-5E5B4481B0EE}\" name=\"Field Out of Boundary\" />"</span>);</span><br><span class="line"> replacements.Add(<span class="string">"<event name=\"Invalid Field Syntax\" />"</span>, <span class="string">"<event id=\"{844BBD40-91F6-42CE-8823-5EA4D089ECA2}\" name=\"Invalid Field Syntax\" />"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> replacements;</span><br><span class="line"> } </span><br><span class="line"> </script></span><br><span class="line"><!DOCTYPE html></span><br><span class="line"><html xmlns=<span class="string">"http://www.w3.org/1999/xhtml"</span>></span><br><span class="line"><head runat=<span class="string">"server"</span>></span><br><span class="line"> <title>WFFM <span class="number">8.2</span> fix tracking field</title></span><br><span class="line"></head></span><br><span class="line"><body></span><br><span class="line"> <form id=<span class="string">"trackingUpdater"</span> runat=<span class="string">"server"</span>></span><br><span class="line"> <h3>Update tracking field <span class="keyword">for</span> WFFM form items</h3></span><br><span class="line"> <div style=<span class="string">"margin-left:15px;"</span>></span><br><span class="line"> Click the button below to fix the Tracking field <span class="keyword">for</span> WFFM forms. This will add ID attributes to the selected items <span class="keyword">in</span> <span class="keyword">this</span> field.</span><br><span class="line"> Modify the dictionary to replace more/less <span class="keyword">as</span> needed.</span><br><span class="line"> <br/><br/></span><br><span class="line"> <asp:Button runat=<span class="string">"server"</span> ID=<span class="string">"FixFields"</span> OnClick=<span class="string">"FixFields_OnClick"</span> Text=<span class="string">"Update form tracking field"</span> /></span><br><span class="line"> </div></span><br><span class="line"> <div id=<span class="string">"output"</span> runat=<span class="string">"server"</span> style=<span class="string">"width: 1000px; height: 500px; overflow-scrolling: auto;"</span>></span><br><span class="line"> </div></span><br><span class="line"> </form></span><br><span class="line"></body></span><br><span class="line"></html></span><br></pre></td></tr></table></figure><p>The dictionary can be easily expanded in case you selected any other goals or attributes in this field. I only added the ones that I had selected in my forms.</p><!-- rebuild by neat -->]]></content>
<summary type="html">
Fixing broken links on WFFM forms after upgrade
</summary>
<category term="sitecore" scheme="http://www.sitecorn.be/tags/sitecore/"/>
<category term="upgrade" scheme="http://www.sitecorn.be/tags/upgrade/"/>
<category term="migrate" scheme="http://www.sitecorn.be/tags/migrate/"/>
<category term="WFFM 8.2" scheme="http://www.sitecorn.be/tags/WFFM-8-2/"/>
<category term="bug" scheme="http://www.sitecorn.be/tags/bug/"/>
</entry>
<entry>
<title>upgrade-sitecore 6.5 to 8.2 - part 3</title>
<link href="http://www.sitecorn.be/2017/03/17/upgrade-sitecore-6-5-to-8-2-part-3/"/>
<id>http://www.sitecorn.be/2017/03/17/upgrade-sitecore-6-5-to-8-2-part-3/</id>
<published>2017-03-17T09:11:50.413Z</published>
<updated>2017-03-24T14:32:58.596Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><blockquote><p>Reality check</p></blockquote><p>In <a href="http://www.sitecorn.be/2016/10/19/upgrade-sitecore-6-5-to-8-2-part-2/">part 2</a> I talked about manually upgrading 6.5 to 7.2 and then using the Express Migration Tool, to take it to 8.2. Fortunately, by the time I got started, 6.6 was already supported by EMT.</p><p>Here are the high level steps I took to get to 8.2:</p><ul><li>Made backup of site and databases</li><li>Updated config files to 6.6 in VS solution</li><li>Updated dll references in solution to new sitecore dll versions</li><li>Updated dll references to 3rd party modules</li><li>Referenced new version of HTMLAgilityPack</li></ul><p>The third step was the most annoying here. I had to download the source code of the modules, replace the sitecore references and recompile. Most of them worked with minor tweaking here and there, so I could add them back into my VS solution. The project also heavily relied on 3rd party implementations of the company that originally developed the solution. This included (but was certainly not limited to) a custom buckets setup that didn’t really work well on a split CM and CD setup. I removed all of the references to their dll’s and started commenting out code until my project would build.</p><p>After this was done I was finally running on Sitecore 6.6 with a semi-disabled custom solution. Time for the EMT to do it’s thing…. and it did. after a few hours my site was upgraded to Sitecore 8.2. This meant it was once again time to update my sitecore references, comment out or modify code specific to 6.6 and get my VS solution to build again.</p><p>Once that was done I had a running 8.2 solution and a very ugly website with very few functionality. Time to bucle down and deep dive into the code, fixing commented out code and rewriting parts that were bugging me.</p><p>Deciding what to keep, what to change and what to throw out and rebuild is the biggest challenge in a project like this. Unfortunately I can’t give you any clear answers here but I would suggest to change only what’s needed.</p><p>I started with adding code generation for templates and a few item locations because I did not want to keep updating the existing POCO classes and “FieldInfo” classes. Hard coded strings give me nightmares, so I’ll let TDS worry about that and generate some code for me. After that I changed the way the 3rd party had implemented repositories (aka Search), configuration (which are items with a ton of fields) and dictionary (again custom).</p><p>Since this is now an 8.2 I thought I’d get on board with Helix and made these parts as foundations and/or features. Now if you’re reading this, you’re in the same boat as me so don’t do what I did next. I made a nice foundation for the base functionality of the repositories and started to move the concrete ones into helix features.</p><p>Turns out these existing repositories liked to keep their POCO classes close and the FieldInfo classes and they like their own POCO’s and FieldInfo’s and … You can guess the rest. after a few days of messing about, I had around 40 foundations with a lot of references between them. It may not be the best setup, but at least it provides a better view on what is in this project.</p><p><strong>A note on templates</strong></p><p>A problem that seems to occur with sitecore upgrades is the template inheritance tab being broken. There is usually a YSOD pointing to the fieldtype.</p><div class="figure"><img src="/images/TemplateInheritanceBug.png" title="Template Inheritance bug"></div><p>The easiest albeit time consuming method of fixing this is opening the template that has the bug (since not all of them may be affected). Switch on Raw Values and copy the contents of the base templates field to your favourite text editor.</p><div class="figure"><img src="/images/RawValuesSelected.png" title="View Raw values"></div><div class="figure"><img src="/images/StandardTemplateBasetemplates.png" title="standard template base templates"></div><p>I’m sure you can guess where this is going, open the templates belonging to these templates and set field types for those fields that have none selected. When you’ve gone through all of them the error should be gone. In my case there were some field sections on the standard template that were causing the issue. The following fields had no field type:</p><ul><li>Appearance section : **_Preview** field</li><li>Layout section : **_Controller** field</li><li>Tasks : **_Archive Version date** field</li></ul><p>In case this didn’t fix your problem there was an old bug in the sitecore 6-ish versions. In that case it was the _Owner field. Switch to the <strong>core</strong> database. open your content editor and select /sitecore/templates/System/Templates/Sections/Security Finally assign a “Single-Line Text” field type to the __Owner field. And that’s the end of that YSOD.</p><!-- rebuild by neat -->]]></content>
<summary type="html">
upgrade part 3
</summary>
<category term="sitecore" scheme="http://www.sitecorn.be/tags/sitecore/"/>
<category term="upgrade" scheme="http://www.sitecorn.be/tags/upgrade/"/>
<category term="migrate" scheme="http://www.sitecorn.be/tags/migrate/"/>
<category term="fieldtype error" scheme="http://www.sitecorn.be/tags/fieldtype-error/"/>
<category term="template inheritance" scheme="http://www.sitecorn.be/tags/template-inheritance/"/>
</entry>
<entry>
<title>upgrade sitecore 6.5 to 8.2 - part 2</title>
<link href="http://www.sitecorn.be/2016/10/19/upgrade-sitecore-6-5-to-8-2-part-2/"/>
<id>http://www.sitecorn.be/2016/10/19/upgrade-sitecore-6-5-to-8-2-part-2/</id>
<published>2016-10-19T09:51:20.985Z</published>
<updated>2016-10-19T10:22:52.841Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:06 GMT+0100 (Romance Standard Time) --><blockquote><p>On second thought…</p></blockquote><p>In <a href="http://www.sitecorn.be/2016/10/07/upgrade-sitecore-6-5-to-8-2-part1/">part 1</a> I described my temporary plan of attack for upgrading a Sitecore 6.5 project to 8.2. After a nice discussion on the Sitecore community slack I revised my initial plan. Basically I’m going to attach the existing databases to a vanilla site setup and upgrade. Separately I’ll upgrade the code and config to work with a 8.2 site. Finally the two will be linked, resulting in a perfect 8.2 project… or at least that’s the idea and it will have an old(er) codebase.</p><p>As for the code part only necessary changes will be made to get everything up and running. meaning changing or upgrading modules and rewriting code if needed. Sadly that means a lot of sheer UI and webforms code will remain for now.</p><p>The preparation plan will be mostly the same so I’ll leave it out in this post. The upgrade strategy has been changed and is now more detailed.</p><p><strong>Sitecore database upgrade</strong></p><ol style="list-style-type:decimal"><li>Stop development</li><li>Clear publishing and event queues. set longer timeouts in web.config</li><li>Shrink and rebuild db indexes</li><li>Update all environments with production content (take care not to loose not deployed development)</li><li>Link to vanilla site installations</li><li>Upgrade to version 7.2 (or whichever version is supported by then)</li><li>Use Express Migration Tool to upgrade to sitecore version 8.2</li><li>Backup analysis and upgrade reports and logs</li></ol><p><strong>Steps for upgrading new site to next version</strong></p><ol style="list-style-type:decimal"><li>Backup master/core/web/analytics databases of previous version</li><li>Restore backups to DB’s with new version number</li><li>Change app_config/connectionstrings.config to point to new databases (which are still in older version)</li><li>Upgrade databases to new version</li></ol><p>Refer to my post on <a href="http://www.sitecorn.be/2016/10/17/duplicate-sql-databases-in-bulk/">bulk duplicating databases</a> to see how I make the backups and restore duplicates.</p><p><strong>Code / file upgrade</strong></p><ol style="list-style-type:decimal"><li>Modify/upgrade config files to Sitecore version 8.2.</li><li>Refactor code for Sitecore 8.2, commenting out all broken (third party or custom) code.</li><li>Build/deploy this minimal version.</li><li>Use the vanilla site versions until 8.2 is reached</li><li>After upgrading databases, start deploying (working parts of) the code</li><li>Gradually fix the code and update/replace the modules as needed</li><li>Start updating the broken code / modules.</li><li>Deploy version 8.2 (without modules) to staging or whatever temporary QA site</li><li>Have key users verify the minimal 8.2 version on staging or whatever temporary QA site</li><li>Build and deploy upgraded code</li><li>Have key users retest entire site.</li></ol><p><strong>Steps for updating code to 8.2 version</strong></p><ol style="list-style-type:decimal"><li>Branch code</li><li>Modify publish settings and other references to site -> vanilla version 8.2</li><li>Change all references for Sitecore version 6.5 to version 8.2</li><li>Build, bugfix and deploy to site version 8.2</li><li>Run (smoke) tests on site 8.2 (still with vanilla db)</li></ol><p><strong>Link upgraded databases to upgraded site files</strong></p><ol style="list-style-type:decimal"><li>Backup Site and upgraded databases</li><li>Change connection strings to upgraded database</li><li>Test, bugfix and retest</li></ol><!-- rebuild by neat -->]]></content>
<summary type="html">
upgrade part 2 - on second thought let's take a slightly different approach
</summary>
<category term="sitecore" scheme="http://www.sitecorn.be/tags/sitecore/"/>
<category term="upgrade" scheme="http://www.sitecorn.be/tags/upgrade/"/>
<category term="migrate" scheme="http://www.sitecorn.be/tags/migrate/"/>
</entry>
<entry>
<title>duplicate sql databases in bulk</title>
<link href="http://www.sitecorn.be/2016/10/17/duplicate-sql-databases-in-bulk/"/>
<id>http://www.sitecorn.be/2016/10/17/duplicate-sql-databases-in-bulk/</id>
<published>2016-10-17T14:14:13.074Z</published>
<updated>2016-10-19T09:47:08.430Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:04 GMT+0100 (Romance Standard Time) --><p>This method can be used to create backups and restore databases (with a new name). This is usefull when you need to quickly setup a test version of multiple databases or in case you want to intigrate it as a build step during development. I’ll be using it to setup copies of sitecore databases before upgrading to a new version.</p><p>First make sure the logical file names of your databases are the same as the database name. For instance the <strong>Sitecore_Analytics</strong> database should have logical name <strong>Sitecore_Analytics</strong> for the mdf file and logical name <strong>Sitecore_Analytics_log</strong> for the ldf file. This allows the stored procedure to find the files to copy.</p><p>Check the logical filenames in a backup:</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">restore filelistonly <span class="keyword">from</span> disk = <span class="string">'D:/Data/backup/Sitecore_Analytics.bak'</span></span><br></pre></td></tr></table></figure><p></p><h3 id="stored-procedure">Stored procedure</h3><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">SET ANSI_NULLS ON</span><br><span class="line">GO</span><br><span class="line">SET QUOTED_IDENTIFIER ON</span><br><span class="line">GO</span><br><span class="line"></span><br><span class="line">CREATE PROCEDURE DuplicateDatabase</span><br><span class="line"> @<span class="function">sourceDb <span class="title">nvarchar</span>(<span class="params"><span class="number">50</span></span>),</span><br><span class="line"> @removeChars <span class="title">nvarchar</span>(<span class="params"><span class="number">45</span></span>),</span><br><span class="line"> @postfix <span class="title">nvarchar</span>(<span class="params"><span class="number">5</span></span>),</span><br><span class="line"> @backupPath <span class="title">nvarchar</span>(<span class="params"><span class="number">400</span></span>),</span><br><span class="line"> @sqlServerDbFolder <span class="title">nvarchar</span>(<span class="params"><span class="number">100</span></span>)</span><br><span class="line">AS</span><br><span class="line">BEGIN </span><br><span class="line"> DECLARE @sourceDb_log <span class="title">nvarchar</span>(<span class="params"><span class="number">50</span></span>)</span>;</span><br><span class="line"> DECLARE @<span class="function">destDb <span class="title">nvarchar</span>(<span class="params"><span class="number">50</span></span>)</span>;</span><br><span class="line"> DECLARE @<span class="function">destMdf <span class="title">nvarchar</span>(<span class="params"><span class="number">100</span></span>)</span>;</span><br><span class="line"> DECLARE @<span class="function">destLdf <span class="title">nvarchar</span>(<span class="params"><span class="number">100</span></span>)</span>;</span><br><span class="line"></span><br><span class="line">SET @sourceDb_log = Replace(@sourceDb, @removeChars,<span class="string">''</span>) + <span class="string">'_log'</span></span><br><span class="line">SET @backupPath = @backupPath + @sourceDb + <span class="string">'.bak'</span> --ATTENTION: file must already exist and SQL Server must have access to it</span><br><span class="line"></span><br><span class="line">SET @destDb = @sourceDb + @postfix</span><br><span class="line">SET @destMdf = @sqlServerDbFolder + @destDb + <span class="string">'.mdf'</span></span><br><span class="line">SET @destLdf = @sqlServerDbFolder + @destDb + <span class="string">'_log'</span> + <span class="string">'.ldf'</span></span><br><span class="line"></span><br><span class="line"> BACKUP DATABASE @sourceDb TO DISK = @backupPath</span><br><span class="line"></span><br><span class="line"> RESTORE DATABASE @destDb FROM DISK = @backupPath</span><br><span class="line"> WITH REPLACE,</span><br><span class="line"> MOVE @sourceDb TO @destMdf,</span><br><span class="line"> MOVE @sourceDb_log TO @destLdf</span><br><span class="line">END</span><br><span class="line">GO</span><br></pre></td></tr></table></figure><h3 id="execute-stored-procedure-for-each-db">Execute stored procedure for each DB</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">exec DuplicateDatabase </span><br><span class="line">'Sitecore_Analytics' -- db name</span><br><span class="line">,'_V6.5' -- chars to remove from original db name </span><br><span class="line">,'_V6.6' -- postfix for new db name</span><br><span class="line">,'D:\data\backup\' -- backup location</span><br><span class="line">,'D:\data\' -- new db files location</span><br></pre></td></tr></table></figure><p>You can use the second parameter to remove characters from the original database name. This allows you to copy a xxx_V6.6 database as a xxx_V6.7 database. To create the next version all you need to to is replace the postfix and the database names. Since this may take a few minutes per DB, I would recommended to execute this one DB at a time to avoid any timeouts and more easily detect errors.</p><!-- rebuild by neat -->]]></content>
<summary type="html">
How to easily duplicate databases with a stored procedure
</summary>
<category term="sql server" scheme="http://www.sitecorn.be/tags/sql-server/"/>
<category term="t-sql" scheme="http://www.sitecorn.be/tags/t-sql/"/>
<category term="maintenance" scheme="http://www.sitecorn.be/tags/maintenance/"/>
<category term="sitecore" scheme="http://www.sitecorn.be/tags/sitecore/"/>
</entry>
<entry>
<title>The Sitecore Upgrade 6.5 to 8.2 - part 1</title>
<link href="http://www.sitecorn.be/2016/10/07/upgrade-sitecore-6-5-to-8-2-part1/"/>
<id>http://www.sitecorn.be/2016/10/07/upgrade-sitecore-6-5-to-8-2-part1/</id>
<published>2016-10-07T15:05:00.546Z</published>
<updated>2016-10-19T10:25:47.223Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><blockquote><p>I will take the <del>ring</del> Sitecore to <del>Mordor</del> 8.2 – though I do not know the way.</p></blockquote><p>My newest project consists of taking an outdated Sitecore 6.5 project, dust it off and prepare it for the future as a Sitecore 8.2 project. Since a complete rebuild is out of the question I’m left with two options; migrate or upgrade. In case the analytics data can be dropped, Sitecore recommends migration. This would mean creating a clean 8.2 solution and bringing in the code, items, config and other good stuff.</p><p>The other, longer, way is to upgrade. Since the <a href="https://dev.sitecore.net/Downloads/Express_Migration_Tool.aspx" target="_blank" rel="external">Express Migration Tool</a> only supports projects in version 7.2 and up we’ll have to upgade manually. At least until we reach 7.2 and can use the tool.</p><p>Below you may find my preliminary plan to tackle such an upgrade. The first part consists mainly of mapping out the current situation and determining risks and breaking changes in between versions.</p><p><strong>Upgrade preparation plan</strong></p><ul><li>Identify state of all environments (which version/branch of the solution is deployed where</li><li>If possible deploy latest version everywhere (preferably done with original dev)</li><li>Identify custom code and which parts of sitecore it plugs in to (together with original dev)</li><li>Identify configuration coupling: which files need to be changed and which can be used as a whole (together with original dev)</li><li>Set up a (manual) test plan for smoke testing site in each intermediate version</li><li>List deprecated functionalities of each intermediate version to determine code to be modified</li><li>List modules that need to be upgraded/replaced</li><li>List prerequisites for each intermediate version</li><li>Choose appropriate windows and SQL server version</li><li>Run a link checker before any new upgrade to check for any extra problems.</li><li>Decide which errors can be ignored (but should be documented) until reaching the final version</li><li>Discuss upgrade strategy with Sitecore (sharing as much info as possible from previous steps), they might have a few tricks up their sleave for this.</li></ul><p><strong>High level upgrade strategy</strong></p><ul><li>Stop development</li><li>Clear publishing and event queues. set longer timeouts in web.config</li><li>Shrink and rebuild db indexes</li><li>Update all environments with production content (take care not to loose not deployed development)</li><li>Upgrade to version x</li><li>Backup analysis and upgrade reports and logs</li><li>Test, compare to x-1 and backup version x</li><li>Deploy version x to staging or whatever temporary QA site</li><li>Have key users verify version x on staging or whatever temporary QA site</li><li>Upgrade to version x+1</li><li>… repeat until version 7.2 (or whichever version is supported by then)</li><li>Use Express Migration Tool</li><li>If possible destroy webforms and replace with MVC</li></ul><p>This is only the beginning, a lot of choices have to made and discussed with the client. stay tuned for the <a href="http://www.sitecorn.be/2016/10/19/upgrade-sitecore-6-5-to-8-2-part-2/">next</a> exciting episode of The Sitecore Upgrade</p><!-- rebuild by neat -->]]></content>
<summary type="html">
upgrade part 1 - this is a story of a version long ago, a time of bugs and outdated technology. Let's find out if it can be brought into the present.
</summary>
<category term="sitecore" scheme="http://www.sitecorn.be/tags/sitecore/"/>
<category term="upgrade" scheme="http://www.sitecorn.be/tags/upgrade/"/>
<category term="migrate" scheme="http://www.sitecorn.be/tags/migrate/"/>
</entry>
<entry>
<title>adding a country to existing uCommerce catalog</title>
<link href="http://www.sitecorn.be/2016/07/28/add-a-country-to-existing-ucommerce-catalog/"/>
<id>http://www.sitecorn.be/2016/07/28/add-a-country-to-existing-ucommerce-catalog/</id>
<published>2016-07-28T12:54:43.298Z</published>
<updated>2016-09-08T15:35:43.967Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>After creating two different catalogs for two different countries (US and Italy) in our uCommerce solution, I needed to add another country. This time however the Italy store and catalog are changed (manually) into an <a href="https://en.wikipedia.org/wiki/Europe,_the_Middle_East_and_Africa" target="_blank" rel="external">EMEA</a> store. Therefore the new country is added to this EMEA store, in my case, using the same payment method and currency.</p><p>Basically you can use the stored procedure for creating a <a href="http://sitecorn.be/2016/07/08/duplicate-ucommerce-store/" target="_blank" rel="external">new store</a> and remove the things you do not need. You will need to change the parameters somewhat to link the new country to the payment method (and perhaps other relations).</p><p>Here’s the stored procedure that let’s you do that.</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SET</span> ANSI_NULLS <span class="keyword">ON</span></span><br><span class="line"><span class="keyword">GO</span></span><br><span class="line"><span class="keyword">SET</span> QUOTED_IDENTIFIER <span class="keyword">ON</span></span><br><span class="line"><span class="keyword">GO</span></span><br><span class="line"><span class="comment">-- =============================================</span></span><br><span class="line"><span class="comment">-- Author: Ruben Verschueren</span></span><br><span class="line"><span class="comment">-- Create date: 2016/07/28</span></span><br><span class="line"><span class="comment">-- Description: creates a new uCommerce country store </span></span><br><span class="line"><span class="comment">-- and adds it to an existing store</span></span><br><span class="line"><span class="comment">-- =============================================</span></span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">PROCEDURE</span> AddCountryToStore </span><br><span class="line">@createdBy <span class="keyword">nvarchar</span>(<span class="number">20</span>),</span><br><span class="line">@currencyIsoCode <span class="keyword">nvarchar</span>(<span class="number">4</span>),</span><br><span class="line">@currenctExchangeRate <span class="built_in">int</span>,</span><br><span class="line">@countryName <span class="keyword">nvarchar</span>(<span class="number">25</span>),</span><br><span class="line">@vatRate <span class="built_in">decimal</span>(<span class="number">5</span>,<span class="number">2</span>),</span><br><span class="line">@priceGroupDescription <span class="keyword">nvarchar</span>(<span class="number">250</span>),</span><br><span class="line">@cultureCode <span class="keyword">nvarchar</span>(<span class="number">6</span>), </span><br><span class="line">@paymentMethodId <span class="built_in">int</span>,</span><br><span class="line">@feePercent <span class="built_in">decimal</span>(<span class="number">18</span>,<span class="number">4</span>),</span><br><span class="line">@shippingMethodName <span class="keyword">nvarchar</span>(<span class="number">128</span>),</span><br><span class="line">@productCatalogId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">AS</span></span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line"><span class="keyword">SET</span> NOCOUNT <span class="keyword">ON</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">DECLARE</span> @currencyId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @pricegroupId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @countryId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @shippingMethodId <span class="built_in">int</span> </span><br><span class="line"><span class="keyword">DECLARE</span> @definitionTypeId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @emailProfileId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @orderNumberId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @productCatalogGroupId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @ProductCatalogPriceGroupRelationId <span class="built_in">int</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SELECT</span> @definitionTypeId = definitionTypeId </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_DefinitionType </span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = <span class="string">'PaymentMethod'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SELECT</span> @emailProfileId = emailprofileid </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_EmailProfile </span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> =<span class="string">'Default'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SELECT</span> @orderNumberId = ordernumberid </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_OrderNumberSerie </span><br><span class="line"><span class="keyword">WHERE</span> OrderNumberName = <span class="string">'Default'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- create currency</span></span><br><span class="line"><span class="keyword">SELECT</span> @currencyId = currencyid </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_Currency </span><br><span class="line"><span class="keyword">WHERE</span> isocode = @currencyIsoCode <span class="keyword">AND</span> deleted = <span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">IF</span> (@currencyId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'currency already exists'</span> </span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_Currency(isocode,exchangerate,deleted,guid) </span><br><span class="line"> <span class="keyword">VALUES</span> (@currencyIsoCode, @currenctExchangeRate, <span class="number">0</span>, NEWID())</span><br><span class="line"> <span class="keyword">SELECT</span> @currencyId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- create pricegroup </span></span><br><span class="line"><span class="keyword">SELECT</span> @pricegroupId = pricegroupid </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_PriceGroup </span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = @countryName <span class="keyword">AND</span> currencyId = @currencyId</span><br><span class="line"></span><br><span class="line"><span class="keyword">IF</span> (@pricegroupId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'pricegroup already exists'</span> </span><br><span class="line"> <span class="keyword">UPDATE</span> uCommerce_PriceGroup </span><br><span class="line"> <span class="keyword">SET</span> deleted = <span class="number">0</span> <span class="keyword">WHERE</span> <span class="keyword">name</span> = @countryName <span class="keyword">AND</span> currencyId = @currencyId</span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_PriceGroup(<span class="keyword">name</span>,currencyid,vatrate,description,</span><br><span class="line"> createdon,createdby,modifiedon,modifiedby,deleted,guid)</span><br><span class="line"> <span class="keyword">VALUES</span> (@countryName ,@currencyId,@vatRate, @priceGroupDescription,<span class="keyword">getdate</span>(),</span><br><span class="line"> @createdBy,<span class="keyword">getdate</span>(),@createdBy,<span class="number">0</span>,NEWID())</span><br><span class="line"> <span class="keyword">SELECT</span> @pricegroupId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- create country</span></span><br><span class="line"><span class="keyword">SELECT</span> @countryId = countryid </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_Country </span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = @countryName <span class="keyword">AND</span> Culture = @cultureCode</span><br><span class="line"><span class="keyword">IF</span> (@countryId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'country already exists'</span></span><br><span class="line"> <span class="keyword">UPDATE</span> uCommerce_Country </span><br><span class="line"> <span class="keyword">SET</span> deleted = <span class="number">0</span></span><br><span class="line"> <span class="keyword">WHERE</span> <span class="keyword">name</span> = @countryName</span><br><span class="line"> <span class="keyword">AND</span> Culture = @cultureCode</span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_Country(<span class="keyword">name</span>,culture,deleted) </span><br><span class="line"> <span class="keyword">VALUES</span> (@countryName, @cultureCode, <span class="number">0</span>)</span><br><span class="line"> <span class="keyword">SELECT</span> @countryId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span> </span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">-- needed?</span></span><br><span class="line"><span class="keyword">SELECT</span> @shippingMethodId = ShippingMethodId </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_ShippingMethod </span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = @shippingMethodName <span class="keyword">AND</span> paymentmethodId = @paymentMethodId</span><br><span class="line"><span class="keyword">IF</span> (@shippingMethodId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'shipping method already exists'</span></span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_ShippingMethod(<span class="keyword">name</span>,PaymentMethodId,ServiceName,deleted) </span><br><span class="line"> <span class="keyword">VALUES</span> (@shippingMethodName, @paymentMethodId, <span class="string">'SinglePriceService'</span>, <span class="number">0</span>)</span><br><span class="line"> <span class="keyword">SELECT</span> @shippingMethodId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span> </span><br><span class="line"></span><br><span class="line"><span class="comment">--map shipping method to country</span></span><br><span class="line"><span class="keyword">IF</span>((<span class="keyword">SELECT</span> <span class="keyword">count</span>(*) </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_ShippingMethodCountry </span><br><span class="line"><span class="keyword">WHERE</span> CountryId = @countryId <span class="keyword">and</span> shippingMethodId = @shippingMethodId) = <span class="number">0</span>)</span><br><span class="line"><span class="keyword">BEGIN</span> </span><br><span class="line"><span class="keyword">INSERT</span> uCommerce_ShippingMethodCountry(CountryId,shippingMethodId)</span><br><span class="line"><span class="keyword">VALUES</span>(@CountryId,@shippingMethodId)</span><br><span class="line"><span class="keyword">END</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- create ProductCatalog pricegroup relation</span></span><br><span class="line"><span class="keyword">SELECT</span> @ProductCatalogPriceGroupRelationId = ProductCatalogPriceGroupRelationId </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_ProductCatalogPriceGroupRelation</span><br><span class="line"><span class="keyword">WHERE</span> ProductCatalogId = @productCatalogId <span class="keyword">and</span> PriceGroupId = @pricegroupId</span><br><span class="line"><span class="keyword">IF</span> (@ProductCatalogPriceGroupRelationId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'ProductCatalog is already linked to pricegroup'</span></span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_ProductCatalogPriceGroupRelation</span><br><span class="line"> (productcatalogid,PriceGroupId,SortOrder) </span><br><span class="line"> <span class="keyword">VALUES</span> (@productCatalogId,@priceGroupId,<span class="number">0</span>)</span><br><span class="line"> <span class="keyword">SELECT</span> @ProductCatalogPriceGroupRelationId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">END</span></span><br></pre></td></tr></table></figure><p>Now that we created the stored procedure, we can execute it as many times as we want adding more countries to our store. Obviously you need to change the values of the parameters especially the PaymentMethodId and productCatalogId. In the uCommerce backend you will now see the new country, pricegroup etc. If you open up the catalog, you will now see the new country as an option in the allowed priceGroups. Just enable the checkbox and you’re good to go… after you add all the prices on the products that is.</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">EXEC AddCountryToStore </span><br><span class="line">'Ruben' <span class="comment">--createdBy</span></span><br><span class="line">,'EUR' <span class="comment">--CurrencyIsoCode</span></span><br><span class="line">,100 <span class="comment">--currentExchangeRate</span></span><br><span class="line">,'Netherlands' <span class="comment">--countryName</span></span><br><span class="line">,0.21 <span class="comment">--vatRate</span></span><br><span class="line">,'Pricing for NL eCommerce' <span class="comment">--priceGroupDescription</span></span><br><span class="line">,'nl-NL' <span class="comment">--cultureCode</span></span><br><span class="line">,8 <span class="comment">--PaymentMethodId</span></span><br><span class="line">,0.0000 <span class="comment">--feePerentage</span></span><br><span class="line">,'MyShippingMethod' <span class="comment">--shippingmethodName</span></span><br><span class="line">,5 <span class="comment">--productCatalogId</span></span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
<summary type="html">
how to add a country to an existing uCommerce catalog
</summary>
<category term="ucommerce" scheme="http://www.sitecorn.be/tags/ucommerce/"/>
<category term="sql" scheme="http://www.sitecorn.be/tags/sql/"/>
</entry>
<entry>
<title>markdown to blog and documents</title>
<link href="http://www.sitecorn.be/2016/07/26/markdown-to-blog-and-documents/"/>
<id>http://www.sitecorn.be/2016/07/26/markdown-to-blog-and-documents/</id>
<published>2016-07-26T11:45:09.868Z</published>
<updated>2016-09-08T15:42:21.098Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>Recently I started using markdown files as a quick way to write documentation on projects. At first I didn’t bother converting the files as there is at least one <a href="https://chrome.google.com/webstore/detail/markdown-preview-plus/febilkbfcbhebfnokafefeacimjdckgl?utm_source=chrome-app-launcher-info-dialog" target="_blank" rel="external">plug in</a> in chrome that can render them as HTML. In Visual studio I just used the <a href="https://visualstudiogallery.msdn.microsoft.com/0855e23e-4c4c-4c82-8b39-24ab5c5a7f79" target="_blank" rel="external">Markdown Mode</a> extension to work with.</p><p>Then I thought of starting a (static) blog and since I already had markdown files, I was in the market for a static site generator. After trying out several different generators I settled on <a href="https://hexo.io/" target="_blank" rel="external">Hexo</a> which works with simple command line instructions to create posts (in markdown) and generate a site from them.</p><p>I could then easily host this static site on github pages. Refer to the deployment page of the <a href="https://hexo.io/docs/deployment.html" target="_blank" rel="external">Hexo documentation</a> on how to achieve that. There are a lot of blog posts out there on how to set this up as well if you need further assistance.</p><p>Now I still wanted to have these documents in my project folder as documentation, so I looked for a way to generate them without all the headers and navigation and such that I would have on the blog. I could a new theme or renderer to Hexo, but I found a better alternative called <a href="http://pandoc.org/installing.html" target="_blank" rel="external">Pandoc</a>. This lets me generate PDF files from markdown. So now I have one source document written in markdown and (at least) two different output formats.</p><p>There are still some issues I’m having, that I want to clear up. The first is a problem with image links Hexo seems to like a leading slash in the image URLs, while Pandoc only seems to work without. Now I haven’t spent much time on this, so there’s bound to be a solution for it.</p><p>The second issue is that now I have two different tools to render the output. It’s not a big problem but I would like to have them both in a single command or pipeline. At the moment this is how I do it. I’m using windows command line to navigate to the Hexo directory first.</p><p><strong>create a new post</strong></p><p>Using the statement below creates a new markdown document in the _posts folder of your Hexo folder structure.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo <span class="keyword">new</span> post <span class="string">"Post Name"</span></span><br></pre></td></tr></table></figure><p><strong>generate my site</strong></p><p>This command generates the full site in the public folder.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo generate</span><br></pre></td></tr></table></figure><p><strong>copy the generated site to a local IIS site</strong></p><p>As I want to verify that the site works (and also to have an offline copy), I have a local IIS site setup. This is in a different location so I can see what would be deployed.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xcopy D:\SITE_PATH\<span class="keyword">public</span> D:\[IIS_SITE_PATH]\Sitecorn /e /d</span><br></pre></td></tr></table></figure><p><strong>Copy to a GIT repository</strong></p><p>For the moment I’m not using the hexo deploy feature. I have several GIT repositories set up for other projects so it makes sense to have this one in the same location. I commit and deploy this repository with the github desktop application, but there are many more tools out there you could use.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xcopy D:\Projects\sitecorn\<span class="keyword">public</span> C:\Users\rubenv\Documents\GitHub\rubenVerschueren.github.io /e /d</span><br></pre></td></tr></table></figure><p><strong>Generate PDF documents</strong></p><p>This command loops through the markdown documents and uses Pandoc to generate the PDF files and puts them in the LOCATION folder.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> /r %<span class="function">i <span class="title">in</span> (<span class="params">_posts<span class="comment">/*.md) do pandoc _posts/%~ni.md -o LOCATION/%~ni.pdf</span></span></span></span><br></pre></td></tr></table></figure><p>Finally if you only need to generate a single file you can use the following command.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pandoc source/_posts/my_document.md -o portal/my_document.pdf</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
<summary type="html">
how to use markdown to generate a static blog and pandoc to generate lovely pdf files
</summary>
<category term="pdf" scheme="http://www.sitecorn.be/tags/pdf/"/>
<category term="blog" scheme="http://www.sitecorn.be/tags/blog/"/>
<category term="markdown" scheme="http://www.sitecorn.be/tags/markdown/"/>
</entry>
<entry>
<title>modifying sitecore itemlinks</title>
<link href="http://www.sitecorn.be/2016/07/08/modifying-sitecore-itemlinks/"/>
<id>http://www.sitecorn.be/2016/07/08/modifying-sitecore-itemlinks/</id>
<published>2016-07-08T14:48:36.254Z</published>
<updated>2016-09-08T15:41:21.077Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>I recently had to modify an archive functionality in which you could archive an item or one of it’s children. If you archived child A then it’s parent would be cloned or copied (depending on the situation) to the archive and the child would be moved. But we also have other items that were referencing this item and it would also be possible to archive just one language version. I won’t go into the rather complex rules of the archiving command, but basically I needed to duplicate all references to the child item and link them to the archived item.</p><p>I poked around the web a bit and the <a href="http://www.sitecoreexperts.com/2014/09/bi-directional-one-to-many-and-many-to-many-relationships-in-sitecore/" target="_blank" rel="external">sitecore experts</a> blog sent me in the right direction.</p><p>I used their GetReferrers method to retrieve an IEnumerable of ItemLinks to the original item.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> IEnumerable<ItemLink> <span class="title">GetReferrers</span>(<span class="params">Item item, ID sourceFieldId = <span class="keyword">null</span></span>)</span><br><span class="line"></span>{</span><br><span class="line"> ItemLink[] referrers = sourceFieldId != <span class="keyword">null</span> <span class="keyword">as</span> ID</span><br><span class="line"> ? Globals.LinkDatabase.GetReferrers(item, sourceFieldId)</span><br><span class="line"> : Globals.LinkDatabase.GetReferrers(item);</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> referrers;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>After that it is just a matter of looping through the item links and adding a new link to the source item. In case of unarchiving I needed the opposite method to delete some item links, so I added that as well.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">AddLinks</span>(<span class="params">Item source, Item target</span>)</span><br><span class="line"></span>{</span><br><span class="line"> IEnumerable<ItemLink> referencingItems = GetReferrers(source, Constants.FieldId1);</span><br><span class="line"> referencingItems.Union(GetReferrers(source, Constants.FieldId2));</span><br><span class="line"> List<ItemLink> links = referencingItems.ToList();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (links == <span class="keyword">null</span> || !links.Any())</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">foreach</span> (ItemLink itemLink <span class="keyword">in</span> links)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (itemLink.SourceFieldID != Guid.Empty.ToID())</span><br><span class="line"> {</span><br><span class="line"> Item linkSource = itemLink.GetSourceItem();</span><br><span class="line"> linkSource.Editing.BeginEdit();</span><br><span class="line"> <span class="keyword">string</span> fieldName = linkSource.Fields.FirstOrDefault(f => f.ID == itemLink.SourceFieldID).Name;</span><br><span class="line"> ((MultilistField)linkSource.Fields[fieldName]).Add(target.ID.ToString());</span><br><span class="line"> linkSource.Editing.AcceptChanges();</span><br><span class="line"> linkSource.Editing.EndEdit();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">DeleteLinks</span>(<span class="params">Item item</span>)</span><br><span class="line"></span>{</span><br><span class="line"> IEnumerable<ItemLink> referencingItems = GetReferrers(item, Constants.FieldId1);</span><br><span class="line"> referencingItems.Union(GetReferrers(item, Constants.FieldId2));</span><br><span class="line"> List<ItemLink> links = referencingItems.ToList();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (links == <span class="keyword">null</span> || !links.Any())</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">foreach</span> (ItemLink itemLink <span class="keyword">in</span> links)</span><br><span class="line"> {</span><br><span class="line"> Item source = itemLink.GetSourceItem();</span><br><span class="line"> source.Editing.BeginEdit();</span><br><span class="line"> MultilistField field = source.Fields.FirstOrDefault(f => f.ID == itemLink.SourceFieldID);</span><br><span class="line"> <span class="keyword">if</span> (field.Contains(item.ID.ToString()))</span><br><span class="line"> {</span><br><span class="line"> field.Remove(item.ID.ToString());</span><br><span class="line"> }</span><br><span class="line"> source.Editing.AcceptChanges();</span><br><span class="line"> source.Editing.EndEdit();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Seeing as both these methods are almost identical, some refactoring is required. It turns out this pattern has a name, the “hole in the middle pattern”. I personally would have called it the donut (doughnut) pattern.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">ModifyLinks</span>(<span class="params">Action<MultilistField, Item> action, Item sourceItem, Item targetItem = <span class="keyword">null</span></span>)</span><br><span class="line"></span>{</span><br><span class="line"> IEnumerable<ItemLink> referencingItems = GetReferrers(sourceItem, IDownloadConstants.ProductsFieldId);</span><br><span class="line"> referencingItems.Union(GetReferrers(sourceItem, ISoftware_InformationConstants.ProductsFieldId));</span><br><span class="line"> List<ItemLink> links = referencingItems.ToList();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (links == <span class="keyword">null</span> || !links.Any())</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">foreach</span> (ItemLink itemLink <span class="keyword">in</span> links)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (itemLink.SourceFieldID != Guid.Empty.ToID())</span><br><span class="line"> {</span><br><span class="line"> Item source = itemLink.GetSourceItem();</span><br><span class="line"> source.Editing.BeginEdit();</span><br><span class="line"> MultilistField field = source.Fields.FirstOrDefault(f => f.ID == itemLink.SourceFieldID);</span><br><span class="line"></span><br><span class="line"> action(field, targetItem);</span><br><span class="line"></span><br><span class="line"> source.Editing.AcceptChanges();</span><br><span class="line"> source.Editing.EndEdit();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Delete links like in the following snippet, where you pass the source item twice.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">ModifyLinks((field, target) => {</span><br><span class="line"> <span class="keyword">if</span> (field.Contains(target.ID.ToString()))</span><br><span class="line"> {</span><br><span class="line"> field.Remove(target.ID.ToString());</span><br><span class="line"> }</span><br><span class="line">}, item, item);</span><br></pre></td></tr></table></figure><p>Add links in a similar fashion by passing in the source item and the target item. The first being the one you want to copy the links from and the latter being the one you want a new link to.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ModifyLinks((field, target) => {field.Add(target.ID.ToString());}, item, addedItem);</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
<summary type="html">
duplicating item references with the donut pattern
</summary>
<category term="sitecore 8" scheme="http://www.sitecorn.be/tags/sitecore-8/"/>
<category term="itemlink" scheme="http://www.sitecorn.be/tags/itemlink/"/>
</entry>
<entry>
<title>custom Adyen skin</title>
<link href="http://www.sitecorn.be/2016/07/08/custom-adyen-skin/"/>
<id>http://www.sitecorn.be/2016/07/08/custom-adyen-skin/</id>
<published>2016-07-08T14:30:35.974Z</published>
<updated>2016-09-08T15:34:46.174Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>When creating my first skin for Adyen I ran into the problem of translations. Adyen has got it’s language files which you can modify and update as much as you want. But here’s the kicker, once uploaded you cannot reach those files from your skin. This means that if you created a nice header with some text that needs translating, you’ll have to do it yourself.</p><p>So that’s what I did. I added some custom JSON files containing the required translations. They are stored as text files with the locale in the file name. I kept the name resources for convenience. example: resources_it_IT.txt Note that the hyphen is replaced with an underscore.</p><h3 id="shortcuts">Shortcuts</h3><p>Because I had trouble uploading these files in separate folders, I keep them in my javascript folder for now. I took another shortcut in the JSON (again as a proof of concept). The JSON structure is super simple and contains key/value pairs. The keys are actually the CSS selectors I will use to find the location of the text that needs to be translated This results in a somewhat dirty file, but keeps everything nice and simple.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="string">".contact"</span>: <span class="string">"Questions? Call us .... "</span>,</span><br><span class="line"> <span class="string">"h2"</span> : <span class="string">"CHECKOUT"</span>,</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="script-with-jquery">Script with jQuery</h3><p>The javascript itself is also quite simple. I get the shopperLocale from the form that gets rendered inside the skin and default it to en-GB. Next I set the link on the logo on my skin to homepage in the correct language. Before getting the file, you need to construct a url which points to the correct directory. This has the following format: <strong>/sf/[SKINCODE]/js/[RESOURCE_FILE_NAME]</strong></p><p>Finally I get the file with the needed translations via an AJAX call, loop through the data and use the key/value pairs to set my translation on the page. All of which gets executed when the page has finished loading. Since I already had jquery loaded for other parts, I used it for this code as well.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// determine correct locale</span></span><br><span class="line"><span class="keyword">var</span> locale = $(<span class="string">'[name="shopperLocale"]'</span>).val();</span><br><span class="line"><span class="keyword">if</span> (locale == <span class="literal">null</span> || locale === <span class="string">""</span>) {</span><br><span class="line"> locale = <span class="string">"en_GB"</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// set logo url to correct language, example: http://www.YOURDOMAIN.com/en-gb/</span></span><br><span class="line">$(<span class="string">".logo"</span>).attr(<span class="string">"href"</span>, <span class="string">"http://www.YOURDOMAIN.com/"</span> + locale.replace(<span class="string">"_"</span>, <span class="string">"-"</span>) + <span class="string">"/"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// construct resource url</span></span><br><span class="line"><span class="keyword">var</span> resourceUrl = <span class="string">"/sf/kTcgNKNd/js/resources_"</span> + locale + <span class="string">".txt"</span>;</span><br><span class="line"></span><br><span class="line">$.ajax({</span><br><span class="line"> url: resourceUrl,</span><br><span class="line"> contentType: <span class="string">"application/json; charset=utf-8"</span>,</span><br><span class="line"> dataType: <span class="string">"json"</span>,</span><br><span class="line"> success: <span class="function"><span class="keyword">function</span>(<span class="params">data</span>) </span>{</span><br><span class="line"> <span class="comment">// loop through data and set translation text</span></span><br><span class="line"> $.each(data, <span class="function"><span class="keyword">function</span> (<span class="params">key, val</span>) </span>{</span><br><span class="line"> $(key).html(val);</span><br><span class="line"> }); </span><br><span class="line"> },</span><br><span class="line"> error: <span class="function"><span class="keyword">function</span>(<span class="params">xhr, ajaxOptions, thrownError</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(xhr.status);</span><br><span class="line"> <span class="built_in">console</span>.log(thrownError);</span><br><span class="line"> }</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>As a final note to this, make sure all links to files in your skin have the same structure as the resource url. I haven’t had much luck with relative url’s using ../ in them. For instance here’s what the part of my skin footer that loads jquery and my script.</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"/sf/kTcgNKNd/js/jquery.min.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"><span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"/sf/kTcgNKNd/js/checkout.js></script></span></span></span><br></pre></td></tr></table></figure><h3 id="display-custom-data">Display custom data</h3><p>Besides the need to display a large amount of data on the HPP (Hosted Payment Page), the customer wanted to display an overview of the order. The problem is that all data you submit to the HPP should be a encoded in the Merchant Signature and the more fields you add the more complicated everything gets. The solution is to make a dictionary of strings and serialize the object as json. This way you can pass it all as the orderdata field.</p><p>another way to do it is to build the html using some sort of string builder and pass that, perhaps url encode it before serializing just to be sure.</p><p>To decode it on the Adyen skin I used the following script. Since I used a dictionary of type <strong>dictionary<string ,="" string=""></string></strong>, I get name / value pairs after de-serialization so I added span tags to the skin which used the same names for their ID attribute.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> orderDataString = <span class="built_in">decodeURIComponent</span>($(<span class="string">"[name='orderData']"</span>).val());</span><br><span class="line"><span class="keyword">var</span> orderJson = $.parseJSON(orderDataString);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> cost = $(<span class="string">"[name='paymentAmount']"</span>).val();</span><br><span class="line"><span class="keyword">if</span> (cost !== <span class="string">""</span> &amp;&amp; cost !== <span class="number">0</span>) {</span><br><span class="line"> cost = cost / <span class="number">100</span>;</span><br><span class="line">}</span><br><span class="line">$(<span class="string">"#totalCost"</span>).html(cost + <span class="string">" "</span> + $(<span class="string">"[name='currencyCode']"</span>).val());</span><br><span class="line"></span><br><span class="line">$.each(orderJson, <span class="function"><span class="keyword">function</span> (<span class="params">index, obj</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> ($(<span class="string">"#"</span> + obj.Name) != <span class="literal">undefined</span> && obj.Value != <span class="literal">undefined</span> </span><br><span class="line"> && obj.Value !== <span class="string">""</span>) {</span><br><span class="line"> <span class="keyword">var</span> val = obj.Value.split(<span class="string">"+"</span>).join(<span class="string">" "</span>);</span><br><span class="line"> <span class="keyword">if</span> (obj.Name === <span class="string">"billingPhone"</span>) {</span><br><span class="line"> val = <span class="string">"+"</span> + val.substring(<span class="number">1</span>, val.length - <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (obj.Name === <span class="string">"backLink"</span>) {</span><br><span class="line"> $(<span class="string">"#"</span> + obj.Name).attr(<span class="string">"href"</span>, val);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> $(<span class="string">"#"</span> + obj.Name).html(val);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>In our case we were integrating with Sitecore and uCommerce. When submitting our first tests to the HPP’s we quickly realized it was a bust. As it turned out uCommerce was still using the SHA1 hashing to calculate the HMAC for the merchant signature. We requested the code they used and adapted it to use the SHA256 hashing. We gave our code back, so in case you need it before the next release, just ask your uCommerce buddy and he can hook you up.</p><p>In case you have some other .NET implementation, I made a pull request to the Adyen github, which was since added to their examples. Here you can find the new <a href="https://github.com/Adyen/asp.net/tree/master/AdyenExamples/1.HPP" target="_blank" rel="external">HPP example</a>.</p><h3 id="d-security">3D security</h3><p>If you want to add extra security, Adyen can activate the 3D secure option. For the shopper this means another form to fill out after the completion of the HPP. This extra page is provided by the card issues (aka the bank) so you don’t have any control over it. This includes the layout if you were wondering.</p><p>Our customer wanted to be extra safe, so we had Adyen enabe the 3D secure option. And that’s when it all blew up in my face. When you clicked on the pay button on the HPP page it started flashing. I soon realized this was the javascript that tried to add in the translations. It didn’t have the correct data however since it was the HPP and not our generated payment page that was being submitted.</p><p>To make matters worse there wasn’t any obvious indication why this was happening as everything worked fine without the 3D secure. After inspecting the skin closely I noticed a few issues. The first being we had some elements with the ID’s that Adyen’s was using for their elements on the HPP.</p><p>The biggest issue was that we added a form element in our skin which had the “pageform” as ID. So you can probably guess what happened. Adyen inserts a form element of it’s own with the same id. In fact the form they add, was inserted inside our form element. They’re using javascript to submit the form with id “pageform” and so it all came tumbling down.</p><p>In hindsight we didn’t need the form, so we could easily solve the problem by removing the form from our skin and using different id’s.</p><p>Another issue that can occur is that the payment is authorised but the issuer has some sort of issue. this results in a correct payment, without 3D secure. In that case it’s up to your customer to decide what to do. Adyen can set up rules to support two scenario’s.</p><p>Either the payment is accepted and the shopper is redirected to your confirmation/success page or the fraud score can be raised for those cases and the shopper is redirected to your cancel page.</p><!-- rebuild by neat -->]]></content>
<summary type="html">
displaying custom data and translations on an Adyen skin
</summary>
<category term="adyen skin" scheme="http://www.sitecorn.be/tags/adyen-skin/"/>
<category term="hpp" scheme="http://www.sitecorn.be/tags/hpp/"/>
</entry>
<entry>
<title>duplicating a UCommerce Store</title>
<link href="http://www.sitecorn.be/2016/07/08/duplicate-ucommerce-store/"/>
<id>http://www.sitecorn.be/2016/07/08/duplicate-ucommerce-store/</id>
<published>2016-07-08T14:15:46.185Z</published>
<updated>2016-09-08T15:44:53.069Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>In a recent project we used uCommerce (6.XX) with Sitecore 8.1 to implement an international webshop.</p><p>Each language in sitecore will eventually be linked to it’s own shop, starting with the italian one (linked to it-IT). We opted to create a separate store per country/language in uCommerce because each of them would have some unique features. Some would have different prices, SKU’s, tax calculation and so on.</p><p>After we finished the Italian shop, we wanted to duplicate it so that the content editors wouldn’t have to enter all the common data again. As it turns out this isn’t supported (yet) by uCommerce. After confirming with our uCommerce buddy, I wrote an SQL script that would do just that.</p><p>If you are reading this it means you might be thinking of doing the same thing, so I must warn you I took a few shortcuts here and there. For instance the product definitions are not duplicated and the script has some hard coded things like disabling product reviews. All this can be easily changed in the stored procedure code below. As the goal was only to do the bulk of the work you might want to create/duplicate more data.</p><p>Here’s a list of what the script creates or duplicates:</p><ul><li>Currency</li><li>PriceGroup</li><li>Country (and existing country is activated)</li><li>Definition</li><li>Payment Method</li><li>Shipping Method</li><li>ProductCatalogGroup</li><li>Mapping between Shipping Method and ProductCatalogGroup</li><li>Mapping between Shipping Methood and Payment Method</li><li>Product Catalog</li><li>Mapping between Product Catalog and PriceGroup</li><li>Categories of products</li><li>Products (duplicating existing only)</li><li>Product properties</li><li>Product description</li><li>Product Category relation</li><li>Price</li><li>Variants</li><li>Variant Properties</li><li>Variant Description</li><li>Variant Price</li></ul><p>You can call the stored procedure with the following script. All you have to do is feed in the correct parameters for you situation. The one shortcut I really don’t like is the SKU suffix. product SKU’s have to be unique so I add the suffix to garantee that. Since the content editor has to enter new ones anyway it’s not that big of a deal.</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">EXEC CreateStore </span><br><span class="line">'Ruben' <span class="comment">--createdBy</span></span><br><span class="line">,'USD' <span class="comment">--CurrencyIsoCode</span></span><br><span class="line">,143 <span class="comment">--currentExchangeRate</span></span><br><span class="line">,'United States' <span class="comment">--countryName</span></span><br><span class="line">,0.22 <span class="comment">--vatRate</span></span><br><span class="line">,'Pricing for US eCommerce' <span class="comment">--priceGroupDescription</span></span><br><span class="line">,'en-US' <span class="comment">--cultureCode</span></span><br><span class="line">,'Adyen' <span class="comment">--definitionName</span></span><br><span class="line">,'Configuration for Adyen' <span class="comment">--definitionDescription</span></span><br><span class="line">,'Adyen Test' <span class="comment">--PaymentMethodName</span></span><br><span class="line">,'Adyen' <span class="comment">--paymentMethodSeviceName</span></span><br><span class="line">,0.0000 <span class="comment">--feePerentage</span></span><br><span class="line">,'ShipmentName' <span class="comment">--shippingmethodName</span></span><br><span class="line">,'United States' <span class="comment">--productCatalogGroupName</span></span><br><span class="line">,'CatalogName' <span class="comment">--productCatalogName</span></span><br><span class="line">,24 <span class="comment">--parentCatalog</span></span><br><span class="line">,'CategoryName' <span class="comment">--productCategoryDefinitionName</span></span><br><span class="line">,'_US' <span class="comment">--SKU_suffix</span></span><br></pre></td></tr></table></figure><p>And finally the stored procedure script. With the exception of the products (and related data) I always check if the data already exists, so you could execute the stored procedure several times if you wanted to. This was mostly handy during the development and saved me a lot of cleaning up. This way I could add the next bit and just execute the entire thing again without having to restore my database.</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">PROCEDURE</span> CreateStore </span><br><span class="line">@createdBy <span class="keyword">nvarchar</span>(<span class="number">20</span>),</span><br><span class="line">@currencyIsoCode <span class="keyword">nvarchar</span>(<span class="number">4</span>),</span><br><span class="line">@currenctExchangeRate <span class="built_in">int</span>,</span><br><span class="line">@countryName <span class="keyword">nvarchar</span>(<span class="number">25</span>),</span><br><span class="line">@vatRate <span class="built_in">decimal</span>(<span class="number">5</span>,<span class="number">2</span>),</span><br><span class="line">@priceGroupDescription <span class="keyword">nvarchar</span>(<span class="number">250</span>),</span><br><span class="line">@cultureCode <span class="keyword">nvarchar</span>(<span class="number">6</span>),</span><br><span class="line">@definitionName <span class="keyword">nvarchar</span>(<span class="number">512</span>),</span><br><span class="line">@definitionDescription <span class="keyword">nvarchar</span>(<span class="keyword">max</span>),</span><br><span class="line">@paymentMethodName <span class="keyword">nvarchar</span>(<span class="number">50</span>),</span><br><span class="line">@paymentMethodServiceName <span class="keyword">nvarchar</span>(<span class="number">50</span>),</span><br><span class="line">@feePercent <span class="built_in">decimal</span>(<span class="number">18</span>,<span class="number">4</span>),</span><br><span class="line">@shippingMethodName <span class="keyword">nvarchar</span>(<span class="number">128</span>),</span><br><span class="line">@productCatalogGroupName <span class="keyword">nvarchar</span>(<span class="number">128</span>),</span><br><span class="line">@productCatalogName <span class="keyword">nvarchar</span>(<span class="number">128</span>),</span><br><span class="line">@parentCatalog <span class="built_in">int</span>,</span><br><span class="line">@productCategoryDefinitionName <span class="keyword">nvarchar</span>(<span class="number">128</span>),</span><br><span class="line">@skuSuffix <span class="keyword">nvarchar</span>(<span class="number">5</span>)</span><br><span class="line"><span class="keyword">AS</span></span><br><span class="line"><span class="keyword">BEGIN</span> </span><br><span class="line"><span class="keyword">SET</span> NOCOUNT <span class="keyword">ON</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">DECLARE</span> @currencyId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @pricegroupId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @countryId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @paymentMethodId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @shippingMethodId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @definitionId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @definitionTypeId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @emailProfileId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @orderNumberId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @productCatalogGroupId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @productCatalogId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @ProductCatalogPriceGroupRelationId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @ProjectCategoryId <span class="built_in">int</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SELECT</span> @definitionTypeId = definitionTypeId </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_DefinitionType </span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = <span class="string">'PaymentMethod'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SELECT</span> @emailProfileId = emailprofileid </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_EmailProfile </span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> =<span class="string">'Default'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SELECT</span> @orderNumberId = ordernumberid </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_OrderNumberSerie </span><br><span class="line"><span class="keyword">WHERE</span> OrderNumberName = <span class="string">'Default'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SELECT</span> @ProjectCategoryId = definitionid </span><br><span class="line"><span class="keyword">FROM</span> ucommerce_Definition </span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = @productCategoryDefinitionName</span><br><span class="line"></span><br><span class="line"><span class="comment">-- create currency</span></span><br><span class="line"><span class="keyword">SELECT</span> @currencyId = currencyid </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_Currency </span><br><span class="line"><span class="keyword">WHERE</span> isocode = @currencyIsoCode <span class="keyword">AND</span> deleted = <span class="number">0</span></span><br><span class="line"><span class="keyword">IF</span> (@currencyId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'currency already exists'</span> </span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_Currency(isocode,exchangerate,deleted,guid) </span><br><span class="line"> <span class="keyword">VALUES</span> (@currencyIsoCode, @currenctExchangeRate, <span class="number">0</span>, NEWID())</span><br><span class="line"> <span class="keyword">SELECT</span> @currencyId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- create pricegroup </span></span><br><span class="line"><span class="keyword">SELECT</span> @pricegroupId = pricegroupid </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_PriceGroup </span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = @countryName <span class="keyword">AND</span> currencyId = @currencyId</span><br><span class="line"><span class="keyword">IF</span> (@pricegroupId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'pricegroup already exists'</span> </span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_PriceGroup(<span class="keyword">name</span>,currencyid,vatrate,description,</span><br><span class="line"> createdon,createdby,modifiedon,modifiedby,deleted,guid)</span><br><span class="line"> <span class="keyword">VALUES</span> (@countryName ,@currencyId,@vatRate, @priceGroupDescription,</span><br><span class="line"> <span class="keyword">getdate</span>(),@createdBy,<span class="keyword">getdate</span>(),@createdBy,<span class="number">0</span>,NEWID())</span><br><span class="line"> <span class="keyword">SELECT</span> @pricegroupId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- create country</span></span><br><span class="line"><span class="keyword">SELECT</span> @countryId = countryid </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_Country </span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = @countryName <span class="keyword">AND</span> Culture = @cultureCode</span><br><span class="line"><span class="keyword">IF</span> (@countryId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'country already exists, activating it'</span></span><br><span class="line"> <span class="keyword">UPDATE</span> uCommerce_Country </span><br><span class="line"> <span class="keyword">SET</span> deleted = <span class="number">0</span></span><br><span class="line"> <span class="keyword">WHERE</span> <span class="keyword">name</span> = @countryName</span><br><span class="line"> <span class="keyword">AND</span> Culture = @cultureCode</span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_Country(<span class="keyword">name</span>,culture,deleted) </span><br><span class="line"> <span class="keyword">VALUES</span> (@countryName, @cultureCode, <span class="number">0</span>)</span><br><span class="line"> <span class="keyword">SELECT</span> @countryId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span> </span><br><span class="line"></span><br><span class="line"><span class="comment">-- create definition</span></span><br><span class="line"><span class="keyword">SELECT</span> @definitionId = definitionId </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_Definition </span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = @definitionName <span class="keyword">AND</span> DefinitionTypeId = @definitionTypeId</span><br><span class="line"><span class="keyword">IF</span> (@definitionId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'definition already exists'</span></span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_Definition(<span class="keyword">name</span>,definitiontypeid,description,deleted,sortorder,guid,builtin) </span><br><span class="line"> <span class="keyword">VALUES</span> (@definitionName, @definitionTypeId, @definitionDescription,<span class="number">0</span>,<span class="number">0</span>,NEWID(),<span class="number">0</span>)</span><br><span class="line"> <span class="keyword">SELECT</span> @definitionId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span> </span><br><span class="line"></span><br><span class="line"><span class="comment">-- create payment method</span></span><br><span class="line"><span class="keyword">SELECT</span> @paymentMethodId = paymentMethodId </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_PaymentMethod</span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = @paymentMethodName </span><br><span class="line"><span class="keyword">AND</span> paymentMethodServiceName = @paymentMethodServiceName </span><br><span class="line"><span class="keyword">AND</span> definitionId = @definitionId</span><br><span class="line"><span class="keyword">IF</span> (@paymentmethodid <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'payment method already exists'</span></span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> ucommerce_paymentmethod(<span class="keyword">name</span>,feepercent,paymentmethodservicename,enabled,deleted,</span><br><span class="line"> modifiedon,modifiedby,pipeline,definitionid)</span><br><span class="line"> <span class="keyword">VALUES</span> (@paymentmethodname, @feepercent, @paymentmethodservicename,<span class="number">1</span>,<span class="number">0</span>,</span><br><span class="line"> <span class="keyword">getdate</span>(),@createdby,<span class="string">'checkout'</span>,@definitionid)</span><br><span class="line"> <span class="keyword">SELECT</span> @paymentmethodid = scope_identity()</span><br><span class="line"> <span class="keyword">END</span> </span><br><span class="line"></span><br><span class="line"><span class="comment">-- create shippingMethod</span></span><br><span class="line"><span class="keyword">SELECT</span> @shippingMethodId = ShippingMethodId </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_ShippingMethod </span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = @shippingMethodName </span><br><span class="line"><span class="keyword">AND</span> paymentmethodId = @paymentMethodId</span><br><span class="line"></span><br><span class="line"><span class="keyword">IF</span> (@shippingMethodId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'shipping method already exists'</span></span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_ShippingMethod(<span class="keyword">name</span>,PaymentMethodId,ServiceName,deleted) </span><br><span class="line"> <span class="keyword">VALUES</span> (@shippingMethodName, @paymentMethodId, <span class="string">'SinglePriceService'</span>, <span class="number">0</span>)</span><br><span class="line"> <span class="keyword">SELECT</span> @shippingMethodId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span> </span><br><span class="line"></span><br><span class="line"><span class="comment">-- create ProductCatalogGroup</span></span><br><span class="line"><span class="keyword">SELECT</span> @productCatalogGroupId = productCatalogGroupId </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_ProductCatalogGroup</span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = @productCatalogGroupName </span><br><span class="line"><span class="keyword">AND</span> emailprofileId = @emailProfileId </span><br><span class="line"><span class="keyword">AND</span> currencyid= @currencyId <span class="keyword">AND</span> ordernumberId = @orderNumberId</span><br><span class="line"><span class="keyword">IF</span> (@productCatalogGroupId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'ProductCatalogGroup already exists'</span></span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_ProductCatalogGroup(<span class="keyword">name</span>,EmailProfileId,currencyid,domainid,</span><br><span class="line"> OrderNumberId,deleted,CreateCustomersAsMembers,ProductReviewsRequireApproval,guid ) </span><br><span class="line"> <span class="keyword">VALUES</span> (@productCatalogGroupName, @emailProfileId,@currencyid,<span class="string">'website'</span>,</span><br><span class="line"> @orderNumberId,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,NEWID())</span><br><span class="line"> <span class="keyword">SELECT</span> @productCatalogGroupId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span> </span><br><span class="line"></span><br><span class="line"><span class="comment">--map shipping method to product catalog group</span></span><br><span class="line"><span class="keyword">IF</span>((<span class="keyword">SELECT</span> <span class="keyword">count</span>(*) <span class="keyword">FROM</span> uCommerce_ProductCatalogGroupShippingMethodMap </span><br><span class="line"><span class="keyword">WHERE</span> productcataloggroupid = @productCatalogGroupId <span class="keyword">AND</span> shippingMethodId = @shippingMethodId) = <span class="number">0</span>)</span><br><span class="line"><span class="keyword">BEGIN</span> </span><br><span class="line"><span class="keyword">INSERT</span> uCommerce_ProductCatalogGroupShippingMethodMap(productcataloggroupid,shippingMethodId)</span><br><span class="line"><span class="keyword">VALUES</span>(@productCatalogGroupId,@shippingMethodId)</span><br><span class="line"><span class="keyword">END</span></span><br><span class="line"></span><br><span class="line"><span class="comment">--map shipping method to country</span></span><br><span class="line"><span class="keyword">IF</span>((<span class="keyword">SELECT</span> <span class="keyword">count</span>(*) <span class="keyword">FROM</span> uCommerce_ShippingMethodCountry </span><br><span class="line"><span class="keyword">WHERE</span> CountryId = @countryId <span class="keyword">AND</span> shippingMethodId = @shippingMethodId) = <span class="number">0</span>)</span><br><span class="line"><span class="keyword">BEGIN</span> </span><br><span class="line"><span class="keyword">INSERT</span> uCommerce_ShippingMethodCountry(CountryId,shippingMethodId)</span><br><span class="line"><span class="keyword">VALUES</span>(@CountryId,@shippingMethodId)</span><br><span class="line"><span class="keyword">END</span></span><br><span class="line"></span><br><span class="line"><span class="comment">--map shipping method to paymentmethod</span></span><br><span class="line"><span class="keyword">IF</span>((<span class="keyword">SELECT</span> <span class="keyword">count</span>(*) <span class="keyword">FROM</span> uCommerce_ShippingMethodPaymentMethods </span><br><span class="line"><span class="keyword">WHERE</span> PaymentMethodId = @paymentMethodId <span class="keyword">AND</span> shippingMethodId = @shippingMethodId) = <span class="number">0</span>)</span><br><span class="line"><span class="keyword">BEGIN</span> </span><br><span class="line"><span class="keyword">INSERT</span> uCommerce_ShippingMethodPaymentMethods(paymentMethodId,shippingMethodId)</span><br><span class="line"><span class="keyword">VALUES</span>(@paymentMethodId,@shippingMethodId)</span><br><span class="line"><span class="keyword">END</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- create ProductCatalog</span></span><br><span class="line"><span class="keyword">SELECT</span> @productCatalogId = productCatalogId </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_ProductCatalog</span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">name</span> = @productCatalogName </span><br><span class="line"><span class="keyword">AND</span> ProductCatalogGroupId = @productCatalogGroupId </span><br><span class="line"><span class="keyword">AND</span> PriceGroupId = @pricegroupId</span><br><span class="line"><span class="keyword">IF</span> (@productCatalogId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'ProductCatalog already exists'</span></span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_ProductCatalog(productcataloggroupid,<span class="keyword">name</span>,pricegroupid,ShowPricesIncludingVAT,</span><br><span class="line"> IsVirtual,DisplayOnWebSite,LimitedAccess,Deleted,CreatedBy,CreatedOn,ModifiedBy,ModifiedOn,</span><br><span class="line"> SortOrder,guid) </span><br><span class="line"> <span class="keyword">VALUES</span> (@productCatalogGroupId,@productCatalogName,@pricegroupId,<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>,@createdBy,<span class="keyword">getdate</span>(),</span><br><span class="line"> @createdBy,<span class="keyword">getdate</span>(),<span class="number">0</span>,NEWID())</span><br><span class="line"> <span class="keyword">SELECT</span> @productCatalogId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span> </span><br><span class="line"></span><br><span class="line"><span class="comment">-- create ProductCatalog pricegroup relation</span></span><br><span class="line"><span class="keyword">SELECT</span> @ProductCatalogPriceGroupRelationId = ProductCatalogPriceGroupRelationId </span><br><span class="line"><span class="keyword">FROM</span> uCommerce_ProductCatalogPriceGroupRelation</span><br><span class="line"><span class="keyword">WHERE</span> ProductCatalogId = @productCatalogId <span class="keyword">and</span> PriceGroupId = @pricegroupId</span><br><span class="line"><span class="keyword">IF</span> (@ProductCatalogPriceGroupRelationId <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> PRINT <span class="string">'ProductCatalog is already linked to pricegroup'</span></span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"><span class="keyword">ELSE</span></span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_ProductCatalogPriceGroupRelation(productcatalogid,PriceGroupId,SortOrder) </span><br><span class="line"> <span class="keyword">VALUES</span> (@productCatalogId,@priceGroupId,<span class="number">0</span>)</span><br><span class="line"> <span class="keyword">SELECT</span> @ProductCatalogPriceGroupRelationId = SCOPE_IDENTITY()</span><br><span class="line"> <span class="keyword">END</span> </span><br><span class="line"></span><br><span class="line"><span class="comment">-- create Categories for catalog</span></span><br><span class="line"><span class="keyword">IF</span>((<span class="keyword">SELECT</span> <span class="keyword">count</span>(categoryId) <span class="keyword">FROM</span> uCommerce_Category </span><br><span class="line"><span class="keyword">WHERE</span> productCatalogId = @productCatalogId <span class="keyword">AND</span> definitionId = @ProjectCategoryId) = <span class="number">0</span>)</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> uCommerce_Category(<span class="keyword">name</span>,DisplayOnSite,createdon,ParentCategoryId,</span><br><span class="line">ProductCatalogId,ModifiedOn,ModifiedBy,Deleted,SortOrder,CreatedBy,DefinitionId,guid)</span><br><span class="line"><span class="keyword">SELECT</span> <span class="keyword">name</span>,DisplayOnSite,<span class="keyword">getdate</span>(),ParentCategoryId,</span><br><span class="line">@productCatalogId,<span class="keyword">getdate</span>(),@createdBy,<span class="number">0</span>,<span class="number">0</span>,@createdBy,@ProjectCategoryId,NEWID()</span><br><span class="line"><span class="keyword">FROM</span> ucommerce_category</span><br><span class="line"><span class="keyword">WHERE</span> productcatalogid = @parentCatalog</span><br><span class="line"></span><br><span class="line"><span class="comment">-- create products</span></span><br><span class="line"><span class="keyword">IF</span> OBJECT_ID(<span class="string">'tempdb..#Products'</span>) <span class="keyword">IS</span> <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DROP</span> <span class="keyword">TABLE</span> #Products</span><br><span class="line"></span><br><span class="line"><span class="keyword">SELECT</span> productid</span><br><span class="line"><span class="keyword">INTO</span> #Products</span><br><span class="line"><span class="keyword">FROM</span> uCommerce_Product</span><br><span class="line"><span class="keyword">WHERE</span> parentproductid <span class="keyword">IS</span> <span class="literal">NULL</span> <span class="keyword">AND</span> variantsku <span class="keyword">IS</span> <span class="literal">NULL</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">DECLARE</span> @<span class="keyword">Id</span> <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @newProductId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @categoryId <span class="built_in">int</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">WHILE</span> <span class="keyword">EXISTS</span>(<span class="keyword">SELECT</span> * <span class="keyword">FROM</span> #Products)</span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">SELECT</span> Top <span class="number">1</span> @<span class="keyword">Id</span> = productid <span class="keyword">FROM</span> #Products</span><br><span class="line"> <span class="comment">/*</span><br><span class="line"> * create product </span><br><span class="line"> * add product/category relation =&gt; [uCommerce_CategoryProductRelation]</span><br><span class="line"> =&gt; duplicate FROM existing, change id's to correct product/category id's</span><br><span class="line"> * add price =&gt; [uCommerce_PriceGroupPrice] </span><br><span class="line"> */</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">INSERT</span> <span class="keyword">INTO</span> uCommerce_Product(sku,<span class="keyword">name</span>,displayonsite,weight,productDefinitionId,</span><br><span class="line"> AllowOrdering,modifiedBy, ModifiedOn, CreatedBy, CreatedOn, Guid)</span><br><span class="line"> <span class="keyword">SELECT</span> sku + @skuSuffix,<span class="keyword">name</span>,displayonsite,weight,productdefinitionId,</span><br><span class="line"> allowordering,@createdBy, <span class="keyword">getdate</span>(),@createdBy, <span class="keyword">getdate</span>(),NEWID()</span><br><span class="line"> <span class="keyword">FROM</span> uCommerce_Product</span><br><span class="line"> <span class="keyword">WHERE</span> productid = @<span class="keyword">Id</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">SELECT</span> @newProductId = SCOPE_IDENTITY() </span><br><span class="line"></span><br><span class="line"> PRINT <span class="string">'creating properties for'</span> + <span class="keyword">cast</span>(@newProductId <span class="keyword">as</span> <span class="built_in">varchar</span>(<span class="number">5</span>))</span><br><span class="line"> <span class="comment">--create product properties</span></span><br><span class="line"> <span class="keyword">INSERT</span> <span class="keyword">INTO</span> uCommerce_ProductProperty(<span class="keyword">value</span>,ProductDefinitionFieldId,ProductId)</span><br><span class="line"> <span class="keyword">SELECT</span> <span class="keyword">value</span>, productdefinitionfieldid, @newProductId</span><br><span class="line"> <span class="keyword">FROM</span> uCommerce_ProductProperty</span><br><span class="line"> <span class="keyword">WHERE</span> productid = @<span class="keyword">Id</span></span><br><span class="line"></span><br><span class="line"> PRINT <span class="string">'creating descriptions for'</span> + <span class="keyword">cast</span>(@newProductId <span class="keyword">as</span> <span class="built_in">varchar</span>(<span class="number">5</span>))</span><br><span class="line"> <span class="comment">--create product descriptions</span></span><br><span class="line"> <span class="keyword">INSERT</span> <span class="keyword">INTO</span> uCommerce_ProductDescription(productid,DisplayName,shortdescription,</span><br><span class="line"> LongDescription,CultureCode)</span><br><span class="line"> <span class="keyword">SELECT</span> @newProductId,displayname,shortdescription,LongDescription,CultureCode</span><br><span class="line"> <span class="keyword">FROM</span> uCommerce_ProductDescription</span><br><span class="line"> <span class="keyword">WHERE</span> productid = @<span class="keyword">id</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">SELECT</span> @categoryId = u2.categoryid </span><br><span class="line"> <span class="keyword">FROM</span> uCommerce_category u1</span><br><span class="line"> <span class="keyword">INNER</span> <span class="keyword">JOIN</span> uCommerce_category u2 <span class="keyword">on</span> u1.<span class="keyword">name</span> = u2.<span class="keyword">name</span> </span><br><span class="line"> <span class="keyword">INNER</span> <span class="keyword">JOIN</span> uCommerce_CategoryProductRelation cpr</span><br><span class="line"> <span class="keyword">on</span> u1.categoryId = cpr.CategoryId</span><br><span class="line"> <span class="keyword">WHERE</span> cpr.ProductId = @<span class="keyword">Id</span> </span><br><span class="line"> <span class="keyword">AND</span> u2.definitionId = @ProjectCategoryId </span><br><span class="line"> <span class="keyword">AND</span> u2.productcatalogid = @productCatalogId</span><br><span class="line"></span><br><span class="line"> PRINT <span class="string">'creating product/category relations for'</span> + <span class="keyword">cast</span>(@newProductId <span class="keyword">as</span> <span class="built_in">varchar</span>(<span class="number">5</span>))</span><br><span class="line"> <span class="comment">--create category/product relation</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_CategoryProductRelation(ProductId,CategoryId,SortOrder)</span><br><span class="line"> <span class="keyword">VALUES</span> (@newProductId,@categoryId,<span class="number">0</span>)</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"> PRINT <span class="string">'adding prices for'</span> + <span class="keyword">cast</span>(@newProductId <span class="keyword">as</span> <span class="built_in">varchar</span>(<span class="number">5</span>))</span><br><span class="line"> <span class="comment">--add price</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_PriceGroupPrice(productId,Price,DiscountPrice,PriceGroupId)</span><br><span class="line"> <span class="keyword">SELECT</span> @newProductId, price, discountprice, @pricegroupId</span><br><span class="line"> <span class="keyword">FROM</span> uCommerce_PriceGroupPrice</span><br><span class="line"> <span class="keyword">WHERE</span> ProductId = @<span class="keyword">Id</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">--add product variants and prices</span></span><br><span class="line"> <span class="keyword">IF</span> OBJECT_ID(<span class="string">'tempdb..#Productvariants'</span>) <span class="keyword">IS</span> <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DROP</span> <span class="keyword">TABLE</span> #Productvariants</span><br><span class="line"> <span class="keyword">SELECT</span> productid</span><br><span class="line"> <span class="keyword">INTO</span> #Productvariants</span><br><span class="line"> <span class="keyword">FROM</span> uCommerce_Product</span><br><span class="line"> <span class="keyword">WHERE</span> parentproductid = @<span class="keyword">Id</span> </span><br><span class="line"> <span class="keyword">AND</span> variantsku <span class="keyword">IS</span> <span class="keyword">NOT</span> <span class="literal">NULL</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">DECLARE</span> @variantId <span class="built_in">int</span></span><br><span class="line"> <span class="keyword">DECLARE</span> @newVariantId <span class="built_in">int</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">WHILE</span> <span class="keyword">EXISTS</span>(<span class="keyword">SELECT</span> * <span class="keyword">FROM</span> #Productvariants)</span><br><span class="line"> <span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">SELECT</span> Top <span class="number">1</span> @variantId = productid </span><br><span class="line"> <span class="keyword">FROM</span> #Productvariants</span><br><span class="line"></span><br><span class="line"> <span class="keyword">INSERT</span> <span class="keyword">INTO</span> uCommerce_Product(sku,variantsku,ParentProductId,<span class="keyword">name</span>,displayonsite,weight,</span><br><span class="line"> productDefinitionId,AllowOrdering,modifiedBy, ModifiedOn, CreatedBy, CreatedOn, Guid)</span><br><span class="line"> <span class="keyword">SELECT</span> sku+ @skuSuffix ,variantsku + @skuSuffix,@newProductId,<span class="keyword">name</span>,displayonsite,weight,</span><br><span class="line"> productdefinitionId,allowordering,@createdBy, <span class="keyword">getdate</span>(),@createdBy, <span class="keyword">getdate</span>(),NEWID()</span><br><span class="line"> <span class="keyword">FROM</span> uCommerce_Product</span><br><span class="line"> <span class="keyword">WHERE</span> productid = @variantId</span><br><span class="line"></span><br><span class="line"> <span class="keyword">SELECT</span> @newVariantId = SCOPE_IDENTITY()</span><br><span class="line"> </span><br><span class="line"> <span class="comment">--create product variant properties</span></span><br><span class="line"> <span class="keyword">INSERT</span> <span class="keyword">INTO</span> uCommerce_ProductProperty(<span class="keyword">value</span>,ProductDefinitionFieldId,ProductId)</span><br><span class="line"> <span class="keyword">SELECT</span> <span class="keyword">value</span>, productdefinitionfieldid, @newVariantId</span><br><span class="line"> <span class="keyword">FROM</span> uCommerce_ProductProperty</span><br><span class="line"> <span class="keyword">WHERE</span> productid = @variantId</span><br><span class="line"></span><br><span class="line"> <span class="comment">--create product descriptions </span></span><br><span class="line"> <span class="comment">--INSERT INTO uCommerce_ProductDescription(productid,DisplayName,shortdescription,</span></span><br><span class="line"> LongDescription,CultureCode)</span><br><span class="line"> <span class="comment">--SELECT @newProductId,displayname,shortdescription,LongDescription,CultureCode</span></span><br><span class="line"> <span class="comment">--FROM uCommerce_ProductDescription</span></span><br><span class="line"> <span class="comment">--WHERE productid = @variantId</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">--add variant price</span></span><br><span class="line"> <span class="keyword">INSERT</span> uCommerce_PriceGroupPrice(productId,Price,DiscountPrice,PriceGroupId)</span><br><span class="line"> <span class="keyword">SELECT</span> @newVariantId, price, discountprice, @pricegroupId</span><br><span class="line"> <span class="keyword">FROM</span> uCommerce_PriceGroupPrice</span><br><span class="line"> <span class="keyword">WHERE</span> ProductId = @variantId</span><br><span class="line"></span><br><span class="line"> <span class="keyword">Delete</span> #Productvariants <span class="keyword">WHERE</span> productid = @variantId</span><br><span class="line"> <span class="keyword">END</span></span><br><span class="line"> <span class="comment">--end product variants and prices</span></span><br><span class="line"> <span class="keyword">Delete</span> #Products <span class="keyword">WHERE</span> productid = @<span class="keyword">Id</span></span><br><span class="line"><span class="keyword">END</span> </span><br><span class="line"><span class="keyword">END</span></span><br></pre></td></tr></table></figure><p>At first it seemed that we didn’t need duplicate product definitions since they would be identical. As it tends to happen in IT… things change. So here’s a script that will do just that. Since the relations between the definitions and the field values will probably change, I did not duplicate them. Here’s a list of what the script duplicates: * ProductDefinition * ProductDefinitionField</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- fields and inheritance should be set manually</span></span><br><span class="line"><span class="comment">-- add ProductDefinitions</span></span><br><span class="line">IF OBJECT_ID('tempdb..#ProductDefinitions') IS NOT NULL <span class="keyword">DROP</span> <span class="keyword">TABLE</span> #ProductDefinitions</span><br><span class="line"><span class="keyword">SELECT</span> productdefinitionid,<span class="keyword">name</span>,deleted</span><br><span class="line"><span class="keyword">INTO</span> #ProductDefinitions</span><br><span class="line"><span class="keyword">FROM</span> uCommerce_ProductDefinition</span><br><span class="line"></span><br><span class="line"><span class="keyword">DECLARE</span> @<span class="keyword">name</span> <span class="keyword">nvarchar</span>(<span class="number">512</span>)</span><br><span class="line"><span class="keyword">DECLARE</span> @deleted <span class="built_in">bit</span></span><br><span class="line"><span class="keyword">DECLARE</span> @newDefinitionId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @productdefinitionId <span class="built_in">int</span></span><br><span class="line"><span class="keyword">DECLARE</span> @skuSuffix <span class="keyword">nvarchar</span>(<span class="number">50</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">WHILE</span> <span class="keyword">EXISTS</span>(<span class="keyword">SELECT</span> * <span class="keyword">FROM</span> #ProductDefinitions)</span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line"> <span class="keyword">SELECT</span> Top <span class="number">1</span> @productdefinitionId = productdefinitionId, </span><br><span class="line"> @<span class="keyword">name</span> = <span class="keyword">name</span>, @deleted = deleted </span><br><span class="line"> <span class="keyword">FROM</span> #ProductDefinitions</span><br><span class="line"></span><br><span class="line"> <span class="keyword">INSERT</span> <span class="keyword">INTO</span> uCommerce_ProductDefinition(<span class="keyword">name</span>,deleted,guid)</span><br><span class="line"> <span class="keyword">SELECT</span> <span class="keyword">name</span> + @skuSuffix, @deleted, NEWID()</span><br><span class="line"> <span class="keyword">FROM</span> uCommerce_ProductDefinition</span><br><span class="line"> <span class="keyword">WHERE</span> productdefinitionId = @productdefinitionId</span><br><span class="line"></span><br><span class="line"> <span class="keyword">SELECT</span> @newDefinitionId = SCOPE_IDENTITY()</span><br><span class="line"> </span><br><span class="line"> <span class="comment">--create product definition fields</span></span><br><span class="line"> <span class="keyword">INSERT</span> <span class="keyword">INTO</span> uCommerce_ProductDefinitionField</span><br><span class="line"> <span class="keyword">SELECT</span> DataTypeId,@newDefinitionId,<span class="keyword">Name</span>,DisplayOnSite,IsVariantProperty,Multilingual</span><br><span class="line"> ,RenderInEditor,Searchable,Deleted,SortOrder,Facet,NEWID()</span><br><span class="line"> <span class="keyword">FROM</span> uCommerce_ProductDefinitionField</span><br><span class="line"> <span class="keyword">WHERE</span> productdefinitionid = @productdefinitionId</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"> <span class="keyword">Delete</span> #ProductDefinitions <span class="keyword">WHERE</span> productdefinitionid = @productdefinitionid</span><br><span class="line"><span class="keyword">END</span></span><br></pre></td></tr></table></figure><p>And that’s the end of this chapter. The presented code here may not be a silver bullet but I hope it’s at least a machete clearing a path for you.</p><!-- rebuild by neat -->]]></content>
<summary type="html">
how to duplicate a uCommerce store to get a running start with the new one
</summary>
<category term="ucommerce" scheme="http://www.sitecorn.be/tags/ucommerce/"/>
<category term="sql" scheme="http://www.sitecorn.be/tags/sql/"/>
</entry>
<entry>
<title>tools and plugins</title>
<link href="http://www.sitecorn.be/2016/07/08/tools-plugins/"/>
<id>http://www.sitecorn.be/2016/07/08/tools-plugins/</id>
<published>2016-07-08T13:41:24.449Z</published>
<updated>2016-09-08T15:39:01.427Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>As a developer I find myself gathering tools, plugins, links and so on. If it looks useful I’ll install it and give it a go. A lot of these don’t make through the first week and some aren’t even installed more than a day. So I tend to make lists of the useful ones in case I need to install a new dev environment. I’ll skip the usual ones like you favourite DLL decompiler, log parser and performance tools as there are enough lists out there for them.</p><h3 id="browser-goodies">Browser goodies</h3><p>The last couple of years I’m using chrome as my primary browser, so all these plugins are for my primary browser.</p><p><strong>Edit this cookie</strong></p><p>This one allows you to change the contents of a cookie. Great for testing. Quick and easy.</p><p><a href="https://chrome.google.com/webstore/detail/editthiscookie/fngmhnnpilhplaeedifhccceomclgfbg?utm_source=chrome-app-launcher-info-dialog" target="_blank" rel="external">link</a></p><p><strong>Ip addres and domain information</strong> Say my site is running in different regions spread across the globe and something is wrong. Which server am I currently viewing? this plugin displays the IP address and geographical location of the server.</p><p><a href="https://chrome.google.com/webstore/detail/ip-address-and-domain-inf/lhgkegeccnckoiliokondpaaalbhafoa?utm_source=chrome-app-launcher-info-dialog" target="_blank" rel="external">link</a></p><p><strong>Markdown preview plus</strong></p><p>I was looking for an easy way to view my mardown documentation files, without having to compile them. Enter Markdown preview plus, it lets you view markdown documents as HTML</p><p><a href="https://chrome.google.com/webstore/detail/markdown-preview-plus/febilkbfcbhebfnokafefeacimjdckgl?utm_source=chrome-app-launcher-info-dialog" target="_blank" rel="external">link</a></p><p><strong>Sonar / Yslow</strong></p><p>Is your site slow? Do you like awake at night wondering where it all went wrong? These plugins will shed some light on why the page is slow(er)</p><p><a href="https://chrome.google.com/webstore/detail/sonar/dibilcjfahbokhiodajibcajcabfjein?utm_source=chrome-app-launcher-info-dialog%20https://chrome.google.com/webstore/detail/yslow/ninejjcohidippngpapiilnmkgllmakh?utm_source=chrome-app-launcher-info-dialog" target="_blank" rel="external">link</a></p><p><strong>HOLA</strong></p><p>Want to see what that international site look like to a foreign visitor? Use this plugin to switch your location so you can test the site from another country</p><p><a href="https://chrome.google.com/webstore/detail/unlimited-free-vpn-hola/gkojfkhlekighikafcpjkiklfbnlmeio?utm_source=chrome-app-launcher-info-dialog" target="_blank" rel="external">link</a></p><h3 id="visual-studio-extensions">Visual studio extensions</h3><p>We all know about Resharper, StyleCop and other great extensions. So here are few you might not know about. The first one allows you to change what is shown in the title bar. this is very useful in case you have multiple banches in TFS. and you have opened several VS’s. This plugin helps you by letting you define how many parent folders are shown in the title bar. That way the branch name can become visible.</p><p>To change the settings go to tools > options > rename VS Window Title</p><div class="figure"><img src="/images/TitleOptions.png" title="Custom VS title" alt="Custom VS title"><p class="caption">Custom VS title</p></div><p>The second extension (VS 2013 version) allow you to add lists of project links. Again I use this to have links to all the branches of my current working project on my start page. No screen shot here, as I don’t want to create all those dummy solutions. just check out the link it has all the info you need.</p><p>The final one allows you to edit and preview markdown documents. Perfect for quick documentation.</p><ul><li><a href="https://visualstudiogallery.msdn.microsoft.com/de5a8b10-d521-43ba-8af4-938c19b10ec9" target="_blank" rel="external">RenameVSWindowTitle</a></li><li><a href="https://visualstudiogallery.msdn.microsoft.com/f3f23845-5b1e-4811-882f-60b7181fa6d6" target="_blank" rel="external">Custom Start page</a></li><li><a href="https://visualstudiogallery.msdn.microsoft.com/0855e23e-4c4c-4c82-8b39-24ab5c5a7f79" target="_blank" rel="external">Markdown Mode</a></li></ul><!-- rebuild by neat -->]]></content>
<summary type="html">
some tools and plugins to make a dev's life a bit easier
</summary>
<category term="tools" scheme="http://www.sitecorn.be/tags/tools/"/>
<category term="browser extensions" scheme="http://www.sitecorn.be/tags/browser-extensions/"/>
<category term="plugins" scheme="http://www.sitecorn.be/tags/plugins/"/>
</entry>
<entry>
<title>UCommerce Extensions</title>
<link href="http://www.sitecorn.be/2016/07/08/ucommerce-extensions/"/>
<id>http://www.sitecorn.be/2016/07/08/ucommerce-extensions/</id>
<published>2016-07-08T12:17:50.462Z</published>
<updated>2016-09-08T15:06:00.221Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>Over the course of my first Sitecore 8 and UCommerce integration project I’ve created some extension methods that might be useful in other projects. Most of these are straight forward so let’s dive into it.</p><h3 id="basket">Basket</h3><p><strong>the culture difference</strong></p><p>In case you have different stores for different you need to keep your baskets separated. You cannot have a basket with product X with Euro as currency and product Y with Dollars as currency. So what we decided to do is delete the existing basket when the visitor browses a different Country website. Our site had a country/language selector which allowed the visitor to do that.</p><p>The following code does just that. It checks if the basket culture corresponds with the SiteContext culture.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">EnsureBasketCulture</span>(<span class="params"><span class="keyword">this</span> Basket basket</span>)</span><br><span class="line"></span>{</span><br><span class="line"> <span class="keyword">if</span> (!basket.PurchaseOrder.CultureCode.Equals(SiteContext.Current.CurrentCulture.Name))</span><br><span class="line"> { </span><br><span class="line"> SiteContext.Current.OrderContext.ClearBasketInformation();</span><br><span class="line"> basket = SiteContext.Current.OrderContext.GetBasket();</span><br><span class="line"> basket.PurchaseOrder.Save();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Now in case you may not want to loose any basket data, so we want to save that. The following code adds a summary of the existing basket in an audit trail in the new one. Now you might be thinking you want to add the order lines to the new basket and you can do that. However it was out of scope for our project and it could lead you down the rabbit hole since you would have to check if the product is sold in the new country, the prices might be different between countries, not to mention taxes and so on.</p><p>This code is just example and you might want to be more defensive in your coding, it’s merely for reference.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">EnsureBasketCulture</span>(<span class="params"><span class="keyword">this</span> Basket basket</span>)</span><br><span class="line"></span>{</span><br><span class="line"> <span class="keyword">if</span> (!basket.PurchaseOrder.CultureCode.Equals(SiteContext.Current.CurrentCulture.Name))</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">string</span> summary = <span class="keyword">string</span>.Empty;</span><br><span class="line"> <span class="keyword">if</span> (basket.PurchaseOrder != <span class="keyword">null</span> && basket.PurchaseOrder.OrderLines.Any())</span><br><span class="line"> {</span><br><span class="line"> summary = <span class="keyword">string</span>.Join(<span class="string">" | "</span>, basket.PurchaseOrder.OrderLines.Select(</span><br><span class="line"> l => <span class="keyword">string</span>.Format(<span class="string">"{0} - #{1}"</span>, l.ProductName, l.Quantity)));</span><br><span class="line"> }</span><br><span class="line"> SiteContext.Current.OrderContext.ClearBasketInformation();</span><br><span class="line"> basket = SiteContext.Current.OrderContext.GetBasket();</span><br><span class="line"> basket.PurchaseOrder.Save();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> auditline = <span class="keyword">new</span> OrderStatusAudit();</span><br><span class="line"> <span class="keyword">var</span> order = basket.PurchaseOrder;</span><br><span class="line"> auditline.CreatedOn = DateTime.Now;</span><br><span class="line"> auditline.Message = <span class="keyword">string</span>.Format(<span class="string">"Country changed, new basket created: {0}"</span>, summary);</span><br><span class="line"> auditline.PurchaseOrder = order;</span><br><span class="line"> auditline.NewOrderStatus = basket.PurchaseOrder.OrderStatus; </span><br><span class="line"> auditline.Save();</span><br><span class="line"> order.AddOrderStatusAudit(auditline);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="payment-method">Payment method</h3><p><strong>the delivery date modification</strong></p><p>In the Adyen payment method properties you can set standard shipping time. To be able to show the estimated delivery date of the order, we added the following extension method. It simply retrieves the properties from the payment method and corrects the date (adding only business days).</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> DateTime <span class="title">GetDateAdjustment</span>(<span class="params">PaymentMethod paymentMethod</span>)</span><br><span class="line"></span>{</span><br><span class="line"> AdyenPaymentMethodProperties properties = <span class="keyword">new</span> AdyenPaymentMethodProperties(paymentMethod.PaymentMethodProperties);</span><br><span class="line"> <span class="keyword">string</span> shipDays = properties.ShipDays;</span><br><span class="line"> <span class="keyword">string</span> shipHours = properties.ShipHours;</span><br><span class="line"> <span class="keyword">string</span> shipMinutes = properties.ShipMinutes;</span><br><span class="line"></span><br><span class="line"> DateTime shipBefore = DateTime.Now;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">string</span>.IsNullOrEmpty(shipDays))</span><br><span class="line"> {</span><br><span class="line"> shipBefore = shipBefore.AddBusinessDays(<span class="keyword">int</span>.Parse(shipDays));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">string</span>.IsNullOrEmpty(shipHours))</span><br><span class="line"> {</span><br><span class="line"> shipBefore = shipBefore.AddHours(<span class="keyword">int</span>.Parse(shipHours));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">string</span>.IsNullOrEmpty(shipMinutes))</span><br><span class="line"> {</span><br><span class="line"> shipBefore = shipBefore.AddMinutes(<span class="keyword">int</span>.Parse(shipMinutes));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> shipBefore; </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>the property enquiry</strong></p><p>The following extension method avoids duplicating the same code each time you need to access a payment method property. I also saves a lot of time trying to figure out how to do that again.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">string</span> <span class="title">GetPaymentMethodPropertiesValue</span>(<span class="params"><span class="keyword">this</span> ICollection<PaymentMethodProperty> properties, <span class="keyword">string</span> key</span>)</span><br><span class="line"></span>{</span><br><span class="line"> <span class="keyword">return</span> properties.FirstOrDefault(p => p.DefinitionField != <span class="keyword">null</span> && p.DefinitionField.Name.Equals(key)).Value;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="puchaseorder">PuchaseOrder</h3><p><strong>the American way</strong> As we had quite a lot of divergent logic for the US, I added this extension method that inspects the culture to find out if the order is in place in/for the US.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">bool</span> <span class="title">IsAmerican</span>(<span class="params"><span class="keyword">this</span> PurchaseOrder order</span>)</span><br><span class="line"></span>{</span><br><span class="line"> <span class="keyword">return</span> order.CultureCode.Equals(<span class="string">"en-US"</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>the pipeline verification</strong></p><p>Sometimes something happens, some times it’s bad. let’s leave it at that. I needed to check if the Checkout pipeline was executed or not, so here’s the code.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">bool</span> <span class="title">CheckoutPipelineHasAlreadyBeenExecutedForPayment</span>(<span class="params"><span class="keyword">this</span> PurchaseOrder order</span>)</span><br><span class="line"></span>{</span><br><span class="line"> <span class="keyword">if</span> (order.OrderStatus.OrderStatusId == (<span class="keyword">int</span>)OrderStatusCode.Basket ||</span><br><span class="line"> order.OrderStatus.OrderStatusId == (<span class="keyword">int</span>)OrderStatusCode.Processing)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>the order number assignment</strong></p><p>In case you want to assign an order number at some random point in the order process, this extension method will let you do that. We used it to assign the order number when the customer reaches the confirmation page and the payment was authorised.</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">public static void AssignOrdernumberIfEmpty(this PurchaseOrder order,string source = "PurchaseOrderExtension")</span><br><span class="line">{</span><br><span class="line"> if (string.IsNullOrEmpty(order.OrderNumber))</span><br><span class="line"> { </span><br><span class="line"> try</span><br><span class="line"> {</span><br><span class="line"> var numberSeriesService = ObjectFactory.Instance.Resolve<INumberSeriesService>();</span><br><span class="line"> order.OrderNumber =</span><br><span class="line"> numberSeriesService.GetNumber(order.ProductCatalogGroup.OrderNumberSerie.OrderNumberName);</span><br><span class="line"> Log.Info(string.Format("Assigning order number to order. id:</span><br><span class="line"> {0}, number {1}", order.OrderId, order.OrderNumber),source);</span><br><span class="line"> order.Save();</span><br><span class="line"> }</span><br><span class="line"> catch (Exception ex)</span><br><span class="line"> {</span><br><span class="line"> Log.Error(string.Format("An error occured assingning the order ordernumber to order (ID): {0}"</span><br><span class="line"> ,order.OrderId) ,ex);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="custom-model">Custom Model</h3><p><strong>the currency format issue</strong></p><p>The UCommerce version we were using 6.x had a fixed currency format. So I wrote this class so I could make my own money. You can provide a currency format to the ToString method or use the default one. In our project we only displayed decimals when they’re not zero.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">MyMoney</span> : <span class="title">Money</span></span><br><span class="line">{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">MyMoney</span>(<span class="params"><span class="keyword">decimal</span> <span class="keyword">value</span>, CultureInfo culture, Currency currency</span>) </span><br><span class="line"> : <span class="title">base</span>(<span class="params"><span class="keyword">value</span>, culture, currency</span>)</span><br><span class="line"> </span>{</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">MyMoney</span>(<span class="params"><span class="keyword">decimal</span> <span class="keyword">value</span>, Currency currency</span>) : <span class="title">base</span>(<span class="params"><span class="keyword">value</span>, currency</span>)</span><br><span class="line"> </span>{</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="title">MyMoney</span>(<span class="params">Money money</span>) : <span class="title">base</span>(<span class="params">money.Value, money.Culture, money.Currency</span>)</span><br><span class="line"> </span>{</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//uCommerce ToString method has a fixed currency format</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">string</span> <span class="title">ToString</span>(<span class="params"><span class="keyword">string</span> format</span>)</span><br><span class="line"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (format.IsNullOrEmpty())</span><br><span class="line"> {</span><br><span class="line"> format = <span class="string">"C0"</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">string</span> cultureSpecificStringValue = Value.ToString(format, Culture);</span><br><span class="line"> <span class="keyword">return</span> cultureSpecificStringValue;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">//should return the value with 2 decimals if it is not a whole number</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">string</span> <span class="title">ToString</span>(<span class="params"></span>)</span><br><span class="line"> </span>{</span><br><span class="line"> <span class="keyword">string</span> format = <span class="string">"C0"</span>;</span><br><span class="line"> <span class="keyword">if</span> (Value - Math.Truncate(Value) > <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> format = <span class="string">"c2"</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ToString(format);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>the money maker</strong></p><p>Here’s how you would use that. Let’s say you’re displaying the cost of a product in an orderline. Since the ultimate goal of e-commerce it to turn the product value into cash, we can do that in code. Let’s convert the product cost to MyMoney.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">string</span> displayValue = <span class="keyword">new</span> MyMoney(orderline.Total.GetValueOrDefault(), </span><br><span class="line">orderline.PurchaseOrder.BillingCurrency).ToString();</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
<summary type="html">
UCommerce extensions: dealing with multiple stores, culture difference and making money
</summary>
<category term="ucommerce" scheme="http://www.sitecorn.be/tags/ucommerce/"/>
<category term="sitecore 8" scheme="http://www.sitecorn.be/tags/sitecore-8/"/>
<category term="extension methods" scheme="http://www.sitecorn.be/tags/extension-methods/"/>
</entry>
<entry>
<title>Shortcut of the day - Peek Definition</title>
<link href="http://www.sitecorn.be/2016/06/03/sotd/shortcutoftheday/"/>
<id>http://www.sitecorn.be/2016/06/03/sotd/shortcutoftheday/</id>
<published>2016-06-03T07:41:16.831Z</published>
<updated>2016-09-08T15:37:11.014Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>I intend to dive deeper into all the wonderful shortcuts VS, Resharper and other plugins have to offer. But since they are covered on lots of other site I will only include a short description in my posts. They are mostly intended to help me remember.</p><p>[CTRL] + [SHIFT] + [LEFT-CLICK]</p><p>Does exactly what it says on the box. Where [CTRL] + [LEFT-CLICK] opens a new tab and navigates to the definition of the method or class, this will open a small pop up window and show the definition “inline”.</p><p>Check it out <a href="https://blog.jetbrains.com/dotnet/2013/11/04/visual-studio-2013-support-resharper-81/" target="_blank" rel="external">here</a></p><!-- rebuild by neat -->]]></content>
<summary type="html">
resharper goodies - avoid jumping between files when viewing definitions
</summary>
<category term="visual studio" scheme="http://www.sitecorn.be/tags/visual-studio/"/>
<category term="resharper" scheme="http://www.sitecorn.be/tags/resharper/"/>
<category term="shortcut" scheme="http://www.sitecorn.be/tags/shortcut/"/>
</entry>
<entry>
<title>SQL cheatsheet: snippets and reference material</title>
<link href="http://www.sitecorn.be/2016/05/18/sql-cheatsheet/"/>
<id>http://www.sitecorn.be/2016/05/18/sql-cheatsheet/</id>
<published>2016-05-18T14:44:00.443Z</published>
<updated>2016-09-08T15:39:52.831Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>Here are a few of the SQL statements I keep googling for. I thought it would be helpful to keep the in one place, so I’ll have a cheatsheet next time.</p><p><strong>Get a list of all tables in the database</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">FROM</span> <span class="keyword">sys</span>.<span class="keyword">Tables</span></span><br><span class="line"><span class="comment">--OR</span></span><br><span class="line">EXEC sp_tables <span class="string">'%'</span>, <span class="string">'%'</span>, <span class="string">'master'</span>, <span class="string">"'TABLE'"</span></span><br></pre></td></tr></table></figure><p><strong>Get a list of all tables, views and system tables in the database</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">EXEC sp_tables '%'</span><br></pre></td></tr></table></figure><p><strong>Get a list of tables that the view depends on</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> view_name, Table_Name</span><br><span class="line"><span class="keyword">FROM</span> INFORMATION_SCHEMA.VIEW_TABLE_USAGE</span><br><span class="line"><span class="keyword">WHERE</span> View_Name = <span class="string">'&lt;giveViewName&gt;'</span></span><br><span class="line"><span class="keyword">ORDER</span> <span class="keyword">BY</span> view_name, table_name</span><br></pre></td></tr></table></figure><p><strong>Get a list of all views that depend on a given table</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> view_name, Table_Name</span><br><span class="line"><span class="keyword">FROM</span> INFORMATION_SCHEMA.VIEW_TABLE_USAGE</span><br><span class="line"><span class="keyword">WHERE</span> Table_Name= <span class="string">'Address'</span></span><br><span class="line"><span class="keyword">ORDER</span> <span class="keyword">BY</span> view_name, table_name</span><br></pre></td></tr></table></figure><p><strong>Get al list of all functions</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> ROUTINE_NAME</span><br><span class="line"><span class="keyword">FROM</span> INFORMATION_SCHEMA.ROUTINES</span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">upper</span>(ROUTINE_TYPE) = <span class="string">'FUNCTION'</span></span><br></pre></td></tr></table></figure><p></p><p><strong>Get information about all fields in a certain table</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> column_name, data_type, is_nullable, character_maximum_length</span><br><span class="line"><span class="keyword">FROM</span> information_schema.<span class="keyword">columns</span></span><br><span class="line"><span class="keyword">WHERE</span> table_name=<span class="string">'contents'</span>;</span><br></pre></td></tr></table></figure><p><strong>Get a list of tables with their create and modified dates</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="keyword">name</span>, object_id, create_date, modify_date</span><br><span class="line"><span class="keyword">FROM</span> <span class="keyword">sys</span>.<span class="keyword">tables</span>;</span><br></pre></td></tr></table></figure><p><strong>Get a list of constraints and the fields they apply to for a given table.</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> a.table_name, a.constraint_name, b.column_name, a.constraint_type</span><br><span class="line"><span class="keyword">FROM</span> information_schema.table_constraints a, information_schema.key_column_usage b</span><br><span class="line"><span class="keyword">WHERE</span> a.table_name = <span class="string">'contents'</span></span><br><span class="line"><span class="keyword">AND</span> a.table_name = b.table_name</span><br><span class="line"><span class="keyword">AND</span> a.table_schema = b.table_schema</span><br><span class="line"><span class="keyword">AND</span> a.constraint_name = b.constraint_name;</span><br></pre></td></tr></table></figure><p><strong>Example of how to generate a script for all tables</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="string">'SELECT count(1) FROM <a class="incipient" title="[click to create page]"'</span> + </span><br><span class="line"> <span class="string">' href="https://somelink/%27%20+%20table_name%20+%20%27">'</span> + table_name + <span class="string">'</a>;'</span></span><br><span class="line"><span class="keyword">FROM</span> information_schema.<span class="keyword">tables</span>;</span><br></pre></td></tr></table></figure><p><strong>Get the definition (code) of a user defined stored procedure</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> routine_definition <span class="keyword">FROM</span> INFORMATION_SCHEMA.ROUTINES</span><br><span class="line"><span class="keyword">WHERE</span> specific_name = ‘USP_NAME<span class="string">'</span></span><br></pre></td></tr></table></figure><p><strong>Retrieve the collation of a column</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span></span><br><span class="line"><span class="keyword">col</span>.<span class="keyword">name</span>, <span class="keyword">col</span>.collation_name</span><br><span class="line"><span class="keyword">FROM</span> <span class="keyword">sys</span>.<span class="keyword">columns</span> <span class="keyword">col</span></span><br><span class="line"><span class="keyword">WHERE</span> object_id = OBJECT_ID(<span class="string">'TableName'</span>)</span><br></pre></td></tr></table></figure><p><strong>Solve collation issues in a join, union, …</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"> <span class="keyword">ALTER</span> <span class="keyword">TABLE</span> tablename <span class="keyword">ALTER</span> <span class="keyword">COLUMN</span> <span class="keyword">id</span></span><br><span class="line"><span class="keyword">COLLATE</span> Latin1_General_CI_AS <span class="keyword">NOT</span> <span class="literal">NULL</span></span><br></pre></td></tr></table></figure><p><strong>Retrieve FK en PK information</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sp_help ‘TABLENAME’</span><br></pre></td></tr></table></figure><p><strong>Check whick document types can be searched with a full text search.</strong></p><p>uncomment the “WHERE” part to check for a specific document type (in this case pdf) </p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> document_type, <span class="keyword">path</span> </span><br><span class="line"><span class="keyword">FROM</span> <span class="keyword">sys</span>.fulltext_document_types </span><br><span class="line"><span class="comment">---WHERE document_type = '.pdf'</span></span><br></pre></td></tr></table></figure><p></p><p><strong>Another way of finding references between tables</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> s1.<span class="keyword">name</span> <span class="keyword">as</span> FROM_schema</span><br><span class="line">, o1.<span class="keyword">Name</span> <span class="keyword">as</span> FROM_table</span><br><span class="line">, s2.<span class="keyword">name</span> <span class="keyword">as</span> to_schema</span><br><span class="line">, o2.<span class="keyword">Name</span> <span class="keyword">as</span> to_table</span><br><span class="line"><span class="keyword">FROM</span> <span class="keyword">sys</span>.foreign_keys fk</span><br><span class="line"><span class="keyword">INNER</span> <span class="keyword">JOIN</span> <span class="keyword">sys</span>.objects o1</span><br><span class="line"><span class="keyword">ON</span> fk.parent_object_id = o1.object_id</span><br><span class="line"><span class="keyword">INNER</span> <span class="keyword">JOIN</span> <span class="keyword">sys</span>.schemas s1</span><br><span class="line"><span class="keyword">ON</span> o1.schema_id = s1.schema_id</span><br><span class="line"><span class="keyword">INNER</span> <span class="keyword">JOIN</span> <span class="keyword">sys</span>.objects o2</span><br><span class="line"><span class="keyword">ON</span> fk.referenced_object_id = o2.object_id</span><br><span class="line"><span class="keyword">INNER</span> <span class="keyword">JOIN</span> <span class="keyword">sys</span>.schemas s2</span><br><span class="line"><span class="keyword">ON</span> o2.schema_id = s2.schema_id</span><br><span class="line"><span class="comment">--For the purposes of finding dependency hierarchy</span></span><br><span class="line"><span class="comment">-- we're not worried about self-referencing tables</span></span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">NOT</span>(s1.<span class="keyword">name</span> = s2.<span class="keyword">name</span> <span class="keyword">AND</span> o1.<span class="keyword">name</span> = o2.<span class="keyword">name</span>)</span><br></pre></td></tr></table></figure><h3 id="a-word-on-collation">A word on collation</h3><h4 id="what-is-collation">What is collation?</h4><p>Collation refers to a set of rules that determine how data is sorted and compared. Character data is sorted using rules that define the correct character sequence, with options for specifying case-sensitivity, accent marks, kana character types and character width.</p><h4 id="case-sensitivity">Case sensitivity</h4><p>If A and a, B and b, etc. are treated in the same way then it is case-insensitive. A computer treats A and a differently because it uses ASCII code to differentiate the input. The ASCII value of A is 65, while a is 97. The ASCII value of B is 66 and b is 98.</p><h4 id="accent-sensitivity">Accent sensitivity</h4><p>If a and á, o and ó are treated in the same way, then it is accent-insensitive. A computer treats a and á differently because it uses ASCII code for differentiating the input. The ASCII value of a is 97 and áis 225. The ASCII value of o is 111 and ó is 243.</p><h4 id="kana-sensitivity">Kana Sensitivity</h4><p>When Japanese kana characters Hiragana and Katakana are treated differently, it is called Kana sensitive.</p><h4 id="width-sensitivity">Width sensitivity</h4><p>When a single-byte character (half-width) and the same character when represented as a double-byte character (full-width) are treated differently then it is width sensitive. Database, Tables and columns with different collation SQL Server 2000 allows the users to create databases, tables and columns in different collations.</p><p><a href="http://www.databasejournal.com/features/mssql/article.php/3302341/SQL-Server-and-Collation.htm" target="_blank" rel="external">source</a></p><h4 id="removing-tags-from-text">Removing tags FROM text</h4><p>The following example shows a way you can remove tags FROM text. In this case only the content of a couple of tags needed to be retrieved FROM the text.</p><p>Full example and problem description can be found <a href="http://stackoverflow.com/questions/16734306/SELECTing-multiple-substrings-FROM-a-field/16774904#16774904" target="_blank" rel="external">here</a></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">declare</span> @<span class="keyword">var</span> <span class="keyword">nvarchar</span>(<span class="keyword">max</span>)</span><br><span class="line"><span class="keyword">declare</span> @tag <span class="keyword">nvarchar</span>(<span class="keyword">max</span>)</span><br><span class="line"><span class="keyword">declare</span> @label <span class="keyword">nvarchar</span>(<span class="keyword">max</span>)</span><br><span class="line"><span class="keyword">declare</span> @<span class="keyword">start</span> <span class="built_in">int</span></span><br><span class="line"><span class="keyword">declare</span> @<span class="keyword">stop</span> <span class="built_in">int</span></span><br><span class="line"><span class="keyword">declare</span> @<span class="keyword">len</span> <span class="built_in">int</span></span><br><span class="line"><span class="keyword">declare</span> @needed <span class="built_in">int</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">set</span> @<span class="keyword">var</span> = <span class="string">'<Name>Example1</Name></span><br><span class="line"><Type>String</Type></span><br><span class="line"><Nullable>False</Nullable></span><br><span class="line"><AllowBlank>False</AllowBlank></span><br><span class="line"><Prompt>Start Date (DD-MMM-YYYY)</Prompt> </span><br><span class="line"><PromptUser>True</PromptUser> </span><br><span class="line"><Parameter> </Parameter></span><br><span class="line"><Name>Example2</Name> </span><br><span class="line"><Type>String</Type> </span><br><span class="line"><Nullable>False</Nullable> </span><br><span class="line"><AllowBlank>False</AllowBlank></span><br><span class="line"><Prompt>Case (Enter Case Number, % for all, OR %AL% for Alberta)</Prompt> </span><br><span class="line"><PromptUser>True</PromptUser> </span><br><span class="line"><DefaultValues> </span><br><span class="line"><Value>%al%</Value> </span><br><span class="line"></DefaultValues> </span><br><span class="line"><Values> </span><br><span class="line"> <Value>%al%</Value> </span><br><span class="line"></Values> </span><br><span class="line"><Parameter></Parameter>'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">set</span> @needed = <span class="number">0</span></span><br><span class="line"><span class="keyword">set</span> @<span class="keyword">start</span> = <span class="keyword">charindex</span>(<span class="string">'<'</span>,@<span class="keyword">var</span>)</span><br><span class="line"><span class="keyword">set</span> @<span class="keyword">stop</span> = <span class="keyword">charindex</span>(<span class="string">'>'</span>,@<span class="keyword">var</span>)</span><br><span class="line"><span class="keyword">set</span> @<span class="keyword">len</span> = @<span class="keyword">stop</span> - @<span class="keyword">start</span> +<span class="number">1</span></span><br><span class="line"><span class="keyword">set</span> @tag = <span class="keyword">substring</span>(@<span class="keyword">var</span>,@<span class="keyword">start</span>,@<span class="keyword">len</span>)</span><br><span class="line"><span class="keyword">set</span> @label = <span class="keyword">substring</span>(@<span class="keyword">var</span>,@<span class="keyword">start</span>+<span class="number">1</span>,@<span class="keyword">len</span><span class="number">-2</span>)</span><br><span class="line"><span class="keyword">set</span> @<span class="keyword">var</span> = <span class="keyword">replace</span>(@<span class="keyword">var</span>,@tag,@label + <span class="string">' : '</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span>(@<span class="keyword">start</span> <> <span class="number">0</span>)</span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">set</span> @<span class="keyword">start</span> = <span class="keyword">charindex</span>(<span class="string">'<'</span>,@<span class="keyword">var</span>)</span><br><span class="line"> <span class="keyword">set</span> @<span class="keyword">stop</span> = <span class="keyword">charindex</span>(<span class="string">'>'</span>,@<span class="keyword">var</span>)</span><br><span class="line"> <span class="keyword">set</span> @<span class="keyword">len</span> = @<span class="keyword">stop</span> - @<span class="keyword">start</span> +<span class="number">1</span></span><br><span class="line"> <span class="keyword">if</span>(@<span class="keyword">start</span> <> <span class="number">0</span>)</span><br><span class="line"> <span class="keyword">begin</span> </span><br><span class="line"> <span class="keyword">set</span> @tag = <span class="keyword">substring</span>(@<span class="keyword">var</span>,@<span class="keyword">start</span>,@<span class="keyword">len</span>) </span><br><span class="line"> <span class="keyword">if</span>(<span class="keyword">charindex</span>(<span class="string">'/'</span>,@tag) = <span class="number">0</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">set</span> @label = <span class="keyword">substring</span>(@<span class="keyword">var</span>,@<span class="keyword">start</span>+<span class="number">1</span>,@<span class="keyword">len</span><span class="number">-2</span>)+ <span class="string">' : '</span> </span><br><span class="line"> <span class="keyword">if</span>(<span class="keyword">lower</span>(@label) <> <span class="string">'name : '</span> <span class="keyword">and</span> <span class="keyword">lower</span>(@label) <> <span class="string">'value : '</span> <span class="keyword">and</span> <span class="keyword">lower</span>(@label) <> <span class="string">'prompt : '</span>)</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">set</span> @needed = <span class="number">0</span></span><br><span class="line"> <span class="keyword">set</span> @<span class="keyword">var</span> = <span class="keyword">replace</span>(@<span class="keyword">var</span>,@tag,<span class="string">''</span>)</span><br><span class="line"> <span class="keyword">set</span> @<span class="keyword">start</span> = @<span class="keyword">stop</span> - <span class="keyword">len</span>(@tag) </span><br><span class="line"> <span class="keyword">set</span> @<span class="keyword">stop</span> = <span class="keyword">charindex</span>(<span class="string">'<'</span>,@<span class="keyword">var</span>)</span><br><span class="line"> <span class="keyword">set</span> @<span class="keyword">len</span> = @<span class="keyword">stop</span> - @<span class="keyword">start</span></span><br><span class="line"> <span class="keyword">set</span> @tag = <span class="keyword">substring</span>(@<span class="keyword">var</span>,@<span class="keyword">start</span>,@<span class="keyword">len</span>) </span><br><span class="line"> <span class="keyword">set</span> @<span class="keyword">var</span> = <span class="keyword">replace</span>(@<span class="keyword">var</span>,@tag,<span class="string">''</span>)</span><br><span class="line"> <span class="keyword">end</span> </span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> <span class="keyword">set</span> @label = <span class="string">''</span></span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">set</span> @<span class="keyword">var</span> = <span class="keyword">replace</span>(@<span class="keyword">var</span>,@tag,@label)</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">print <span class="keyword">replace</span>(@<span class="keyword">var</span>,<span class="string">'</span><br><span class="line">'</span>,<span class="string">''</span>)</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
<summary type="html">
the sql scripts I keep googling for wrapped up in one blog post
</summary>
<category term="sql" scheme="http://www.sitecorn.be/tags/sql/"/>
<category term="cheat sheet" scheme="http://www.sitecorn.be/tags/cheat-sheet/"/>
</entry>
<entry>
<title>Javascript unit testing with Qunit</title>
<link href="http://www.sitecorn.be/2016/05/18/javascript-unit-testing/"/>
<id>http://www.sitecorn.be/2016/05/18/javascript-unit-testing/</id>
<published>2016-05-18T13:58:46.896Z</published>
<updated>2016-09-08T15:43:27.919Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>Qunit is a javascript testing framework created by the jquery foundation. You can download Qunit and find some more documentation at <a href="http://qunitjs.com/" class="uri" target="_blank" rel="external">http://qunitjs.com/</a> . The site has tutorials and general unit testing info, so I won’t go into details but here is a quick recap to get started. Include qunit and your test.js in your header. Throw in the qunit CSS if you like the fancy red/green colors for your test results.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><script src=<span class="string">"resources/qunit-1.13.0.js"</span>></script></span><br><span class="line"><script src=<span class="string">"resources/tests.js"</span>></script></span><br><span class="line"><link rel=<span class="string">"stylesheet"</span> href=<span class="string">"resources/qunit-1.13.0.css"</span>></span><br></pre></td></tr></table></figure><p>In your tests.js add the following code and presto! Your have some working tests.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">test( <span class="string">"hello string test"</span>, function() {</span><br><span class="line">ok( <span class="number">1</span> === <span class="string">"1"</span>, <span class="string">"Failed!"</span> );</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line">test( <span class="string">"hello integer test"</span>, function() {</span><br><span class="line">ok( <span class="number">1</span> === <span class="number">1</span>, <span class="string">"Passed!"</span> );</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>Here’s what that looks like in your browser:</p><div class="figure"><img src="/images/qunit.png" alt="Qunit basic setup"><p class="caption">Qunit basic setup</p></div><p>Now let’s add some extensions to Qunit. Link jQuery and the QunitExtensions.js in your header and you’ll get the following extra’s. You could get rid of the jquery, but you’ll have to rewrite some of the extension code. * Next to existing Test and AsyncTest, the extensions adds a SkippedTest. * A handy checkbox that will sort the test results by result type * A checkbox similar to the existing ones that lets you hide/show the SkippedTests * Setup module function which enables you to define setup and teardown functions for your tests.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">function <span class="title">setupModule</span>(<span class="params">name, setupFunction, tearDownFunction</span>)</span>{…}</span><br></pre></td></tr></table></figure><p>For the statistics guys/gals I threw in the following code. Which outputs a Junit XML report to the console. The thought behind that is to prepare to dump this report in a CI environment. You’ll have to add the qunit-reporter-junit.js in your header as well.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">QUnit.jUnitReport = function(report) {</span><br><span class="line">console.log(report.xml);</span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>Here’s an example export:</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><?xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span>?></span><br><span class="line"><testsuites name=<span class="string">"file:///D:/cloudstation/JS%20testing/testsuite.html"</span> </span><br><span class="line">hostname=<span class="string">"localhost"</span> tests=<span class="string">"2"</span> failures=<span class="string">"0"</span> errors=<span class="string">"0"</span> time=<span class="string">"0.053"</span> timestamp=<span class="string">"2014-11-06T10:40:37Z"</span>></span><br><span class="line"><testsuite id=<span class="string">"0"</span> name=<span class="string">"Hello Qunit module"</span> hostname=<span class="string">"localhost"</span> tests=<span class="string">"2"</span> failures=<span class="string">"0"</span></span><br><span class="line"> errors=<span class="string">"0"</span> time=<span class="string">"0.001"</span> timestamp=<span class="string">"2014-11-06T10:40:37Z"</span>></span><br><span class="line"><testcase name=<span class="string">"hello string test"</span> tests=<span class="string">"1"</span> failures=<span class="string">"0"</span> errors=<span class="string">"0"</span> time=<span class="string">"0"</span> timestamp=<span class="string">"2014-11-06T10:40:37Z"</span>></span><br><span class="line"></testcase></span><br><span class="line"><testcase name=<span class="string">"hello integer test"</span> tests=<span class="string">"1"</span> failures=<span class="string">"0"</span> errors=<span class="string">"0"</span> time=<span class="string">"0"</span> timestamp=<span class="string">"2014-11-06T10:40:37Z"</span>></span><br><span class="line"></testcase></span><br><span class="line"></testsuite></span><br><span class="line"><testsuite id=<span class="string">"1"</span> name=<span class="string">"skipped test module"</span> hostname=<span class="string">"localhost"</span> tests=<span class="string">"0"</span> failures=<span class="string">"0"</span></span><br><span class="line"> errors=<span class="string">"0"</span> time=<span class="string">"0.001"</span> timestamp=<span class="string">"2014-11-06T10:40:37Z"</span>></span><br><span class="line"><testcase name=<span class="string">"Igore me (SKIPPED)"</span> tests=<span class="string">"0"</span> failures=<span class="string">"0"</span> errors=<span class="string">"0"</span> time=<span class="string">"0.001"</span> timestamp=<span class="string">"2014-11-06T10:40:37Z"</span>></span><br><span class="line"></testcase></span><br><span class="line"></testsuite></span><br><span class="line"></testsuites></span><br></pre></td></tr></table></figure><p>Here’s what the skipped test looks like in code and browser:</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">SkippedTest(<span class="string">'Igore me'</span>,function(){</span><br><span class="line">equal(<span class="string">'foo'</span>,<span class="string">'bar'</span>, <span class="string">'this never happened'</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><div class="figure"><img src="/images/qunit2.png" alt="Qunit skipped test"><p class="caption">Qunit skipped test</p></div><p>Now let’s divide these tests into modules without any setup and teardown functions:</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">setupModule(<span class="string">"Hello Qunit module"</span>, <span class="keyword">null</span>, <span class="keyword">null</span>);</span><br><span class="line"></span><br><span class="line">test( <span class="string">"hello string test"</span>, function() {</span><br><span class="line">ok( <span class="string">"1"</span> === <span class="string">"1"</span>, <span class="string">"Failed!"</span> );</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line">test( <span class="string">"hello integer test"</span>, function() {</span><br><span class="line">ok( <span class="number">1</span> === <span class="number">1</span>, <span class="string">"Passed!"</span> );</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line">setupModule(<span class="string">"skipped test module"</span>, <span class="keyword">null</span>, <span class="keyword">null</span>);</span><br><span class="line">SkippedTest(<span class="string">'Igore me'</span>,function(){</span><br><span class="line">equal(<span class="string">'foo'</span>,<span class="string">'bar'</span>, <span class="string">'this never happened'</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>Notice that the results display the name of the module they belong to, but more practical is the dropdown at the top allowing you to select a module. This will execute only the tests in that module. At some point you may want to have some benchmarks on your script (functional script, not the tests themselves). So lets do that now. Don’t forget to add references to lodash-compat.js and benchmark.js . Just so we have something to test, I added the RandomIntFromInterval and GenerateCode functions (guess what they do..). In the tests. js file I added a formatOutput function to display the results of the benchmark.</p><p>And this code snippet which creates the benchmark suite and adds the two functions to it:</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> suite = <span class="keyword">new</span> Benchmark.Suite;</span><br><span class="line"></span><br><span class="line"><span class="comment">// add tests</span></span><br><span class="line">suite.add(<span class="string">'RandomIntFromInterval_benchmark#test'</span>, function() {</span><br><span class="line"><span class="keyword">var</span> Number = RandomIntFromInterval(<span class="number">1</span>, <span class="number">10</span>);</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">.add(<span class="string">'GenerateCode_benchmark#test'</span>, function() {</span><br><span class="line"><span class="keyword">var</span> ColorsEnum = [<span class="string">"yellow"</span>, <span class="string">"green"</span>, <span class="string">"orange"</span>,<span class="string">"purple"</span>,<span class="string">"gray"</span>,<span class="string">"magenta"</span>,<span class="string">"red"</span>,<span class="string">"white"</span>,<span class="string">"black"</span>];</span><br><span class="line"><span class="keyword">var</span> mastercode = GenerateCode(ColorsEnum);</span><br><span class="line">})</span><br><span class="line"><span class="comment">// add listeners</span></span><br><span class="line">.on(<span class="string">'cycle'</span>, function(<span class="keyword">event</span>) {</span><br><span class="line"><span class="comment">//console.log(String(event.target));</span></span><br><span class="line">$(<span class="string">"<div>"</span>+formatOutput(String(<span class="keyword">event</span>.target))+<span class="string">"</div>"</span>).appendTo(<span class="string">"#benchmarks"</span>);</span><br><span class="line">})</span><br><span class="line">.on(<span class="string">'complete'</span>, function() {</span><br><span class="line">console.log(<span class="string">'Fastest is '</span> + <span class="keyword">this</span>.filter(<span class="string">'fastest'</span>).pluck(<span class="string">'name'</span>));</span><br><span class="line">})</span><br><span class="line">.on(<span class="string">'start'</span>,function(){</span><br><span class="line"><span class="comment">// do something when the suite starts</span></span><br><span class="line">})</span><br><span class="line"><span class="comment">// run async</span></span><br><span class="line">.run({ <span class="string">'async'</span>: <span class="keyword">true</span> });</span><br></pre></td></tr></table></figure><p>This will result in the super helpful results below (notice the pretty layout I added to make it match the Qunit results). I’d advise to wrap the benchmark code in a conditional statement so you can toggle them on or off. You can even go so far as to add another checkbox to control that.</p><div class="figure"><img src="/images/qunit3.png" alt="Qunit benchmark"><p class="caption">Qunit benchmark</p></div><p>But what about quality you ask. Well let’s add a quality check with jsHint and Qhint (which is just a layer over jsHint). Link to the correct files in the head of the page. And add the following test to your tests.js file (demo.js contains the functions of previous steps):</p><ul><li>qHint(“QHint code quality:”, “resources/demo.js”); Since we did such a fine job in coding those functions I get an “Okay” from jsHint.</li></ul><div class="figure"><img src="/images/qunit4.png" alt="JShint"><p class="caption">JShint</p></div><p>Now you might get an error like this:</p><div class="figure"><img src="/images/qunit5.png" alt="JShint error"><p class="caption">JShint error</p></div><p>Which means you aren’t running the testsuite file from a server (IIS, or WAMP or anything like it). If the URL in your address bar starts with “file:///”, you’ll get punished with a broken test. So again I’d advise to put a condition around it, to ignore this test in case want to run the testsuite outside of a server environment.</p><p>Finally if you are really really serious about testing, you can run a code coverage test with JS-Coverage. A project called JSCover is being built on top of this, which checks even more metrics. Running JS-coverage involves executing and exe with some parameters, so I’ll refer to their manual instead of repeating it here: [link](http://siliconforks.com/jscoverage/manual.html](http://siliconforks.com/jscoverage/manual.html) .</p><p>Basically it takes your files and inserts instrumenting javascript in them and drops everything in a new directory. In this directory you’ll find a jscoverage.html. <strong>IMPORTANT</strong> just like jsHint you’ll need to run this file on a server. Once you open that, you’ll see a (very ugly) screen like this:</p><div class="figure"><img src="/images/qunit6.png" title="JS coverage" alt="JS coverage"><p class="caption">JS coverage</p></div><p>Here I already entered the url to the testsuite.html file.</p><p>IMPORTANT this should be the file inside the newly generated js-coverage directory as this is the one containing the instrumentation code.</p><p>If you click on the summary tab you’ll see something similar to this:</p><div class="figure"><img src="/images/qunit7.png" title="JS coverage summary" alt="JS coverage summary"><p class="caption">JS coverage summary</p></div><p>If you click on one of the files you’ll open up the source tab with some extra info:</p><div class="figure"><img src="/images/qunit8.png" title="JS coverage source" alt="JS coverage source"><p class="caption">JS coverage source</p></div><p>That concludes this tutorial. I’ll include a zip-file which contains the code of this tutorial.</p><p>As a bonus I’ll add a second zip file containing a simple mastermind game, made TDD style with all these tool. You can find the tests in /js/testsuite.html I already generated the instrumented code which can be found in mastermind/jscoverage_src .</p><div class="figure"><img src="/images/qunit9.png" title="Mastermind screenshot" alt="Mastermind screenshot"><p class="caption">Mastermind screenshot</p></div><p>The idea behind making that mastermind game, besides the fact that it is fun, is to make a series of these tutorials. Next step will be some better layout and useabilty (yes, I’m talking about a fancy color picker and all that) and javascript templating with mustache.</p><p>List of links for more information:</p><ul><li>[QHint] (https://github.com/gyoshev/qhint)</li><li>[JSHint] (http://www.jshint.com/)</li><li>[Benchmark] (http://benchmarkjs.com/)</li><li>[QUnit] (http://qunitjs.com/)</li><li>[JS-Coverage] (http://siliconforks.com/jscoverage/)</li></ul><p>Zip files with all code for this tutorial:</p><ul><li><a href="/2016/05/18/javascript-unit-testing/mastermind.zip" title="mastermind zip file">mastermind zip file</a></li><li><a href="/2016/05/18/javascript-unit-testing/testsuite.zip" title="test suite zip file">test suite zip file</a></li></ul><!-- rebuild by neat -->]]></content>
<summary type="html">
testing one, two. Even javascript could benefit from some testing and quality checks.
</summary>
<category term="javascript" scheme="http://www.sitecorn.be/tags/javascript/"/>
<category term="unit testing" scheme="http://www.sitecorn.be/tags/unit-testing/"/>
</entry>
<entry>
<title>Custom mediaRequest in Sitecore 8</title>
<link href="http://www.sitecorn.be/2016/05/18/custom-mediarequest/"/>
<id>http://www.sitecorn.be/2016/05/18/custom-mediarequest/</id>
<published>2016-05-18T13:51:24.349Z</published>
<updated>2016-09-08T15:45:31.617Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>For a new project in Sitecore 8, we needed an Image cropper. However, the images needed to be cropped dynamically. We started off by implementing the image cropper made by Anders Laub (found <a href="http://laubplusco.net/make-sitecore-deliver-images-fits-screen-part-2/" target="_blank" rel="external">here</a>). After adding the custom image processor, we could use a few querystring parameters to crop the image. the important ones are:</p><ul><li>cw : crop width</li><li>ch : crop height</li><li>c : indicate that this cropper is to be used</li></ul><p>However, when we got this working we noticed that the image was cached by sitecore, but the new querystring parameters were not. When an image is being processed, a cache is created in the app_data/mediacache folder. In a subfolder the transformed image is stored along with some info in a .ini file. The contents of the file will look something like this:</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">[key]</span><br><span class="line">?<span class="keyword">as</span>=False&bc=<span class="number">0</span>&h=<span class="number">0</span>&iar=False&mh=<span class="number">0</span>&mw=<span class="number">0</span>&sc=<span class="number">0</span>&thn=False&w=<span class="number">0</span></span><br><span class="line"></span><br><span class="line">[extension]</span><br><span class="line">png</span><br><span class="line"></span><br><span class="line">[headers]</span><br><span class="line">Content-Type: image/png</span><br><span class="line"></span><br><span class="line">[dataFile]</span><br><span class="line"><span class="number">3</span>f427bbc14fa4e4aa399266c96221b51.png</span><br></pre></td></tr></table></figure><p>The key obviously contains the querystring parameters used in the url to link the image. Notice how all the default parameters are included, but none of the custom ones for the image cropper. To force sitecore to do that you need to write a custom mediarequest class that inherits from the MediaRequest class, found in the Sitecore.Resources.Media namespace. In your new class, you need to override the GetOptions() and Clone() methods of the MediaRequest class. I came up with a super original name for my new class, the CustomMediaRequest class.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">override</span> MediaRequest <span class="title">Clone</span>(<span class="params"></span>)</span><br><span class="line"> </span>{</span><br><span class="line"> Assert.IsTrue((<span class="keyword">bool</span>)(<span class="keyword">base</span>.GetType() == <span class="keyword">typeof</span>(CustomMediaRequest)), </span><br><span class="line"> <span class="string">"The Clone() method must be overridden to support prototyping."</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> CustomMediaRequest { innerRequest = <span class="keyword">this</span>.innerRequest, mediaUri = <span class="keyword">this</span>.mediaUri,</span><br><span class="line"> options = <span class="keyword">this</span>.options, mediaQueryString = <span class="keyword">this</span>.mediaQueryString };</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>Since I didn’t need any fancy things done here I basically copied the existing code and changed the MediaRequest to CustomMediaRequest. The GetOptions() method is also mostly a copy of the original, but here I added some code to include the new querystring parameters. The parameters both custom and sitecore ones (KnownOptions) are stored in MediaOptions.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">this</span>.ProcessCustomParameters(options); </span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (!options.CustomOptions.ContainsKey(<span class="string">"c"</span>))</span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions.Add(<span class="string">"c"</span>, queryString.Get(<span class="string">"c"</span>));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions[<span class="string">"c"</span>] = queryString.Get(<span class="string">"c"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (!options.CustomOptions.ContainsKey(<span class="string">"cw"</span>))</span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions.Add(<span class="string">"cw"</span>, queryString.Get(<span class="string">"cw"</span>));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions[<span class="string">"cw"</span>] = queryString.Get(<span class="string">"cw"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (!options.CustomOptions.ContainsKey(<span class="string">"ch"</span>))</span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions.Add(<span class="string">"ch"</span>, queryString.Get(<span class="string">"ch"</span>));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions[<span class="string">"ch"</span>] = queryString.Get(<span class="string">"ch"</span>);</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p>Finally, we need to add an extra config file in the app_config/include folder. I named mine Sitecore.Media.RequestParser.config since we are replacing the default requestparser with our own.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><requestParser type=<span class="string">"Company.SC.Requests.CustomMediaRequest, Company.SC"</span> </span><br><span class="line">patch:instead=<span class="string">"processor[@type='Sitecore.Resources.Media.MediaRequest, Sitecore.Kernel']"</span> /></span><br></pre></td></tr></table></figure><p>Notice how we added the patch:instead. Patch:After won’t work as only one RequestParser is used. you also need to patch the Sitecore.Media.RequestProtection.config file, so that sitecore knows about these parameters.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><protectedMediaQueryParameters></span><br><span class="line"> ...</span><br><span class="line"> <parameter description=<span class="string">"crop query key"</span> name=<span class="string">"c"</span>/></span><br><span class="line"> <parameter description=<span class="string">"crop width query key"</span> name=<span class="string">"cw"</span>/></span><br><span class="line"> <parameter description=<span class="string">"crop height query key"</span> name=<span class="string">"ch"</span>/></span><br><span class="line"> <parameter description=<span class="string">"jpeg compression"</span> name=<span class="string">"jq"</span>/></span><br><span class="line"></protectedMediaQueryParameters></span><br><span class="line"></span><br><span class="line"><customMediaQueryParameters></span><br><span class="line"> <parameter description=<span class="string">"image encoding"</span> name=<span class="string">"enc"</span>/></span><br><span class="line"></customMediaQueryParameters></span><br><span class="line">You need to patch <span class="keyword">this</span> before the renderWebEditing pipeline.</span><br><span class="line"></span><br><span class="line"> <pipelines></span><br><span class="line"> <renderField></span><br><span class="line"> <processor patch:before=<span class="string">"processor[@type='Sitecore.Pipelines.RenderField.RenderWebEditing, Sitecore.Kernel']"</span></span><br><span class="line"> type=<span class="string">"Sitecore.Pipelines.RenderField.ProtectedImageLinkRenderer, Sitecore.Kernel"</span> /></span><br><span class="line"> </renderField></span><br><span class="line"> </pipelines></span><br></pre></td></tr></table></figure><p>When this is done, the CustomOptions will be added to the querystring and the image cache key in the ini .file will look like this:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[key]</span><br><span class="line">?as=False&bc=0&h=0&iar=False&mh=0&mw=0&sc=0&thn=False&w=0&c=1&ch=550&cw=180</span><br></pre></td></tr></table></figure><p>Now, every time you render the image with different cropping (querystring) settings, a new image is stored in the mediacache (sub)folder and a new key is added to the .ini file. I hope this short tutorial can help someone looking to extend the image caching.</p><p>The complete CustomMediaRequest class:</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br></pre></td><td class="code"><pre><span class="line">using System.Collections.Specialized;</span><br><span class="line">using System.Web;</span><br><span class="line">using Sitecore.Configuration;</span><br><span class="line">using Sitecore.Diagnostics;</span><br><span class="line">using Sitecore.Resources.Media;</span><br><span class="line"></span><br><span class="line">namespace YourProject.SC.Requests</span><br><span class="line">{</span><br><span class="line"> public class CustomMediaRequest : MediaRequest</span><br><span class="line"> {</span><br><span class="line"> private HttpRequest innerRequest;</span><br><span class="line"> private bool isRawUrlSafe;</span><br><span class="line"> private bool isRawUrlSafeInitialized;</span><br><span class="line"> private MediaUrlOptions mediaQueryString;</span><br><span class="line"> private Sitecore.Resources.Media.MediaUri mediaUri;</span><br><span class="line"> private MediaOptions options; </span><br><span class="line"></span><br><span class="line"> protected override MediaOptions GetOptions()</span><br><span class="line"> { </span><br><span class="line"> NameValueCollection queryString = this.InnerRequest.QueryString;</span><br><span class="line"> if ((queryString == null) || queryString.HasKeys() )</span><br><span class="line"> {</span><br><span class="line"> options = new MediaOptions();</span><br><span class="line"> }</span><br><span class="line"> else</span><br><span class="line"> {</span><br><span class="line"> MediaUrlOptions mediaQueryString = this.GetMediaQueryString();</span><br><span class="line"> options = new MediaOptions</span><br><span class="line"> {</span><br><span class="line"> AllowStretch = mediaQueryString.AllowStretch,</span><br><span class="line"> BackgroundColor = mediaQueryString.BackgroundColor,</span><br><span class="line"> IgnoreAspectRatio = mediaQueryString.IgnoreAspectRatio,</span><br><span class="line"> Scale = mediaQueryString.Scale,</span><br><span class="line"> Width = mediaQueryString.Width,</span><br><span class="line"> Height = mediaQueryString.Height,</span><br><span class="line"> MaxWidth = mediaQueryString.MaxWidth,</span><br><span class="line"> MaxHeight = mediaQueryString.MaxHeight,</span><br><span class="line"> Thumbnail = mediaQueryString.Thumbnail</span><br><span class="line"> };</span><br><span class="line"> if (mediaQueryString.DisableMediaCache)</span><br><span class="line"> {</span><br><span class="line"> options.UseMediaCache = false;</span><br><span class="line"> }</span><br><span class="line"> string[] strArray = queryString.AllKeys;</span><br><span class="line"> for (int i = 0; i < strArray.Length; i = (int)(i + 1))</span><br><span class="line"> {</span><br><span class="line"> string str = strArray[i];</span><br><span class="line"> if ((str != null) && (queryString.Get(str) != null))</span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions[str] = queryString.Get(str);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> if (!this.IsRawUrlSafe)</span><br><span class="line"> {</span><br><span class="line"> if (Settings.Media.RequestProtection.LoggingEnabled)</span><br><span class="line"> {</span><br><span class="line"> string urlReferrer = this.GetUrlReferrer();</span><br><span class="line"> Log.SingleError(string.Format("MediaRequestProtection: An invalid/missing hash value was encountered.</span><br><span class="line"> The expected hash value: {0}. Media URL: {1}, Referring URL: {2}"</span><br><span class="line"> , HashingUtils.GetAssetUrlHash(this.InnerRequest.Path), this.InnerRequest.Path, string.IsNullOrEmpty(urlReferrer)</span><br><span class="line"> ? ((object)"(empty)") : ((object)urlReferrer)), this);</span><br><span class="line"> }</span><br><span class="line"> options = new MediaOptions();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> this.ProcessCustomParameters(options); </span><br><span class="line"></span><br><span class="line"> if (!options.CustomOptions.ContainsKey("c"))</span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions.Add("c", queryString.Get("c"));</span><br><span class="line"> }</span><br><span class="line"> else</span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions["c"] = queryString.Get("c");</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> if (!options.CustomOptions.ContainsKey("cw"))</span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions.Add("cw", queryString.Get("cw"));</span><br><span class="line"> }</span><br><span class="line"> else</span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions["cw"] = queryString.Get("cw");</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> if (!options.CustomOptions.ContainsKey("ch"))</span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions.Add("ch", queryString.Get("ch"));</span><br><span class="line"> }</span><br><span class="line"> else</span><br><span class="line"> {</span><br><span class="line"> options.CustomOptions["ch"] = queryString.Get("ch");</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> return options;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public override MediaRequest Clone()</span><br><span class="line"> {</span><br><span class="line"> Assert.IsTrue((bool)(base.GetType() == typeof(CustomMediaRequest)),</span><br><span class="line"> "The Clone() method must be overridden to support prototyping.");</span><br><span class="line"> return new CustomMediaRequest { innerRequest = this.innerRequest,</span><br><span class="line"> mediaUri = this.mediaUri, options = this.options, mediaQueryString = this.mediaQueryString };</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>The complete Sitecore.Media.RequestParser.config file:</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><?xml version=<span class="string">"1.0"</span>?></span><br><span class="line"><configuration xmlns:patch=<span class="string">"http://www.sitecore.net/xmlconfig/"</span>></span><br><span class="line"><sitecore></span><br><span class="line"> <mediaLibrary></span><br><span class="line"> <requestParser type=<span class="string">"Company.SC.Requests.CustomMediaRequest, Company.SC"</span> </span><br><span class="line"> patch:instead=<span class="string">"processor[@type='Sitecore.Resources.Media.MediaRequest, Sitecore.Kernel']"</span> /></span><br><span class="line"> </mediaLibrary></span><br><span class="line"></sitecore></span><br><span class="line"></configuration></span><br></pre></td></tr></table></figure><p>Finally I’d like to thank <a href="http://laubplusco.net/" target="_blank" rel="external">Anders Laub</a>, for his excellent Sitecore blog and image cropper code.</p><!-- rebuild by neat -->]]></content>
<summary type="html">
how to crop sitecore images and cache the output
</summary>
<category term="sitecore 8" scheme="http://www.sitecorn.be/tags/sitecore-8/"/>
<category term="mediarequest" scheme="http://www.sitecorn.be/tags/mediarequest/"/>
</entry>
<entry>
<title>Google maps autocomplete filter by multiple countries</title>
<link href="http://www.sitecorn.be/2016/05/18/googlemaps-autocomplete-filter-multiple-countries/"/>
<id>http://www.sitecorn.be/2016/05/18/googlemaps-autocomplete-filter-multiple-countries/</id>
<published>2016-05-18T13:43:26.473Z</published>
<updated>2016-09-08T15:44:08.982Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>At the end of last year (2014) I had to modify an existing Google maps autocomplete to filter by multiple countries. To my horror I discovered this was not possible, in fact the issue / feature request has been logged since 2012 (google issue) without any real fix. So I had to work around it.</p><p>I found out it is possible to get Autocomplete predictions, but sadly they suffer from the same shortcoming. However the predictions return a list of, well predictions allowing the developer to make their own lists. So that’s what I did and after sprinkling some jQuery around I came up with my own custom Autocomplete.</p><p>I only had to search a secondary country (Luxemburg) when the current country was Belgium, that’s why those countries are hard coded in the demo example. Feel free to use the code and change it in any way.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br></pre></td><td class="code"><pre><span class="line"><!DOCTYPE html></span><br><span class="line"></span><br><span class="line"> <html></span><br><span class="line"> <head></span><br><span class="line"> <title>Retrieving Autocomplete Predictions</title></span><br><span class="line"> <script type=<span class="string">"text/javascript"</span> src=<span class="string">"jquery.js"</span>></script></span><br><span class="line"> <script type=<span class="string">"text/javascript"</span> src=<span class="string">"https://maps.googleapis.com/maps/api/js?libraries=places&v=3.exp"</span>></script></span><br><span class="line"> <script></span><br><span class="line"></span><br><span class="line"> <span class="function">function <span class="title">initialize</span>(<span class="params"></span>) </span>{ </span><br><span class="line"> $(<span class="string">"#place"</span>).live(<span class="string">"keyup"</span>, function (evt) { </span><br><span class="line"> <span class="comment">// Clear any previously set timer before setting a new one</span></span><br><span class="line"> window.clearTimeout($(<span class="keyword">this</span>).data(<span class="string">"timeout"</span>));</span><br><span class="line"> $(<span class="keyword">this</span>).data(<span class="string">"timeout"</span>, setTimeout(function () {</span><br><span class="line"> <span class="comment">//whe the timeout has expired get the predictions</span></span><br><span class="line"> <span class="keyword">var</span> inputData = $(<span class="string">"#place"</span>).val(); </span><br><span class="line"> service = <span class="keyword">new</span> google.maps.places.AutocompleteService();</span><br><span class="line"> <span class="keyword">var</span> request = {</span><br><span class="line"> input: inputData,</span><br><span class="line"> componentRestrictions: {country: <span class="string">'be'</span>},</span><br><span class="line"> };</span><br><span class="line"> <span class="keyword">var</span> secondaryRequest = {</span><br><span class="line"> input: inputData,</span><br><span class="line"> componentRestrictions: {country: <span class="string">'lu'</span>},</span><br><span class="line"> };</span><br><span class="line"> $(<span class="string">'#resultWindow'</span>).empty();</span><br><span class="line"> service.getPlacePredictions(request, callback);</span><br><span class="line"> service.getPlacePredictions(secondaryRequest, callback); </span><br><span class="line"> }, <span class="number">1000</span>));</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> <span class="function">function <span class="title">callback</span>(<span class="params">predictions, status</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (status != google.maps.places.PlacesServiceStatus.OK) {</span><br><span class="line"> console.log(status);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> } </span><br><span class="line"> <span class="keyword">var</span> resultHTML = <span class="string">''</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, prediction; prediction = predictions[i]; i++) {</span><br><span class="line"> resultHTML += <span class="string">'<div>'</span> + prediction.description + <span class="string">'</div>'</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>($(<span class="string">'#resultWindow'</span>).html() != undefined && $(<span class="string">'#resultWindow'</span>).html() != <span class="string">''</span>){ </span><br><span class="line"> resultHTML = $(<span class="string">'#resultWindow'</span>).html()+ resultHTML;</span><br><span class="line"> } </span><br><span class="line"> <span class="keyword">if</span>(resultHTML != undefined && resultHTML != <span class="string">''</span>){ </span><br><span class="line"> $(<span class="string">'#resultWindow'</span>).html(resultHTML).show();</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//add the "powered by google" image at the bottom -> required!!</span></span><br><span class="line"> <span class="keyword">if</span>($(<span class="string">'#resultWindow'</span>).html() != undefined){</span><br><span class="line"> $(<span class="string">'#resultWindow #googleImage'</span>).remove();</span><br><span class="line"> <span class="keyword">var</span> imageHtml = $(<span class="string">'#resultWindow'</span>).html() </span><br><span class="line"> + <span class="string">'<img id="googleImage" src="powered-by-google-on-white2.png"/>'</span>;</span><br><span class="line"> $(<span class="string">'#resultWindow'</span>).html(imageHtml);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function">function <span class="title">geocodeAddress</span>(<span class="params">address</span>) </span>{ </span><br><span class="line"> <span class="keyword">var</span> geocoder = <span class="keyword">new</span> google.maps.Geocoder(); </span><br><span class="line"> geocoder.geocode({<span class="string">'address'</span>: address}, function (results, status) </span><br><span class="line"> { </span><br><span class="line"> <span class="keyword">if</span> (status == google.maps.GeocoderStatus.OK) </span><br><span class="line"> {</span><br><span class="line"> $(<span class="string">'#latitude'</span>).val(results[<span class="number">0</span>].geometry.location.lat());</span><br><span class="line"> $(<span class="string">'#longitude'</span>).val(results[<span class="number">0</span>].geometry.location.lng()); </span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> console.log(<span class="string">"Error: "</span> + google.maps.GeocoderStatus);</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> $(<span class="string">'#resultWindow div'</span>).live(<span class="string">'click'</span>,function(){</span><br><span class="line"> <span class="comment">//get the coördinates for the selected (clicked) address</span></span><br><span class="line"> $(<span class="string">'#resultWindow'</span>).hide();</span><br><span class="line"> <span class="keyword">var</span> address = $(<span class="keyword">this</span>).text();</span><br><span class="line"> <span class="keyword">var</span> addressParts = address.split(<span class="string">','</span>);</span><br><span class="line"> $(<span class="string">'#country'</span>).val(addressParts[<span class="number">2</span>]);</span><br><span class="line"> $(<span class="string">'#city'</span>).val(addressParts[<span class="number">1</span>]);</span><br><span class="line"> $(<span class="string">'#place'</span>).val(addressParts[<span class="number">0</span>]);</span><br><span class="line"> <span class="keyword">if</span>(address != <span class="string">''</span>){</span><br><span class="line"> geocodeAddress(address);</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> <span class="comment">/*end custom autocomplete stuff*/</span></span><br><span class="line"> }</span><br><span class="line"> google.maps.<span class="keyword">event</span>.addDomListener(window, <span class="string">'load'</span>, initialize);</span><br><span class="line"></span><br><span class="line"> </script></span><br><span class="line"> <style type=<span class="string">"text/css"</span>></span><br><span class="line"> <span class="meta">#resultWindow{ </span></span><br><span class="line"> position: <span class="keyword">fixed</span>;</span><br><span class="line"> <span class="comment">/* top: 0;</span><br><span class="line"> left: 0;</span><br><span class="line"> width: 100%;</span><br><span class="line"> height: 100%;*/</span></span><br><span class="line"> background-color: <span class="meta">#fff;</span></span><br><span class="line"> filter:alpha(opacity=<span class="number">50</span>);</span><br><span class="line"> -moz-opacity:<span class="number">0.5</span>;</span><br><span class="line"> -khtml-opacity: <span class="number">0.5</span>;</span><br><span class="line"> opacity: <span class="number">0.5</span>;</span><br><span class="line"> z-index: <span class="number">10000</span>;</span><br><span class="line"> border: <span class="number">1</span>px solid black;</span><br><span class="line"> color:black;</span><br><span class="line"> display:none;</span><br><span class="line"> }</span><br><span class="line"> </style></span><br><span class="line"> </head></span><br><span class="line"><body></span><br><span class="line"><div id=<span class="string">"placeholder"</span>> </span><br><span class="line"> <input type=<span class="string">"text"</span> id=<span class="string">"place"</span> style=<span class="string">"width:200px;"</span>/></span><br><span class="line"> <label <span class="keyword">for</span>=<span class="string">"latitude"</span>>Latitude</label></span><br><span class="line"> <input type=<span class="string">"text"</span> id=<span class="string">"latitude"</span>/></span><br><span class="line"> <label <span class="keyword">for</span>=<span class="string">"longitude"</span>>Longitude</label></span><br><span class="line"> <input type=<span class="string">"text"</span> id=<span class="string">"longitude"</span>/></span><br><span class="line"> <label <span class="keyword">for</span>=<span class="string">"city"</span>>city</label></span><br><span class="line"> <input type=<span class="string">"text"</span> id=<span class="string">"city"</span>/></span><br><span class="line"> <label <span class="keyword">for</span>=<span class="string">"country"</span>>selected country</label></span><br><span class="line"> <input type=<span class="string">"text"</span> id=<span class="string">"country"</span>/></span><br><span class="line"> <div id=<span class="string">"resultWindow"</span>></div> </span><br><span class="line"></div></span><br><span class="line"></body></span><br><span class="line"></html></span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
<summary type="html">
how to fiter a google maps autocomplete by multiple countries
</summary>
<category term="google maps" scheme="http://www.sitecorn.be/tags/google-maps/"/>
<category term="javascript" scheme="http://www.sitecorn.be/tags/javascript/"/>
<category term="autocomplete" scheme="http://www.sitecorn.be/tags/autocomplete/"/>
<category term="filter" scheme="http://www.sitecorn.be/tags/filter/"/>
</entry>
<entry>
<title>Sitecore multiple forms on one page - view renderings</title>
<link href="http://www.sitecorn.be/2016/05/18/mvc/sitecore-multiple-forms-on-a-page/"/>
<id>http://www.sitecorn.be/2016/05/18/mvc/sitecore-multiple-forms-on-a-page/</id>
<published>2016-05-18T10:57:42.746Z</published>
<updated>2016-09-08T15:37:48.479Z</updated>
<content type="html"><![CDATA[<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>I was trying to read out form values after a POST and was reminded by a colleague that all controller actions will be able to render the form. That simply will not do. He referred me to some excellent blog posts which offer a solution for the controller renderings. Check out Reinoud Van Dalen’s ultimate fix for multiple forms on one page with sitecore mvc</p><p>However I happened to have a view rendering on the receiving end of the form post. This blog post will explain how you can apply the same principle to view rendering.</p><h3 id="create-a-sitecorehelperextension">Create a sitecoreHelperExtension</h3><p>This code was copied form Reinoud’s solution, with a small modification to allow the developer to choose his own id (in case you want to use the id from some kind of generated code)</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> MvcHtmlString <span class="title">RenderingToken</span>(<span class="params"><span class="keyword">this</span> SitecoreHelper helper, <span class="keyword">string</span> id = <span class="keyword">null</span></span>)</span><br><span class="line"></span>{</span><br><span class="line"> <span class="keyword">if</span> (helper.CurrentRendering == <span class="keyword">null</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> tagBuilder = <span class="keyword">new</span> TagBuilder(<span class="string">"input"</span>);</span><br><span class="line"> tagBuilder.Attributes[<span class="string">"type"</span>] = <span class="string">"hidden"</span>;</span><br><span class="line"> tagBuilder.Attributes[<span class="string">"name"</span>] = <span class="string">"uid"</span>;</span><br><span class="line"> tagBuilder.Attributes[<span class="string">"value"</span>] = id ?? helper.CurrentRendering.UniqueId.ToString();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> MvcHtmlString(tagBuilder.ToString(TagRenderMode.SelfClosing));</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="update-your-form">Update your form</h3><p>You can call this without a parameter and it will use the id of the current rendering (default).</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@Html.Sitecore().RenderingToken()</span><br></pre></td></tr></table></figure><p>Alternatively you could call it using a custom Id, in this case the item Id from our generated code</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@Html.Sitecore().RenderingToken(ItemTree.Layout.Renderings.MyRendering.ItemID.ToGuid().ToString())</span><br></pre></td></tr></table></figure><p>This will generate a hidden field with the unique id of the current rendering (or the ID of your choice). That value will then get posted with the rest of you form.</p><p><strong>remark</strong> the ToGuid() method will remove the curly braces. You can skip that if you don’t mind them in you values. Just don’t forget to use the same structure (with or without curly braces) when reading it back out.</p><h3 id="creating-a-form-extension">Creating a form Extension</h3><p>The first method checks for the correct source form. It does this by comparing the posted Id with the Id you provide it in the renderId parameter. The second method reads the form value in case the source is confirmed to be the correct form.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title">FormExtensions</span></span><br><span class="line">{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">bool</span> <span class="title">IsSourceForm</span>(<span class="params"><span class="keyword">this</span> HttpRequestBase request, <span class="keyword">string</span> renderId, <span class="keyword">string</span> sourceField = <span class="keyword">null</span></span>)</span><br><span class="line"> </span>{</span><br><span class="line"> <span class="keyword">string</span> sourceFieldName = sourceField ?? <span class="string">"uid"</span>;</span><br><span class="line"> <span class="keyword">return</span> request.Form != <span class="keyword">null</span> && !request.Form[sourceFieldName].IsNullOrEmpty() &&</span><br><span class="line"> request.Form[sourceFieldName].Equals(renderId);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">string</span> <span class="title">GetFormSourceValue</span>(<span class="params"><span class="keyword">this</span> HttpRequestBase request, <span class="keyword">string</span> renderId,</span><br><span class="line"> <span class="keyword">string</span> formFieldName, <span class="keyword">string</span> sourceFieldName = <span class="keyword">null</span></span>)</span><br><span class="line"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (!IsSourceForm(request, renderId, sourceFieldName))</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> request.Form[formFieldName].HasValue() </span><br><span class="line"> ? request.Form[formFieldName] </span><br><span class="line"> : <span class="keyword">string</span>.Empty;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Here’s the one liner on how to get the value you want, from the form you want .</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> formID = ItemTree.Layout.Renderings.MyRendering.ItemID.ToGuid().ToString();</span><br><span class="line"><span class="keyword">var</span> formValue = Request.GetFormSourceValue(formID, <span class="string">"name of form value"</span>);</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
<summary type="html">
<!-- build time:Sat Mar 25 2017 11:26:05 GMT+0100 (Romance Standard Time) --><p>I was trying to read out form values after a POST and was re
</summary>
<category term="sitecore 8" scheme="http://www.sitecorn.be/tags/sitecore-8/"/>
<category term="mvc" scheme="http://www.sitecorn.be/tags/mvc/"/>
<category term="multiple renderings" scheme="http://www.sitecorn.be/tags/multiple-renderings/"/>
</entry>
</feed>