<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: iainrough</title>
    <description>The latest articles on DEV Community by iainrough (@iainrough).</description>
    <link>https://dev.to/iainrough</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F559039%2F250ea9df-cf7f-480d-8c30-f3c19417a276.png</url>
      <title>DEV Community: iainrough</title>
      <link>https://dev.to/iainrough</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iainrough"/>
    <language>en</language>
    <item>
      <title>Maui Tip - Resolve a dependancy in MauiProgram.cs</title>
      <dc:creator>iainrough</dc:creator>
      <pubDate>Thu, 04 Jan 2024 15:13:18 +0000</pubDate>
      <link>https://dev.to/iainrough/maui-tip-resolve-a-dependancy-in-mauiprogramcs-1i5k</link>
      <guid>https://dev.to/iainrough/maui-tip-resolve-a-dependancy-in-mauiprogramcs-1i5k</guid>
      <description>&lt;p&gt;Need to resolve a dependency in &lt;code&gt;CreateMauiApp()&lt;/code&gt; method in &lt;code&gt;MauiProgram.cs&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;If you google around you find you need to get an instance of IServiceProvider, this can be achived using the snippet bellow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;serviceProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BuildServiceProvider&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;myService&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;MauiProgram.cs&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>maui</category>
      <category>dotnet</category>
      <category>dependencyinjection</category>
      <category>mobiledev</category>
    </item>
    <item>
      <title>iOS Tips Xamarin Forms - Get Safe Area Height</title>
      <dc:creator>iainrough</dc:creator>
      <pubDate>Wed, 13 Sep 2023 10:36:37 +0000</pubDate>
      <link>https://dev.to/iainrough/ios-tips-xamarin-forms-get-safe-area-height-31od</link>
      <guid>https://dev.to/iainrough/ios-tips-xamarin-forms-get-safe-area-height-31od</guid>
      <description>&lt;p&gt;I needed to get the Safe Area height so I could manipulate a screenshot taken on a device. &lt;a href="https://stackoverflow.com/a/58856891"&gt;Stack Overflow&lt;/a&gt; to the rescue once again.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Yes the project I'm working on has not started the migration to Maui.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Xamarin Forms
&lt;/h2&gt;

&lt;p&gt;Setup the interface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IGetSafeArea&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IGetSafeArea&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;GetSafeAreaTop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;GetSafeAreaBottom&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Xamarin.iOS
&lt;/h2&gt;

&lt;p&gt;Implement the interface and register it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GetSafeArea.cs&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GetSafeArea&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IGetSafeArea&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;GetSafeAreaBottom&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UIDevice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentDevice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CheckSystemVersion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;UIWindow&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UIApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SharedApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Delegate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetWindow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;bottomPadding&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SafeAreaInsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bottom&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;bottomPadding&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;GetSafeAreaTop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UIDevice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentDevice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CheckSystemVersion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;UIWindow&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UIApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SharedApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Delegate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetWindow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;topPadding&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SafeAreaInsets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Top&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;topPadding&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;AppDelegate.cs&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppDelegate&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FormsApplicationDelegate&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="p"&gt;...&lt;/span&gt;
       &lt;span class="n"&gt;DependencyService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GetSafeArea&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
       &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RuntimePlatform&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iOS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;safeAreaTop&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DependencyService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IGetSafeArea&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;GetSafeAreaTop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

       &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/a/58856891"&gt;StackOverFlow&lt;/a&gt;&lt;/p&gt;

