<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>visual studio Archives - Blog IT</title>
	<atom:link href="https://blogit.create.pt/tag/visual-studio/feed/" rel="self" type="application/rss+xml" />
	<link>https://blogit.create.pt/tag/visual-studio/</link>
	<description>Create IT blogger community</description>
	<lastBuildDate>Thu, 10 Jan 2019 12:46:20 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>
	<item>
		<title>git-askpass.exe: No such file or directory. Visual Studio</title>
		<link>https://blogit.create.pt/ricardocosta/2018/09/06/git-askpass-no-such-file-visual-studio/</link>
					<comments>https://blogit.create.pt/ricardocosta/2018/09/06/git-askpass-no-such-file-visual-studio/#respond</comments>
		
		<dc:creator><![CDATA[Ricardo Costa]]></dc:creator>
		<pubDate>Thu, 06 Sep 2018 12:57:44 +0000</pubDate>
				<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[BitBucket]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[visual studio]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=7432</guid>

					<description><![CDATA[<p>I was getting an error when I tried to sync to my Git BitBucket repository with Visual Studio 2017: git-askpass.exe: No such file or directory. To resolve this I had to: Remove Git from Control Panel -&#62; Uninstall Remove Git Windows Credential Manager from Control Panel -&#62; Uninstall With Visual Studio 2017 Installer, remove Git [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/ricardocosta/2018/09/06/git-askpass-no-such-file-visual-studio/">git-askpass.exe: No such file or directory. Visual Studio</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I was getting an error when I tried to sync to my Git BitBucket repository with Visual Studio 2017:</p>
<p><em>git-askpass.exe: No such file or directory.</em></p>
<p>To resolve this I had to:</p>
<ol>
<li>Remove Git from Control Panel -&gt; Uninstall</li>
<li>Remove Git Windows Credential Manager from Control Panel -&gt; Uninstall</li>
<li>With Visual Studio 2017 Installer, remove Git for Windows</li>
<li>Install Git</li>
<li>Install Git Windows Credential Manager</li>
<li>With Visual Studio 2017 Installer, install Git for Windows</li>
</ol>
<p>The post <a href="https://blogit.create.pt/ricardocosta/2018/09/06/git-askpass-no-such-file-visual-studio/">git-askpass.exe: No such file or directory. Visual Studio</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/ricardocosta/2018/09/06/git-askpass-no-such-file-visual-studio/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to add your custom content files into a nuget package (for Visual Studio)</title>
		<link>https://blogit.create.pt/gustavobrito/2018/01/12/how-to-add-your-custom-content-files-into-a-nuget-package-for-visual-studio/</link>
					<comments>https://blogit.create.pt/gustavobrito/2018/01/12/how-to-add-your-custom-content-files-into-a-nuget-package-for-visual-studio/#comments</comments>
		
		<dc:creator><![CDATA[Gustavo Brito]]></dc:creator>
		<pubDate>Fri, 12 Jan 2018 15:49:08 +0000</pubDate>
				<category><![CDATA[Nuget]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[$rootnamespace$]]></category>
		<category><![CDATA[add files]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[cml]]></category>
		<category><![CDATA[content]]></category>
		<category><![CDATA[contentFiles]]></category>
		<category><![CDATA[custom]]></category>
		<category><![CDATA[customfiles]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[external]]></category>
		<category><![CDATA[external files]]></category>
		<category><![CDATA[nupkg]]></category>
		<category><![CDATA[nuspec]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[packaging]]></category>
		<category><![CDATA[pp]]></category>
		<category><![CDATA[targets]]></category>
		<category><![CDATA[transform]]></category>
		<category><![CDATA[visual studio]]></category>
		<category><![CDATA[visual studio nuget]]></category>
		<category><![CDATA[xdt]]></category>
		<category><![CDATA[XML]]></category>
		<guid isPermaLink="false">http://blogit.create.pt/gustavobrito/?p=1214</guid>

					<description><![CDATA[<p>Yesterday, I was assigned to fix a nuget package solution that was not packing all the needed files. I had a bad time searching online for answers, and had to dig in by myself. After I discovered how to include the files that I needed, I decided to create a simple tutorial that has it [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/gustavobrito/2018/01/12/how-to-add-your-custom-content-files-into-a-nuget-package-for-visual-studio/">How to add your custom content files into a nuget package (for Visual Studio)</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Yesterday, I was assigned to fix a nuget package solution that was not packing all the needed files. I had a bad time searching online for answers, and had to dig in by myself. After I discovered how to include the files that I needed, I decided to create a simple tutorial that has it all!</p>
<p>This tutorial will show you how to include your non-compilable items into a nuget package (nupkg). This steps apply to any type of file.</p>
<p><span id="more-1214"></span></p>
<p><strong>DISCLAIMER: You must have a nuspec file and a targets file. If you don&#8217;t have one yet, download one from somewhere and change the metadata accordingly.</strong></p>
<p><strong>Let&#8217;s start!</strong></p>
<ol>
<li>Open up your solution in Visual Studio</li>
<li>Open your solution&#8217;s nuspec file and look for <strong>&lt;files&gt;</strong> tag</li>
<li>You need to reference <strong>all folders and all files</strong> that you want to include in your nuget. Example below:</li>
</ol>
<blockquote>
<pre class="brush: xml; title: ; notranslate">
&lt;files&gt;
    &lt;file src=&quot;lib\net452\your_compiled_assembly.dll&quot; target=&quot;lib\net452&quot; /&gt;
    &lt;file src=&quot;Your_Folder\*.pp&quot; target=&quot;content\Your_Folder&quot;/&gt;
    &lt;file src=&quot;Your_Folder\Your_Sub_Folder\*.*&quot; target=&quot;content&quot; /&gt;
    &lt;file src=&quot;*.xdt&quot; target=&quot;content&quot; /&gt;
 &lt;/files&gt;
</pre>
</blockquote>
<p>4.  After you added all files into nuspec config, now you can open your targets file. Don&#8217;t forget to import targets into your csproj file like the example below</p>
<pre class="brush: xml; title: ; notranslate">
&lt;Import Project=&quot;your_targets_file.targets&quot; Condition=&quot;Exists('your_targets_file.targets')&quot; /&gt;
</pre>
<p>5. Now to targets file, you must index <strong>ALL </strong>files that you want to add to your nuget. <strong>This step is very important</strong></p>
<div>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;Project ToolsVersion=&quot;14.0&quot; DefaultTargets=&quot;Build&quot; xmlns=&quot;http://schemas.microsoft.com/developer/msbuild/2003&quot;&gt;
 &lt;TargetName=&quot;CreatePackage&quot;&gt;
   &lt;PropertyGroup&gt;
   &lt;Configuration&gt;Release&lt;/Configuration&gt;
   &lt;PackageSource&gt;bin\$(Configuration)\Package&lt;/PackageSource&gt;
   &lt;NuSpecPath&gt;$(MSBuildProjectName).nuspec&lt;/NuSpecPath&gt;
   &lt;/PropertyGroup&gt;
   &lt;RemoveDirDirectories=&quot;$(PackageSource)&quot;/&gt;
   &lt;MSBuildProjects=&quot;$(MSBuildProjectFullPath)&quot; Targets=&quot;Rebuild&quot;Properties=&quot; TargetFrameworkVersion=v4.0; OutputPath=bin\$(Configuration)\net40;Configuration=$(Configuration)&quot; BuildInParallel=&quot;$(BuildInParallel)&quot;/&gt;


   &lt;Copy SourceFiles=&quot;bin\$(Configuration)\net40\$(AssemblyName).dll&quot; DestinationFolder=&quot;$(PackageSource)\lib\net40&quot;/&gt;
   &lt;Copy SourceFiles=&quot;$(NuSpecPath)&quot; DestinationFolder=&quot;$(PackageSource)&quot;/&gt;
   &lt;Copy SourceFiles=&quot;Your_Folder\Your_Class_File.cs.pp&quot; DestinationFolder=&quot;$(PackageSource)\Your_Folder&quot;/&gt;
   &lt;Copy SourceFiles=&quot;Your_Folder\Yet_Another_Class.cs.pp&quot; DestinationFolder=&quot;$(PackageSource)\Your_Folder&quot;/&gt;
   &lt;Copy SourceFiles=&quot;Your_Folder\Your_Sub_Folder\A_Class.cs.pp&quot; DestinationFolder=&quot;$(PackageSource)\Your_Folder\Your_Sub_Folder&quot;/&gt;
   &lt;Copy SourceFiles=&quot;Your_Images_Folder\Your_Image.jpeg&quot; DestinationFolder=&quot;$(PackageSource)\Your_Images_Folder&quot;/&gt;
   &lt;Copy SourceFiles=&quot;Your_root_file.xml&quot; DestinationFolder=&quot;$(PackageSource)&quot;/&gt;
 &lt;/Target&gt;
&lt;/Project&gt;
</pre>
</div>
<p>6. After you added all your source files into your targets file, you are ready to pack it!!</p>
<p><strong>File extensions for Transformations and generated classes:</strong></p>
<ol>
<li>A <strong>pp </strong>file extension is a class that&#8217;s generated when a nuget is installed in any solution. Usually, the class namespace is replaced by &#8220;<strong>$rootnamespace$&#8221;</strong> (without quotes) and the extension is added (yourclass.cs<strong>.pp</strong>)</li>
<li>A <strong>xdt </strong>file extension is a <a href="https://msdn.microsoft.com/en-us/library/dd465326(v=vs.110).aspx">XML Transformation procedure</a>.</li>
</ol>
<p>Example of a <strong>*.pp </strong>class ready to be packed into a nuget:</p>
<pre class="brush: csharp; title: ; notranslate">
namespace $rootnamespace$.App_Start
{
 using System;
 using System.Collections.Generic;
 using System.Configuration;
 using System.Linq;
...
}
</pre>
<p>That&#8217;s all folks!</p>
<p>The post <a href="https://blogit.create.pt/gustavobrito/2018/01/12/how-to-add-your-custom-content-files-into-a-nuget-package-for-visual-studio/">How to add your custom content files into a nuget package (for Visual Studio)</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/gustavobrito/2018/01/12/how-to-add-your-custom-content-files-into-a-nuget-package-for-visual-studio/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
		<item>
		<title>Remote resource handling in a MVC website project</title>
		<link>https://blogit.create.pt/andresantos/2016/04/15/remote-resource-handling-in-a-mvc-website-project/</link>
					<comments>https://blogit.create.pt/andresantos/2016/04/15/remote-resource-handling-in-a-mvc-website-project/#comments</comments>
		
		<dc:creator><![CDATA[André Santos]]></dc:creator>
		<pubDate>Fri, 15 Apr 2016 18:01:43 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[action filter]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[mvc 5]]></category>
		<category><![CDATA[resources]]></category>
		<category><![CDATA[resx]]></category>
		<category><![CDATA[viewmodel]]></category>
		<category><![CDATA[visual studio]]></category>
		<category><![CDATA[webapi]]></category>
		<guid isPermaLink="false">http://blogit.create.pt/andresantos/?p=1381</guid>

					<description><![CDATA[<p>I don&#8217;t have very fond memories of using .Net resource files (.resx) to handle the translation of static web page elements such as form labels. The Visual Studio resx editor was slow and using it to change resources that were more than a single line of text was a pain. I still have nightmares where [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2016/04/15/remote-resource-handling-in-a-mvc-website-project/">Remote resource handling in a MVC website project</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I don&#8217;t have very fond memories of using .Net resource files (.resx) to handle the translation of static web page elements such as form labels.</p>
<p>The Visual Studio <em>resx</em> editor was slow and using it to change resources that were more than a single line of text was a pain. I still have nightmares where I&#8217;m trying to edit complete email templates on a single field of a <em>resx</em> file&#8230;</p>
<p>The biggest problem with resource files, however, is that they are included in the project. This creates a problem for both the developers and the content managers, since the content managers are not able to change resources themselves, and the developers need to be changing resources files when they could be doing something productive.</p>
<p>The following will show a way to handle resource items in a MVC website project, where the resources can be stored wherever they are more easily handled by content managers: a SharePoint list, a database table, an excel file, or something completely different.</p>
<p><span id="more-6480"></span></p>
<p>The process is really simple:</p>
<ol>
<li>Select every resource item key needed to render the current page</li>
<li>Fetch the resources associated with the keys provided at the end of the current action</li>
<li>Populate a ViewModel property with the resource items</li>
<li>Use the resource items in their respective places in the markup</li>
</ol>
<h3>1 &#8211; Compile a list of resource keys</h3>
<p>Typically in a website, there are certain areas of the layout that are common across all pages, the header and the footer being the most prominent candidates. There are, however, other areas that can be reused across a smaller subset of pages such as a common banner in the FAQ pages. Taking this into account, we split the resource keys by groups, where each group (a list of strings) contains every resource key needed for that area and load them on each action, like so:</p>
<pre class="brush: csharp; title: Area resource keys; notranslate">
model.ContentResourceKeys = new List&amp;lt;string&amp;gt;();
model.ContentResourceKeys.AddRange(ResourceHelper.SOCIALNETWORK_RESOURCE_KEYS);
model.ContentResourceKeys.AddRange(ResourceHelper.HOTEL_BANNER_RESOURCE_KEYS);
model.ContentResourceKeys.AddRange(ResourceHelper.DOCUMENTS_RESOURCE_KEYS);
model.ContentResourceKeys.AddRange(ResourceHelper.GENERAL_FOOTER_BANNERS_RESOURCE_KEYS);
model.ContentResourceKeys.AddRange(ResourceHelper.LANDING_PAGE_SEARCH_AREA_RESOURCE_KEYS);
model.ContentResourceKeys.AddRange(ResourceHelper.LANDING_PAGE_MODULES_RESOURCE_KEYS);
</pre>
<p>The ContentResourceKeys property is defined in a <em>MasterModel</em> that is extended by every View Model used across the site, as can be seen here: <a href="http://blogit.create.pt/andresantos/2014/11/07/pre-set-common-viewmodel-preperties-before-action-result/">http://blogit.create.pt/andresantos/2014/11/07/pre-set-common-viewmodel-preperties-before-action-result/</a>. That post also describes the Action Filter that is executed after every action on the site and it&#8217;s the place where we append the footer and header resources to the <strong>ContentResourceKeys</strong> list:</p>
<pre class="brush: csharp; title: Master resouce keys; notranslate">
List&amp;lt;string&amp;gt; resourceKeys = new List&amp;lt;string&amp;gt;();
resourceKeys.AddRange(ResourceHelper.HEADER_RESOURCE_KEYS.ToList());
resourceKeys.AddRange(ResourceHelper.LOGIN_RESOURCE_KEYS.ToList());
resourceKeys.AddRange(ResourceHelper.FOOTER_RESOURCE_KEYS.ToList());
resourceKeys.AddRange(ResourceHelper.LOADING_RESOURCE_KEYS.ToList());
resourceKeys.AddRange(ResourceHelper.HEADER_COOKIES_RESOURCE_KEYS.ToList());

if (model.ContentResourceKeys != null &amp;amp;&amp;amp; model.ContentResourceKeys.Count &amp;gt; 0)
{
    resourceKeys.AddRange(model.ContentResourceKeys);
}
</pre>
<h3>2 &#8211; Fetch the resources</h3>
<p>After compiling the resource keys needed, we go on and fetch the associated resource items. The project where this was implemented used a WebAPI to serve all the page content and the resource items were no exception. So, we send a POST request to the resource WebAPI method and fetch the needed resources, for the user language, from the available backoffice (we used a SharePoint list).</p>
<pre class="brush: csharp; title: Fetch the keys; notranslate">
model.Resources.AddRange(ResourceFacade.ListResources(model.CurrentLanguageCode, resourceKeys));
</pre>
<h3>3 &#8211; Add them to the View Model</h3>
<p>The <em>Resources</em> property available in the View Model where we added the result of the call to the resources WebAPI method is a string Dictionary. Since C# Dictionaries don&#8217;t provide an <em>AddRange</em> method, we create an extension method that enables us to append resources to a dictionary that&#8217;s not empty. Moreover, with this extension method we are able to scrap duplicate keys:</p>
<pre class="brush: csharp; title: Dictionary AddRange extension method; notranslate">
public static class IDictionaryExtensions
{
    public static void AddRange&amp;lt;T, S&amp;gt;(this IDictionary&amp;lt;T, S&amp;gt; source, IDictionary&amp;lt;T, S&amp;gt; collection)
    {
        if (collection == null)
        {
            throw new ArgumentNullException(&quot;Collection is null&quot;);
        }

        foreach (var item in collection)
        {
            if (!source.ContainsKey(item.Key))
            {
                source.Add(item.Key, item.Value);
            }
        }
    }
}
</pre>
<h3>4 &#8211; Use the resources in the views</h3>
<p>Since every View Model extends the MasterModel, we are able to use the same property everywhere:</p>
<pre class="brush: xml; title: Usage in the view; notranslate">
&amp;lt;footer id=&quot;footer&quot;&amp;gt;
  &amp;lt;div class=&quot;container&quot;&amp;gt;
    &amp;lt;div class=&quot;newsletter&quot;&amp;gt;
      &amp;lt;h2&amp;gt;@Model.Resources&#x5B;&quot;Footer.Newsletter.Title&quot;]&amp;lt;/h2&amp;gt;
</pre>
<p>This way, we are able to manage the resource keys in a SharePoint list, or any other backoffice solution.</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2016/04/15/remote-resource-handling-in-a-mvc-website-project/">Remote resource handling in a MVC website project</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/andresantos/2016/04/15/remote-resource-handling-in-a-mvc-website-project/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Automatic generation of Umbraco packages with Grunt</title>
		<link>https://blogit.create.pt/andresantos/2016/03/07/automatic-generation-of-umbraco-packages-with-grunt/</link>
					<comments>https://blogit.create.pt/andresantos/2016/03/07/automatic-generation-of-umbraco-packages-with-grunt/#comments</comments>
		
		<dc:creator><![CDATA[André Santos]]></dc:creator>
		<pubDate>Mon, 07 Mar 2016 16:03:50 +0000</pubDate>
				<category><![CDATA[Umbraco]]></category>
		<category><![CDATA[automatization]]></category>
		<category><![CDATA[Backoffice extension]]></category>
		<category><![CDATA[grunt]]></category>
		<category><![CDATA[npm]]></category>
		<category><![CDATA[NPM Scripts Task Runner]]></category>
		<category><![CDATA[package]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Section]]></category>
		<category><![CDATA[visual studio]]></category>
		<guid isPermaLink="false">http://blogit.create.pt/andresantos/?p=1161</guid>

					<description><![CDATA[<p>Manually creating Umbraco packages can be tiresome. If you&#8217;re continuously building upon the same package, doing it manually is wasting time that can be more useful developing new features. This problem presented itself to me when improving Approve It. In order to create the Umbraco package I need several things: The main assembly The new dashboard [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/andresantos/2016/03/07/automatic-generation-of-umbraco-packages-with-grunt/">Automatic generation of Umbraco packages with Grunt</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Manually creating Umbraco packages can be tiresome.</p>
<p>If you&#8217;re continuously building upon the same package, doing it manually is wasting time that can be more useful developing new features.</p>
<p>This problem presented itself to me when improving <a href="https://our.umbraco.org/projects/backoffice-extensions/approve-it/" target="_blank" rel="noopener">Approve It</a>. In order to create the Umbraco package I need several things:</p>
<ul>
<li>The main assembly</li>
<li>The new dashboard section html file</li>
<li>The App_Plugins folder which contains every angular controller and views, javascript frameworks and custom css</li>
<li>The <a href="http://packageactioncontrib.codeplex.com/" target="_blank" rel="noopener">Package Actions Contrib</a> assembly and its respective actions that enable me to bundle some translations in the package</li>
</ul>
<p>I decided to go with <a href="http://gruntjs.com/getting-started" target="_blank" rel="noopener">Grunt</a> and the <a href="https://www.npmjs.com/package/grunt-umbraco-package" target="_blank" rel="noopener">Grunt Umbraco Package</a> task. A grunt file is a script that typically automates the process of executing some tasks. These scripts can be executed on top of <a href="https://www.npmjs.com/" target="_blank" rel="noopener">NPM</a>, a package manager for javscript that provides a command line tool to run its packages. To streamline even more the package creation, I installed a Visual Studio extension called <a href="https://visualstudiogallery.msdn.microsoft.com/8f2f2cbc-4da5-43ba-9de2-c9d08ade4941" target="_blank" rel="noopener">NPM Scripts Task Runner</a>, that detects the grunt file and provides a simples UI to handle its tasks.</p>
<p><span id="more-6479"></span></p>
<h3>Step 1 &#8211; Install NPM</h3>
<p>With NPM installed we are able to execute a Grunt file.</p>
<h3>Step 2 &#8211; Install NPM Scripts Task Runner</h3>
<p>The Visual Studio extension:</p>
<figure id="attachment_1241" aria-describedby="caption-attachment-1241" style="width: 471px" class="wp-caption alignnone"><a href="http://blogit-create.com/wp-content/uploads/2016/03/npmscriptsvs.png" rel="attachment wp-att-1241"><img fetchpriority="high" decoding="async" class="wp-image-1241 size-full" src="http://blogit-create.com/wp-content/uploads/2016/03/npmscriptsvs.png" alt="NPM Scripts Task Runner Visual Studio extension" width="471" height="235" /></a><figcaption id="caption-attachment-1241" class="wp-caption-text">NPM Scripts Task Runner Visual Studio extension</figcaption></figure>
<h3>Step 3 &#8211; Create a Grunt file</h3>
<p>And place it in your project:</p>
<pre class="brush: jscript; title: Gruntfile.js; notranslate">
module.exports = function (grunt) {

    // Setup
    var pkg = grunt.file.readJSON('package.json');
    var projectRoot = 'C:/path/to/project/ApproveIt/';
    var packageNamespace = &quot;Create.Plugin&quot;;

    // Grunt Configuration
    grunt.initConfig({
        pkg: pkg,
        clean: {
            files: &#x5B;
                'bld/App_Plugins',
                'bld/bin',
                'bld/Umbraco'
            ]
        },
        copy: {
            release: {
                files: &#x5B;
                    {
                        expand: true,
                        cwd: projectRoot + 'bin/',
                        src: &#x5B;
                            packageNamespace + '.' + pkg.name + '.dll',
                            'PackageActionsContrib.dll'
                        ],
                        dest: 'bld/bin/'
                    },
                    {
                        expand: true,
                        cwd: projectRoot + 'App_Plugins/',
                        src: &#x5B;'**'],
                        dest: 'bld/App_Plugins/'
                    },
                    {
                        expand: true,
                        cwd: projectRoot + 'Dashboard/Views/dashboard/approveIt/',
                        src: &#x5B;'approveItdashboardintro.html'],
                        dest: &quot;bld/Umbraco/Views/dashboard/approveIt/&quot;
                    }
                ]
            }
        },
        umbracoPackage: {
            release: {
                src: 'bld/',
                dest: 'bin/umbraco',
                options: {
                    name: pkg.name,
                    version: pkg.version,
                    url: pkg.url,
                    license: pkg.license.name,
                    licenseUrl: pkg.license.url,
                    author: pkg.author.name,
                    authorUrl: pkg.author.url,
                    readme: pkg.readme,
                    outputName: pkg.name + '.v' + pkg.version + '.zip',
                    manifest: 'package.xml'
                }
            }
        }
    });

    // Loading of Grunt Tasks
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-umbraco-package');
};
</pre>
<p>This file has three sections, which I&#8217;ll explain in a different order:</p>
<ol>
<li>Setup</li>
<li>Grunt configuration</li>
<li>Loading of grunt tasks</li>
</ol>
<h4>Loading of Grunt Tasks</h4>
<p>Most actions we need a grunt file to execute are simplified by the use of existing Grunt tasks. In my case, I only need 3:</p>
<ol>
<li><em>grunt-contrib-clean</em>: deletes files and folders</li>
<li><em>grunt-contrib-copy</em>: copies files and folders</li>
<li><em>grunt-umbraco-package</em>: generates an umbraco package</li>
</ol>
<h4>Grunt File Setup</h4>
<p>Here I define a set of variables and load an external configuration file that contains project properties I use later on:</p>
<pre class="brush: jscript; title: package.json; notranslate">
{
  &quot;author&quot;: {
    &quot;name&quot;: &quot;André Santos&quot;,
    &quot;url&quot;: &quot;http://www.create.pt&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;grunt&quot;: &quot;~0.4.5&quot;,
    &quot;grunt-contrib-clean&quot;: &quot;^0.6.0&quot;,
    &quot;grunt-contrib-copy&quot;: &quot;~0.4.1&quot;,
    &quot;grunt-umbraco-package&quot;: &quot;1.0.0&quot;
  },
  &quot;license&quot;: {
    &quot;name&quot;: &quot;MIT&quot;,
    &quot;url&quot;: &quot;http://opensource.org/licenses/MIT&quot;
  },
  &quot;name&quot;: &quot;ApproveIt&quot;,
  &quot;readme&quot;: &quot;Umbraco Plugin that creates a section that shows all the content that is waiting approval for publishing.&quot;,
  &quot;url&quot;: &quot;https://our.umbraco.org/projects/backoffice-extensions/approve-it/&quot;,
  &quot;version&quot;: &quot;1.0.1&quot;
}
</pre>
<h4>Grunt Configuration</h4>
<p>This section is where everything comes together. The <em>package.json</em> configuration file is loaded and the three aforementioned grunt tasks are implemented:</p>
<h5>Clean</h5>
<p>In here, the directories used as the source for the umbraco package creation, are configured so that when we can empty them at will</p>
<h5>Copy</h5>
<p>This task copies every file needed by the plugin to a centralized location, creating a snapshot of our plugin. We copy full directories and hand picked files as needed.</p>
<h5>Umbraco Package</h5>
<p>Finally, this task picks up every file we have copied and creates the final Umbraco package. It uses the configuration properties set in <em>package.json</em> and uses a custom <em>package.xml</em> file so that I can include my custom post umbraco package install actions (using Package Actions Contrib):</p>
<pre class="brush: xml; title: package.xml; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;
&lt;umbPackage&gt;
  &lt;info&gt;
    &lt;package&gt;
      &lt;name&gt;&lt;%= name %&gt;&lt;/name&gt;
      &lt;version&gt;&lt;%= version %&gt;&lt;/version&gt;
      &lt;license url=&quot;&lt;%= licenseUrl %&gt;&quot;&gt;&lt;%= license %&gt;&lt;/license&gt;
      &lt;url&gt;&lt;%= url %&gt;&lt;/url&gt;
      &lt;requirements&gt;
        &lt;major&gt;3&lt;/major&gt;
        &lt;minor&gt;0&lt;/minor&gt;
        &lt;patch&gt;0&lt;/patch&gt;
      &lt;/requirements&gt;
    &lt;/package&gt;
    &lt;author&gt;
      &lt;name&gt;&lt;%= author %&gt;&lt;/name&gt;
      &lt;website&gt;&lt;%= authorUrl %&gt;&lt;/website&gt;
    &lt;/author&gt;
    &lt;readme&gt;&lt;!&#x5B;CDATA&#x5B;&lt;%= readme %&gt;]]&gt;&lt;/readme&gt;
  &lt;/info&gt;
  &lt;DocumentTypes /&gt;
  &lt;Templates /&gt;
  &lt;Stylesheets /&gt;
  &lt;Macros /&gt;
  &lt;DictionaryItems /&gt;
  &lt;Languages /&gt;
  &lt;DataTypes /&gt;
  &lt;control /&gt;
  &lt;Actions&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;addDashboardSection&quot; dashboardAlias=&quot;StartupApproveItDashboardSection&quot;&gt;
      &lt;section&gt;
        &lt;areas&gt;
          &lt;area&gt;approveIt&lt;/area&gt;
        &lt;/areas&gt;
        &lt;tab caption=&quot;Get Started&quot;&gt;
          &lt;control showOnce=&quot;true&quot; addPanel=&quot;true&quot; panelCaption=&quot;&quot;&gt;
            views/dashboard/approveIt/approveItdashboardintro.html
          &lt;/control&gt;
        &lt;/tab&gt;
      &lt;/section&gt;
    &lt;/Action&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;en&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;pt&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;cs&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;da&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;en_us&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;es&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;fr&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;he&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;it&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;ja&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;ko&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;nl&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;no&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;pl&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;ru&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;sv&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;zh&quot; position=&quot;end&quot; area=&quot;sections&quot; key=&quot;approveIt&quot; value=&quot;Approve It&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;en&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;pt&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Editador por&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;cs&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;da&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;en_us&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;es&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;fr&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;he&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;it&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;ja&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;ko&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;nl&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;no&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;pl&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;ru&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;sv&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
    &lt;Action runat=&quot;install&quot; undo=&quot;true&quot; alias=&quot;AddLanguageFileKey&quot; language=&quot;zh&quot; position=&quot;end&quot; area=&quot;general&quot; key=&quot;approveitupdatedBy&quot; value=&quot;Updated by&quot; /&gt;
  &lt;/Actions&gt;
  &lt;files&gt;
  	&lt;% files.forEach(function(file) { %&gt;
  	&lt;file&gt;
      &lt;guid&gt;&lt;%= file.guid %&gt;&lt;/guid&gt;
      &lt;orgPath&gt;&lt;%= file.dir %&gt;&lt;/orgPath&gt;
      &lt;orgName&gt;&lt;%= file.name %&gt;&lt;/orgName&gt;
    &lt;/file&gt;
	&lt;% }); %&gt;
  &lt;/files&gt;
&lt;/umbPackage&gt;
</pre>
<p>This file uses the Grunt templating engine so that, not only can I include the Package Action Contrib custom actions, but also some custom variables, such as:</p>
<ul>
<li>The mandatory list of files that is automatically updated when a new file is added to the project output</li>
<li>The <em>package.json</em> variables</li>
</ul>
<p>That&#8217;s it! We can now create new versions of Approve It without having to go into the Umbraco backoffice and doing it manually every time we need a new package version.</p>
<p><em>You can find the complete source code in my GitHub: <a href="https://github.com/ViGiLnT/ApproveIt" target="_blank" rel="noopener">https://github.com/ViGiLnT/ApproveIt</a>. You can download the Approve It package here: <a href="https://our.umbraco.org/projects/backoffice-extensions/approve-it/" target="_blank" rel="noopener">https://our.umbraco.org/projects/backoffice-extensions/approve-it/</a>.</em></p>
<p>The post <a href="https://blogit.create.pt/andresantos/2016/03/07/automatic-generation-of-umbraco-packages-with-grunt/">Automatic generation of Umbraco packages with Grunt</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/andresantos/2016/03/07/automatic-generation-of-umbraco-packages-with-grunt/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
	</channel>
</rss>