</description>
      <category>xamarin</category>
      <category>ios</category>
      <category>dotnetmaui</category>
      <category>mobile</category>
    </item>
    <item>
      <title>iOS Tips - This app cannot be installed because its integrity could not be verified</title>
      <dc:creator>iainrough</dc:creator>
      <pubDate>Tue, 12 Sep 2023 15:11:45 +0000</pubDate>
      <link>https://dev.to/iainrough/ios-tips-this-app-cannot-be-installed-because-its-integrity-could-not-be-verified-3jjm</link>
      <guid>https://dev.to/iainrough/ios-tips-this-app-cannot-be-installed-because-its-integrity-could-not-be-verified-3jjm</guid>
      <description>&lt;p&gt;Ran into the following error today&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ This app cannot be installed because its integrity could not be verified&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Found the following commands helpful in debugging it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check Entitlements for a Provisioning profile on iOS
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   security cms &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; Profile.mobileprovision | xmllint &lt;span class="nt"&gt;--xpath&lt;/span&gt; &lt;span class="s2"&gt;"/plist/dict/key[text()='Entitlements']/following-sibling::dict[position()=1]"&lt;/span&gt; -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.developer.associated-domains&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;*&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;application-identifier&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;#######.com.company.appName&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;keychain-access-groups&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;#######.*&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.apple.token&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;get-task-allow&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.developer.team-identifier&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;#######&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Check the Entitlements of a signed app
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   codesign &lt;span class="nt"&gt;--display&lt;/span&gt; &lt;span class="nt"&gt;--entitlements&lt;/span&gt; :- com.company.appName.app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output after formatting&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd"&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Associated Domain&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;applinks:######?mode=developer&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;application-identifier&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;######.com.company.appName.app&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.developer.team-identifier&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;######&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;get-task-allow&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Simple error and easy to spot if you have the tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ &lt;a href="https://developer.apple.com/documentation/bundleresources/entitlements/diagnosing_issues_with_entitlements"&gt;Diagnosing Issues with Entitlements&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>dotnetmaui</category>
      <category>ios</category>
      <category>xamarin</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Re-Post: My Love Hate Relationship with Kendo Grid — Part 1: The Broken Child Grid on Deployment</title>
      <dc:creator>iainrough</dc:creator>
      <pubDate>Fri, 26 May 2023 08:18:58 +0000</pubDate>
      <link>https://dev.to/iainrough/re-post-my-love-hate-relationship-with-kendo-grid-part-1-the-broken-child-grid-on-deployment-3cln</link>
      <guid>https://dev.to/iainrough/re-post-my-love-hate-relationship-with-kendo-grid-part-1-the-broken-child-grid-on-deployment-3cln</guid>
      <description>&lt;p&gt;&lt;strong&gt;Originally published at:&lt;/strong&gt; &lt;a href="https://roughiain.medium.com/my-love-hate-relationship-with-kendo-grid-part-1-the-broken-child-grid-on-deployment-dfdc3989da57"&gt;https://roughiain.medium.com/my-love-hate-relationship-with-kendo-grid-part-1-the-broken-child-grid-on-deployment-dfdc3989da57&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So a while ago I decided to merge my various GitHub accounts into one account, during this process I lost some gist's which were embedded in the original of this blog post. :(&lt;/p&gt;

&lt;p&gt;So here is the article again with the some edits...&lt;/p&gt;

&lt;h2&gt;
  
  
  My Love Hate Relationship with Kendo Grid — Part 1: The Broken Child Grid on Deployment
&lt;/h2&gt;

&lt;p&gt;For years I have been involved in a love hate relationship with Telerik’s Kendo Grid. Hours have been wasted debugging small things and hours have been saved on massive tasks.&lt;/p&gt;

&lt;p&gt;Some technical info on today's tryst with Kendo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI for ASP.NET Core R2 2019 SP1&lt;/li&gt;
&lt;li&gt;Development machine windows 10&lt;/li&gt;
&lt;li&gt;Production Ubuntu 18.xx &lt;/li&gt;
&lt;li&gt;ASP.NET Core SDK: 2.2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the many joys of programming is discovering the feature that worked 100% on your local machine breaks on production(do i need sarcasm tags?).&lt;/p&gt;

&lt;p&gt;This is the simple grid that broke on deployment[1]&lt;/p&gt;

&lt;p&gt;Everything worked on my local environment, the child grid bound, expanded and contracted, displayed all the correct data.&lt;/p&gt;

&lt;p&gt;On production in developer console …&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Uncaught SyntaxError: Invalid or unexpected token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at inspect source in the browser, and the JS code that Kendo generates: I noticed the JS contained extra line breaks. So could the line breaks in the Razor page be affecting the Kendo JS???&lt;/p&gt;

&lt;p&gt;Yup, one small commit to remove a line break in the child template script and it was fixed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JiwuKUB1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cmpewiklip5kpxoq9wwz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JiwuKUB1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cmpewiklip5kpxoq9wwz.png" alt="GIT DIFF" width="800" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>telerik</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>aspdotnet</category>
    </item>
    <item>
      <title>Telerik Grid Love and Hate: Exporting Client Templates to Excel.</title>
      <dc:creator>iainrough</dc:creator>
      <pubDate>Fri, 26 May 2023 07:54:53 +0000</pubDate>
      <link>https://dev.to/iainrough/telerik-grid-love-and-hate-exporting-client-templates-to-excel-1hlh</link>
      <guid>https://dev.to/iainrough/telerik-grid-love-and-hate-exporting-client-templates-to-excel-1hlh</guid>
      <description>&lt;p&gt;In todays entry in the ongoing saga of love and hate between me and the Kendo Grid. &lt;/p&gt;

&lt;h2&gt;
  
  
  Exporting client template values to excel.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Version&lt;/strong&gt;: &lt;code&gt;Telerik UI For Asp.Net Core 2020.2.617&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So we have a basic Kendo Grid with one minor difference, a column with a client template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sku&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StockStatus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ClientTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#=StockStatus.Value#"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stock status is nothing special a simple class with an &lt;code&gt;int&lt;/code&gt; Id and a &lt;code&gt;string&lt;/code&gt; value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InStockStatusViewModel&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.ClientTemplate("#=StockStatus.Value#");&lt;/code&gt; changes the display to show the &lt;code&gt;Value&lt;/code&gt; from the object.&lt;/p&gt;

&lt;p&gt;So lets add the excel export:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="n"&gt;@section&lt;/span&gt; &lt;span class="n"&gt;Scripts&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/js/jszip.min.js"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToolBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Search SKU"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Excel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Excel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;excel&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;excel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FileName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"StockStatus.xlsx"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;AllPages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nice an simple, except when we test the functionality the third column in the export excel is blank.&lt;/p&gt;

&lt;p&gt;After some googling and frustration from broken links on the &lt;a href="https://www.telerik.com/forums/exporting-grid-to-excel-but-including-client-templates-possible-"&gt;Telerik Forums&lt;/a&gt; we find out that as the client template could generate HTML, the excel export functionality excludes client templates for safety.&lt;/p&gt;

&lt;p&gt;Further down the forum post it links to a &lt;a href="http://dojo.telerik.com/@tsveti/EfoSUNim"&gt;dojo example&lt;/a&gt; of the Jquery version of the grid using a custom block of JS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;exportGridWithTemplatesContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;gridColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workbook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sheets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;visibleGridColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;columnTemplates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;dataItem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// Create element to generate templates in.&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;elem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Get a list of visible columns&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;gridColumns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;gridColumns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;visibleGridColumns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gridColumns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Create a collection of the column templates, together with the current column index&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;visibleGridColumns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;visibleGridColumns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;columnTemplates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;kendo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;visibleGridColumns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Traverse all exported rows.&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
          &lt;span class="c1"&gt;// Traverse the column templates and apply them for each row at the stored column position.&lt;/span&gt;

          &lt;span class="c1"&gt;// Get the data item corresponding to the current row.&lt;/span&gt;
          &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;dataItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
          &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;columnTemplates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;columnTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;columnTemplates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="c1"&gt;// Generate the template content for the current cell.&lt;/span&gt;
            &lt;span class="nx"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;columnTemplate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataItem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;columnTemplate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="c1"&gt;// Output the text content of the templated cell into the exported cell.&lt;/span&gt;
              &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;columnTemplate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay that works, now how do we hook it up to the MVC grid...&lt;/p&gt;

&lt;p&gt;Seems there is a nice event called &lt;code&gt;ExcelExport&lt;/code&gt; that we can pass the name of the JS function provided from the Dojo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExcelExport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"exportGridWithTemplatesContent"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tested again and bingo it works.&lt;/p&gt;

&lt;p&gt;Complete grid code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Kendo&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Grid&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ProductDataStockViewModel&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"StockGrid"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Columns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sku&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StockStatus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ClientTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#=StockStatus.Value#"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Editable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;editable&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;editable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Mode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GridEditMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InCell&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToolBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Search SKU"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Excel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Excel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;excel&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;excel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FileName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"StockStatus.xlsx"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;AllPages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExcelExport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"exportGridWithTemplatesContent"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sku&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Pageable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Filterable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Scrollable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ColumnMenu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DataSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataSource&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Ajax&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Ajax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Ajax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;AutoSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Ajax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;PageSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Ajax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sku"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Ascending&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Ajax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataSourceJsEvent&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;dataSourceJsEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JsFunctionName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DISPLAY_ERROR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Ajax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sku&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Editable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Editable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InStockStatus&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Ajax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"?handler=Read"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpVerbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JsFunctionName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET_FORGERY_TOKEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="n"&gt;dataSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Ajax&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"?handler=Update"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpVerbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JsFunctionName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET_FORGERY_TOKEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>dotnet</category>
      <category>telerik</category>
      <category>csharp</category>
      <category>aspdotnet</category>
    </item>
    <item>
      <title>Copy Via SSH - Adventures in WSL2 Scripting #3</title>
      <dc:creator>iainrough</dc:creator>
      <pubDate>Mon, 14 Feb 2022 06:17:17 +0000</pubDate>
      <link>https://dev.to/iainrough/copy-via-ssh-adventures-in-wsl2-scripting-3-5b32</link>
      <guid>https://dev.to/iainrough/copy-via-ssh-adventures-in-wsl2-scripting-3-5b32</guid>
      <description>&lt;h2&gt;
  
  
  Upload
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scp myzip myUserName@targetHost:/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Download
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scp myUserName@targetHost:/myDump.sql ~/dumps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ssh</category>
      <category>bash</category>
      <category>wsl2</category>
      <category>scripting</category>
    </item>
    <item>
      <title>Post to Slack WebHook from Bash using Curl - Adventures in WSL2 Scripting #2</title>
      <dc:creator>iainrough</dc:creator>
      <pubDate>Tue, 15 Jun 2021 09:22:50 +0000</pubDate>
      <link>https://dev.to/iainrough/post-to-slack-webhook-from-bash-using-curl-adventures-in-wsl2-scripting-2-18c9</link>
      <guid>https://dev.to/iainrough/post-to-slack-webhook-from-bash-using-curl-adventures-in-wsl2-scripting-2-18c9</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# URL as supplied in your slack bot&lt;/span&gt;
&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://hooks.slack.com/services/&lt;span class="o"&gt;{}&lt;/span&gt;/&lt;span class="o"&gt;{}&lt;/span&gt;/&lt;span class="o"&gt;{}&lt;/span&gt;

&lt;span class="c"&gt;#JSON body&lt;/span&gt;
&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{"text": ":interrobang: Unable to do something"}'&lt;/span&gt;

sendError&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
    curl &lt;span class="nt"&gt;-X&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         POST &lt;span class="se"&gt;\&lt;/span&gt;
         &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         &lt;span class="nv"&gt;$url&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;#Function that checks something&lt;/span&gt;
checkSomething

&lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="c"&gt;#echo "result: $result"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;sendError
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
Bash script that on failure sends slack notice.


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UsbfZjQR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xgef36bqown2qm6edx1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UsbfZjQR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xgef36bqown2qm6edx1f.png"&gt;&lt;/a&gt;&lt;/p&gt;
The Result in Slack.



</description>
      <category>wsl2</category>
      <category>bash</category>
      <category>linux</category>
      <category>slack</category>
    </item>
    <item>
      <title>if... then... elif.. else - Adventures in WSL2 Scripting #1</title>
      <dc:creator>iainrough</dc:creator>
      <pubDate>Fri, 04 Jun 2021 13:22:48 +0000</pubDate>
      <link>https://dev.to/iainrough/if-then-elif-else-adventures-in-wsl2-scripting-1-3do1</link>
      <guid>https://dev.to/iainrough/if-then-elif-else-adventures-in-wsl2-scripting-1-3do1</guid>
      <description>&lt;p&gt;First up some basics&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;WSL2 with ubuntu 20.04&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A lot of the logic in the scripts I write rely on bash's &lt;code&gt;if.. then.. else&lt;/code&gt;. The basic syntax of the statement is as follows:&lt;/p&gt;

&lt;blockquote&gt;

&lt;pre&gt; &lt;br&gt;
    if [ {statement} {operator} {value} ]&lt;br&gt;
    then&lt;br&gt;
        # do something here&lt;br&gt;
    elif [ {statement} {operator} {value} ]&lt;br&gt;
        # else if do something&lt;br&gt;
    else&lt;br&gt;
        # do something else&lt;br&gt;
    fi # this is just if spelled backwards.&lt;/pre&gt;
&lt;/blockquote&gt;
The syntax. 







&lt;h2&gt;
  
  
  Why the square brackets?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;[...]&lt;/code&gt; tells bash to evaluate the command and return 0 or 1 for the conditional expression inside the square brackets.&lt;/p&gt;

&lt;blockquote&gt;

&lt;pre&gt;
    test and [ evaluate conditional expressions using a set of 
    rules based on the number of arguments.
&lt;/pre&gt;
source: `man test`. 


&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;tldr;&lt;/strong&gt; ensure things evaluate correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Muting the output
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&amp;gt;&lt;/code&gt; is used to redirect the output of a command somewhere.&lt;/p&gt;

&lt;blockquote&gt;

&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   dev@Dark-Matter:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;file1 file2
   &lt;span class="nb"&gt;cp&lt;/span&gt;: cannot &lt;span class="nb"&gt;stat&lt;/span&gt; &lt;span class="s1"&gt;'file1'&lt;/span&gt;: No such file or directory
   dev@Dark-Matter:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;file1 file2 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;- 2&amp;gt;&amp;amp;-
   dev@Dark-Matter:~&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
Example with and without redirect. 







&lt;h2&gt;
  
  
  Getting exit code from a command
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;$?&lt;/code&gt; returns the success of the previous command, 0 for success and &amp;gt;= 1 for failure. Lets look at the previous example and see what the output is.&lt;/p&gt;

&lt;blockquote&gt;

&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   dev@Dark-Matter:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;file1 file2 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;- 2&amp;gt;&amp;amp;-
   dev@Dark-Matter:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
   1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
Getting the exit code from a command. 







&lt;h2&gt;
  
  
  Simple example
&lt;/h2&gt;

&lt;blockquote&gt;

&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
   &lt;span class="nb"&gt;cp &lt;/span&gt;file1 file2 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;- 2&amp;gt;&amp;amp;-
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
   &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;file1
      &lt;span class="nb"&gt;cp &lt;/span&gt;file1 file2
   &lt;span class="k"&gt;else
     &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"File copied to file 2"&lt;/span&gt; 
   &lt;span class="k"&gt;fi&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
Simple example. 







&lt;h2&gt;
  
  
  Something useful
&lt;/h2&gt;

&lt;blockquote&gt;

&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Check we have a parameter&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then
   &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"syntax: old {filename}"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Copy the file as .old&lt;/span&gt;
&lt;span class="nv"&gt;newFileName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;.old"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$newFileName&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="nv"&gt;$newFileName&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;- 2&amp;gt;&amp;amp;-

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"File has aged and has had '.old' appended to it"&lt;/span&gt;
      &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;else
     &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"File has not been born yet or you do not have parental rights to the file."&lt;/span&gt;
     &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
Simple example. 







</description>
      <category>wsl2</category>
      <category>bash</category>
      <category>windows</category>
      <category>linux</category>
    </item>
    <item>
      <title>Map a Local Folder to a Virtual Drive - Windows 10</title>
      <dc:creator>iainrough</dc:creator>
      <pubDate>Mon, 17 May 2021 08:24:34 +0000</pubDate>
      <link>https://dev.to/iainrough/map-a-local-folder-to-a-drive-letter-windows-10-1b07</link>
      <guid>https://dev.to/iainrough/map-a-local-folder-to-a-drive-letter-windows-10-1b07</guid>
      <description>&lt;h4&gt;
  
  
  The Problem
&lt;/h4&gt;

&lt;p&gt;I ran into a licencing issue with an old ASP.NET Web Forms project. The developer license links to the initial install location. Due to the age of the project, I can no longer update the licence key for the new location. &lt;/p&gt;

&lt;blockquote&gt;

&lt;pre&gt;    d:\projects\{client}\src &lt;/pre&gt;
 The path linked to the license. 


&lt;/blockquote&gt;

&lt;p&gt;So how do I create a location on a drive that my current machine does not have?&lt;/p&gt;

&lt;p&gt;Option 1: Make a new partition on my machine (Not ideal)&lt;/p&gt;

&lt;p&gt;Option 2: Google a different solution.&lt;/p&gt;

&lt;p&gt;Found the following article from 2014: &lt;a href="https://www.computerworld.com/article/2694895/how-to-map-a-local-folder-to-a-drive-letter-in-windows.html"&gt;How to map a local folder to a drive letter in Windows&lt;/a&gt;. It looked simple to implement and not a permanent change. &lt;/p&gt;

&lt;h3&gt;
  
  
  The SUBST command
&lt;/h3&gt;

&lt;pre&gt;
   subst /?
   Associates a path with a drive letter.

   SUBST [drive1: [drive2:]path]
   SUBST drive1: /D

     drive1:        Specifies a virtual drive to which you want to assign a path.
     [drive2:]path  Specifies a physical drive and path you want to assign to
                 a virtual drive.
     /D             Deletes a substituted (virtual) drive.

   Type SUBST with no parameters to display a list of current virtual drives.
&lt;/pre&gt;
The subst help output.






&lt;h4&gt;
  
  
  1. So first things first I needed a root folder to map to.
&lt;/h4&gt;

&lt;blockquote&gt;

&lt;pre&gt; mkdir c:\files\fakeddrive &lt;/pre&gt;
 The fake root folder 


&lt;/blockquote&gt;




&lt;h4&gt;
  
  
  2. Next up duplicate the folder structure:
&lt;/h4&gt;

&lt;blockquote&gt;

&lt;pre&gt; 
    mkdir c:\files\fakeddrive\projects
    mkdir c:\files\fakeddrive\projects\{client}
    mkdir c:\files\fakeddrive\projects\{client}\src
 &lt;/pre&gt;
 Create the path 


&lt;/blockquote&gt;




&lt;h4&gt;
  
  
  3. Next up run &lt;code&gt;subst&lt;/code&gt;
&lt;/h4&gt;

&lt;blockquote&gt;

&lt;pre&gt; 
   subst d: c:\files\fakeddrive
 &lt;/pre&gt;
Run The Command 


&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The results
&lt;/h2&gt;



&lt;pre&gt;
   &amp;gt; subst
   D:\: =&amp;gt; C:\files\fakeddrive
&lt;/pre&gt;

List of current virtual drives.




&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UYqwoWpC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9swx37iu7bomr5hmp8zb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UYqwoWpC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9swx37iu7bomr5hmp8zb.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;There are a couple of things to keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't run as an elevated user.&lt;/li&gt;
&lt;li&gt;The drive does not survive a reboot.&lt;/li&gt;
&lt;li&gt;remove the mapping &lt;code&gt;subst d: /D&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>windows</category>
      <category>map</category>
      <category>subst</category>
    </item>
    <item>
      <title>Send Slack Notification via InvokeRESTAPI@1 - Azure DevOps Tricks #2</title>
      <dc:creator>iainrough</dc:creator>
      <pubDate>Sun, 16 May 2021 06:08:00 +0000</pubDate>
      <link>https://dev.to/iainrough/send-slack-notification-via-invokerestapi-1-azure-devops-tricks-2-415n</link>
      <guid>https://dev.to/iainrough/send-slack-notification-via-invokerestapi-1-azure-devops-tricks-2-415n</guid>
      <description>&lt;p&gt;Need to send a slack notification from an Azure DevOps pipeline? The InvokeRESTAPI@1 task is one of the most versatile and useful in Azure DevOps. It handles sending messages to Slack in a couple of lines of YAML.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    - task: InvokeRESTAPI@1
      displayName: Slack
      inputs:
        connectionType: 'connectedServiceName'
        serviceConnection: 'Slack'
        method: 'POST'
        body: $body
        urlSuffix: $urlSuffix
        waitForCompletion: 'false'

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
 The finshed YAML Task





&lt;h2&gt;
  
  
  The Service Connection
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Project Settings &amp;gt; Pipelines &amp;gt; Service connections&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The service connection is where we define the URL we are going to post to. For this we will use the &lt;a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&amp;amp;tabs=yaml#sep-generic" rel="noopener noreferrer"&gt;Generic Service Connection&lt;/a&gt;. You navigate to &lt;em&gt;Project Settings &amp;gt; Pipelines &amp;gt; Service connections&lt;/em&gt; or append this string after your project name in the URL &lt;code&gt;_settings/adminservices&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5vdgnspxfq061d4ekwt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5vdgnspxfq061d4ekwt.png"&gt;&lt;/a&gt;&lt;/p&gt;
 Create a Generic Service Connection






&lt;h3&gt;
  
  
  The fields we need to fill:
&lt;/h3&gt;

&lt;p&gt;Server URL: &lt;a href="https://hooks.slack.com/services/" rel="noopener noreferrer"&gt;https://hooks.slack.com/services/&lt;/a&gt;&lt;br&gt;
Service Connection Name: Slack&lt;br&gt;
Description: A Generic Slack Service connection.&lt;/p&gt;




&lt;h3&gt;
  
  
  The other Variables in the task
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;$body:&lt;/strong&gt; You can either generate this variable or Input the body inline. Here is an example body:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
{
   "attachments":[
      {
         "mrkdwn_in":[
            "text"
         ],
         "color":"#36a64f",
         "pretext":"New Deployment",
         "title":"$(Pipeline.WebSiteName) deployed",
         "title_link":"$(Pipeline.WebSiteName)",
         "fields":[
            {
               "title":"Version",
               "value":"$(CurrentRelease)",
               "short":true
            },
            {
               "title":"Release Notes",
               "value":"&amp;amp;lt;$(Pipeline.WebSiteAddress)/ReleaseNotes/$(PullId)&amp;amp;gt;",
               "short":true
            },
            {
               "title":"Trigger",
               "value":"Pull Request",
               "short":true
            }
         ]
      }
   ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
 Example Slack Body


&lt;p&gt;So here you can see we are passing variables like the &lt;strong&gt;PullId&lt;/strong&gt; and using them in the Slack Message. The ability to use any of the variables in the pipeline allows for detailed Slack Messages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;$urlSuffix&lt;/strong&gt;: &lt;code&gt;T778W530Z/B021W918BNH/HQIPtyCfACfs5WVXg1w7b4Xk&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is the magic bit for Slack, I would recommend storing this value as &lt;strong&gt;secret&lt;/strong&gt; or getting it from your Azure Key Vault.&lt;/p&gt;

&lt;p&gt;Simple Quick and Easy.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>azure</category>
      <category>slack</category>
    </item>
    <item>
      <title>Change PowerShell Version used in PowerShell@2 - Azure DevOps Tricks #1</title>
      <dc:creator>iainrough</dc:creator>
      <pubDate>Wed, 12 May 2021 14:45:32 +0000</pubDate>
      <link>https://dev.to/iainrough/change-powershell-version-used-in-powershell-2-azure-devops-tricks-1-56hm</link>
      <guid>https://dev.to/iainrough/change-powershell-version-used-in-powershell-2-azure-devops-tricks-1-56hm</guid>
      <description>&lt;p&gt;Ran into a pipeline issue when using &lt;code&gt;ConvertFrom-Json -Depth 20&lt;/code&gt; to load a JSON file in a &lt;code&gt;PowerShell@2&lt;/code&gt; task in a DevOps pipeline. The &lt;code&gt;-Depth&lt;/code&gt; parameter was throwing an error: &lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;ConvertFrom-Json : A parameter cannot be found that matches parameter name 'Depth'&lt;/pre&gt;
Error message

&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What the ConvertFrom-Json docs say?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertfrom-json?view=powershell-5.1"&gt;PowerShell 5.1&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Doesn't list a parameter &lt;code&gt;-Depth&lt;/code&gt;. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertfrom-json?view=powershell-7"&gt;PowerShell 7 (LTS)&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-Depth&lt;/code&gt;: Gets or sets the maximum depth the JSON input is allowed to have. By default, it is 1024. This parameter was introduced in PowerShell 6.2.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What version of PowerShell is &lt;code&gt;PowerShell@2&lt;/code&gt; using?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;note: this may differ depending on the Agent that is running the task.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I added a line to the script to get the version:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;   Write-Host "Version: ($PSVersionTable.PSVersion)"&lt;/pre&gt;
Extra line to show PowerShell version 
&lt;/blockquote&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;   Version: 5.1.17763.1852&lt;/pre&gt;
PowerShell Version running on the Agent

&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How do we change the version?
&lt;/h2&gt;

&lt;p&gt;This little snippet allows a script defined in a &lt;code&gt;PowerShell@2&lt;/code&gt; task to relaunch in a specific version of PowerShell. &lt;/p&gt;

&lt;blockquote&gt;

&lt;pre&gt;
    if ($PSVersionTable.PSVersion -lt [Version]"7.0") {
        Write-Host "Version: $($PSVersionTable.PSVersion)"
        Write-Host "Re-launching as pwsh"
        pwsh -File $MyInvocation.MyCommand.Definition
        exit
    }
&lt;/pre&gt;
 From &lt;a href="https://stackoverflow.com/a/31197015"&gt;StackOverflow&lt;/a&gt;.

&lt;/blockquote&gt;

&lt;p&gt;Some other options if you want a specific version.&lt;/p&gt;

&lt;blockquote&gt;

&lt;pre&gt;
    powershell -Version 2 -File $MyInvocation.MyCommand.Definition
&lt;/pre&gt;
Specify a specific version of powershell

&lt;/blockquote&gt;

</description>
      <category>devops</category>
      <category>azure</category>
      <category>powershell</category>
    </item>
    <item>
      <title>Decode TOTP(Time-based One-time Password) QR Code</title>
      <dc:creator>iainrough</dc:creator>
      <pubDate>Tue, 11 May 2021 12:34:33 +0000</pubDate>
      <link>https://dev.to/iainrough/decode-totp-time-based-one-time-password-qr-code-3ed6</link>
      <guid>https://dev.to/iainrough/decode-totp-time-based-one-time-password-qr-code-3ed6</guid>
      <description>&lt;h1&gt;
  
  
  How not to do this.
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fspaq45zmivvy3f0q8m8y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fspaq45zmivvy3f0q8m8y.png" alt="Trulli"&gt;&lt;/a&gt;&lt;br&gt;DO NOT USE AN ONLINE SERVICE
  &lt;/p&gt;

&lt;p&gt;While an online service such as &lt;a href="https://webqr.com/" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://webqr.com/" rel="noopener noreferrer"&gt;https://webqr.com/&lt;/a&gt; or &lt;a href="https://www.qrstuff.com/scan" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://www.qrstuff.com/scan" rel="noopener noreferrer"&gt;https://www.qrstuff.com/scan&lt;/a&gt; are fine for normal QR codes they should never be used for TOTP QR Codes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What inside the QR CODE
&lt;/h2&gt;

&lt;p&gt;A TOTP QR code contains the following details (all values are placeholders).&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;

     Hex secret: 3132333435363738393031323334353637383930
     Base32 secret: GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ
     Digits: 8
     Window size: 0
     TOTP mode: SHA1
     Step size (seconds): 30
     Start time: 1970-01-01 00:00:00 UTC (0)
     Time now: 2033-05-18 03:33:20 UTC (2000000000)
     Counter: 0x3F940AA (66666666)

&lt;/pre&gt;

&lt;p&gt;Information from: &lt;a href="https://www.nongnu.org/oath-toolkit/oathtool.1.html" rel="noopener noreferrer"&gt;oathtool&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more information visit &lt;a href="https://www.nongnu.org/oath-toolkit/oathtool.1.html" rel="noopener noreferrer"&gt;oathtool&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Decode QR code locally
&lt;/h1&gt;




&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Mac
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 install zbar

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Windows(WSL), Linux
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 apt-get install zbarimg

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

/mnt/c/Users/rough&lt;span class="nv"&gt;$ &lt;/span&gt;zbarimg /mnt/c/tmp/a.png
otpauth://totp/hub.docker.com:&lt;span class="o"&gt;{&lt;/span&gt;username&lt;span class="o"&gt;}&lt;/span&gt;?algorithm&lt;span class="o"&gt;=&lt;/span&gt;SHA1&amp;amp;digits&lt;span class="o"&gt;=&lt;/span&gt;6&amp;amp;issuer&lt;span class="o"&gt;=&lt;/span&gt;hub.docker.com&amp;amp;period&lt;span class="o"&gt;=&lt;/span&gt;30&amp;amp;secret&lt;span class="o"&gt;={&lt;/span&gt;Key&lt;span class="o"&gt;}&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can now store the OTPAUTH URI in your favorite password manager or add the {Key} so that your password manager can generate the TOPT code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8x8cv4i6ukhnc5n3s98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8x8cv4i6ukhnc5n3s98.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/iainrough/bad-ux-lastpass-password-dialog-4lfj"&gt;How to add your TOPT key to LastPass&lt;/a&gt;&lt;/p&gt;

</description>
      <category>totp</category>
      <category>security</category>
      <category>qrcode</category>
    </item>
  </channel>
</rss>
