tag:blogger.com,1999:blog-39233593430890349962024-02-22T12:38:10.815-08:00Project 31-AA Windows Programming BlogWayne Walter Berryhttp://www.blogger.com/profile/07116744675621334568noreply@blogger.comBlogger467125tag:blogger.com,1999:blog-3923359343089034996.post-6632294310086133092024-02-22T12:37:00.000-08:002024-02-22T12:37:10.147-08:00Cosmos Status Code 400 - SubStatus Code 1004 <p></p><p class="MsoNormal">When calling Cosmos DB via Gateway Mode and you get a HTTP 400
status code, the Cosmos DB Gateway is telling you the request contains invalid
data or is missing required parameters.<span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>A sub status code 1004 means that the query is
not support cross partition.<span style="mso-spacerun: yes;"> </span>Cosmos DB
can run partitions (as defined by the partition key) on multiple nodes in the
region, however some queries can’t be executed on sperate nodes and then
combined in the response.<span style="mso-spacerun: yes;"> </span>For example
queries with Order By, Top, District, Offset, Limit and Group by require the
data from this separate nodes to be evaluated together.<span style="mso-spacerun: yes;"> </span><o:p></o:p></p>
<p class="MsoNormal">To solve this issue, do the aggregate, ordering and grouping
at the client after the data is return.<span style="mso-spacerun: yes;">
</span>Or target just a single partition with queries that contain this syntax.<o:p></o:p></p><span style="background-color: white; color: #333333; font-family: Georgia, serif; font-size: 13.33px;">{6230289B-5BEE-409e-932A-2F01FA407A92}</span><p></p>Wayne Walter Berryhttp://www.blogger.com/profile/07116744675621334568noreply@blogger.com0tag:blogger.com,1999:blog-3923359343089034996.post-77802334847618947232022-12-05T22:07:00.000-08:002022-12-05T22:07:32.050-08:00GraphQL on GitHub: a fragment for aggregated repo data<p>GitHub provides the <a href="https://docs.github.com/en/graphql/overview/explorer" target="_blank">GraphQL explorer</a> to play with GraphQL data and learn how to shape your queries. When your group of queries grows to the point of repeating objects and their fields, its time to move to fragments. </p><p>A fragment in GraphQL allows you to have:</p><p></p><ul style="text-align: left;"><li>readability - a well-named fragment shortens queries and mutations</li><li>reusability - reuse fragments in queries and mutations</li><li>performance - on the client, fragments and their components are a cache layer</li><li>type-safety - the <a href="https://the-guild.dev/graphql/codegen">code generator</a> that builds your GraphQL SDK includes named fragments so you can access any deeply nested objects <i>as fragments</i> without the types and their guards you would need to manage</li></ul><p></p><p>Typical places to create and use fragments to <i>DRY</i> up your GraphQL queries include the most common schema objects. For a GitHub GraphQL schema, those can include the <a href="https://docs.github.com/en/graphql/reference/objects#user">User</a> and <a href="https://docs.github.com/en/graphql/reference/objects#repository">Repository</a>.</p><p>To get the entire list of repositories in a GitHub org, you need to compensate for the cursor/paging as well as the return results. An example query for that looks like:</p><div style="text-align: left;"><span style="font-family: courier;"><span style="background-color: #01ffff;">query OrgReposAg</span>(<br /> $organization: String!<br /> $pageSize: Int<br /> $after: String<br />) {<br /> organization(login: $organization) {<br /> repositories(<br /> after: $after<br /> first: $pageSize<br /> orderBy: { field: STARGAZERS, direction: DESC }<br /> ) {<br /> totalCount<br /> pageInfo {<br /> startCursor<br /> hasNextPage<br /> endCursor<br /> }<br /> edges {<br /> cursor<br /> node {<br /> <span style="background-color: #fcff01;">...MyRepoFields</span><br /> }<br /> }<br /> }<br /> }<br />}</span></div><div style="text-align: left;"><span style="font-family: courier;"><br /></span></div><div style="text-align: left;"><span style="font-family: courier;"># This fragment extracts each repository in the edges array</span></div><div style="text-align: left;"><span style="font-family: courier;"># to a named type MyRepoFields, created by codegen<br /><span style="background-color: #01ffff;">fragment MyRepoFields</span><span style="background-color: white;"> on Repository</span> {<br /> repositoryName: name<br /> id<br /> url<br /> descriptionHTML<br /> updatedAt<br /> stargazers {<br /> totalCount<br /> }<br /> forks {<br /> totalCount<br /> }<br /> issues(states: [OPEN]) {<br /> totalCount<br /> }<br /> pullRequests(states: [OPEN]) {<br /> totalCount<br /> }<br />}</span></div><div style="text-align: left;"><span style="font-family: courier;"><br /></span></div><div style="text-align: left;"><span style="font-family: courier;">The <b>OrgReposAg</b> query uses the named fragment, <b>MyRepoFields</b>, to extract the Repository object fields and aggregations needed such as the total stargazers, forks and open issues. </span></div><div style="text-align: left;"><span style="font-family: courier;"><br /></span></div><div style="text-align: left;">This query uses the <i>after </i>variable to page through the org's repo list, 100 repos at a time. The variables object intially contains:</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><div><span style="font-family: courier;">{</span></div><div><span style="font-family: courier;"> "organization": "Azure-samples",</span></div><div><span style="font-family: courier;"> "after": null,</span></div><div><span style="font-family: courier;"> "pageSize": 100</span></div><div><span style="font-family: courier;">}</span></div></div><div style="text-align: left;"><br /></div><div style="text-align: left;">To page through all the repos in an org, each request needs to capture the paging information via the pageInfo.<i>endCursor</i>, in order to use that value in the next request of where to start <i>after</i>.</div><div style="text-align: left;"><br /></div><div style="text-align: left;">If you need the list of repos in an org, and you weren't using a fragment, you would need to create your own TypeScript type for the repository fields. That in itself isn't a huge barrier, but you need to manage the type, separately from the generated types, and you need to manage it over the time of the project and the people that come and go from it. It becomes one more thing that has to be known and verified. </div><div style="text-align: left;"><br /></div><div style="text-align: left;">This becomes increasingly problematic as the query changes over time with the nested depths of items or the remapping of data to the final shape needed by the UI. Moving the <i>core</i> information of the query to a fragment allows the query to organically change without interferring with your ability to get at the core information. It also provides assurance that when you need this <i>core</i> information in other queries in the same schema, the same core information is returned in the same named fragment (and its cooresponding type in the SDK) in each place it is used. </div><div style="text-align: left;"><br /></div><div style="text-align: left;"><span style="font-family: courier;">If you have a different solution, let me know. <a href="https://twitter.com/dfberry">@dfberry</a></span></div>Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-37113571066639222252021-11-27T08:56:00.004-08:002021-11-27T08:56:58.014-08:00Migrate Azure Scheduler jobs to Azure Functions<div style="text-align: left;"><b><span style="font-size: medium;"><br /></span></b></div><div style="text-align: left;"><b><span style="font-size: medium;">Migrate a code-based Azure Scheduler job to Azure Functions</span></b></div><p><br /></p><p>Recently, I migrated a scheduled job from .NET Framework 4.6 to .NET Core and from Azure App Service to Azure Functions. This was part of a larger effort to move to .NET Core, and the retirement of a dependency of <a href=" https://docs.microsoft.com/azure/scheduler/migrate-from-scheduler-to-logic-apps">Azure Scheduler jobs</a>. </p><p>While there is nothing wrong with .NET Framework 4.6 or Azure App service, the project was moving toward separate, smaller, quicker deployments for the various projects instead of a single monolithic deployment.</p><div style="text-align: left;"><b><span style="font-size: medium;"><br /></span></b></div><div style="text-align: left;"><b><span style="font-size: medium;">Existing scheduled job: Add feature flags</span></b></div><div style="text-align: left;"><b><span style="font-size: medium;"><br /></span></b></div><div>Add the ability to control you job with a feature flag.</div><div><ol style="text-align: left;"><li>In your Azure App service, create a feature flag for every scheduled job. This can be as simple as an App Configuration setting with a value or you can use Azure App Configuration. </li><li>Add code for the feature flag and make sure it has a default value if it isn't detected in the environment. </li><li>Add logging statements to report your runtime feature flag value. </li><li>Deploy the code to Azure App service and make sure you can stop and start the scheduled job with the feature flag before continuing. </li></ol></div><div><br /></div><div style="text-align: left;"><span style="font-family: courier; font-size: x-small;">string FeatureFlagFindRetweets = Environment.GetEnvironmentVariable("FeatureFlagScheduledJobFindRetweets");<br />if (!String.IsNullOrEmpty(FeatureFlagFindRetweets) && FeatureFlagFindRetweets.ToLower() == "false")<br />{<br /> log.WriteLine($"FindRetweet executed at: {DateTime.Now} feature flag disabled");<br /> return;<br />}<br />log.WriteLine($"FindRetweet executed at {DateTime.Now} feature flag enabled");</span></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><b><span style="font-size: medium;">New Azure Function: Timer trigger</span></b></div><div style="text-align: left;"><b><span style="font-size: medium;"><br /></span></b></div><div style="text-align: left;">Create a new Azure Function app to replace the scheduled job and add the same feature flags</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><ol style="text-align: left;"><li>Create an Azure Function app locally with Visual Studio 2021 and the latest .NET Core you intend to support.</li><li>Create a timer trigger and add the same code inside the function as your original scheduled job including the logging. </li><li>Add the same feature flags you use in the original scheduled job. While Azure Functions has an easy way to disable a function, a feature flag allows for greater flexibility in the future. </li><li>Add any dependencies the original project used with NuGet Manager. </li><li>Build your function. </li><li>You probably have a few build errors because the .NET versions are different and there may be breaking changes. These are usually minor issues that take a little investigation. Common issues I've come across are:</li><ul><li>HTTP Client library changes - used to integrated with other APIs</li><li>JSON (de)serialization library changed from NewtonSoft to System.Text.Json</li><li>Entity Framework changes - or whatever database library you use. </li><li>Authentication library changes</li></ul><li>Fix your build issues but don't change any of the logic of the code yet. This is a straight migration. </li><li>Once your project builds, migrate your tests and perform the same dependency migrations. </li><li>Run your tests and verify your new timer trigger logic still succeeds.</li><li>Deploy your timer trigger with your existing deployment infrastructure making sure the feature flags are not enabled. </li></ol><div><br /></div></div><div style="text-align: left;"><b><span style="font-size: medium;">Disable Azure Schedule job, enable Azure Function Timer trigger</span></b></div><div style="text-align: left;"><b><span style="font-size: medium;"><br /></span></b></div><div style="text-align: left;">Azure App Service and Azure Functions both allow you to control the Configuration Settings from a variety of methods include Azure CLI, PowerShell, Azure SDKs, and the Azure portal. </div><div style="text-align: left;"><ol style="text-align: left;"><li>Determine how you want to automatically deploy configuration changes. For this initial switch over, in a low priority job, you could change these feature flags manually in the Azure portal. For more critical jobs, you should automate the task and include it as part of your deployment pipeline. </li><li>Disable the original scheduler jobs and verify with logging that the job executed but didn't continue past the check of the feature flag. </li><li>Enable the timer trigger and verify with logging that the job executed and did continue past the feature flag check. </li></ol></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><b><span style="font-size: medium;">Have a better method? </span></b></div><div style="text-align: left;"><br /></div><div style="text-align: left;">Let me know <a href="https://twitter.com/dfberry">@dfberry</a></div><div style="text-align: left;"><br /></div>Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-67734463400176092002021-11-13T14:08:00.002-08:002021-11-13T14:08:08.476-08:00Entity Framework 6 won't save (update) an entity returned from Stored Procedure<h4 style="text-align: left;">Symptom</h4><p>The issue was that code that previously worked, update property then save, wasn't working any more. The application is a .NET 4.6 Web API project using Entity Framework 6. </p><h4 style="text-align: left;">Issue</h4><p>The fix isn't in the code which saved (updated) the entity, but was caused because the entity that is updated isn't correctly formed by the Stored Procedure. Before the SP was added, the entity was returned from EF directly. </p><h4 style="text-align: left;"><span style="font-family: inherit;">Fix</span></h4><p>After the stored procedure completes, refetch the entity using straight Entity Framework code such as `<span style="font-family: courier; font-size: x-small;">await TwitterAccounts.FirstAsync(table => table.TwitterHandle == twitterHandle);</span>` where TwitterAccounts is a table in the EF Context. </p><h4 style="text-align: left;">Step to debug issue: capture save result</h4><p>The original EF code to save didn't capture the returned int of number of rows changed. </p><p><b>Before</b></p><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><div style="text-align: left;"><span style="font-family: courier; font-size: x-small;">account.IsProperty = true;<br />_context.SaveChanges();<br />return OK();</span></div></blockquote><p><b>After</b></p><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><div style="text-align: left;"><span style="font-family: courier; font-size: x-small;">account.IsProperty = true;</span></div><div style="text-align: left;"><span style="font-family: courier; font-size: x-small;">int result= _context.SaveChanges();</span></div><div style="text-align: left;"><span style="font-family: courier; font-size: x-small;">if(result==0)</span></div><div style="text-align: left;"><span style="font-family: courier; font-size: x-small;">{</span></div><div style="text-align: left;"><span style="font-family: courier; font-size: x-small;"><span style="white-space: pre;"> </span>throw new Exception("property was not updated");</span></div><div style="text-align: left;"><span style="font-family: courier; font-size: x-small;">}</span></div><div style="text-align: left;"><span style="font-family: courier; font-size: x-small;">return Ok(account);</span></div></blockquote><h4 style="text-align: left;">Step to debug issue: see T-SQL from Entity Framework in Visual Studio Output window</h4><div>Once the row count was returned as zero, the issue was why? To see the actual T-SQL sent to the database, I added the following code to the BotContext class, which inherits from DbContext. The constructor now includes:</div><div><br /></div><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><div style="text-align: left;"><div><span style="font-family: courier; font-size: x-small;">#if DEBUG</span></div></div><div style="text-align: left;"><div><span style="font-family: courier; font-size: x-small;">Database.Log = s => System.Diagnostics.Debug.WriteLine(s);</span></div></div><div style="text-align: left;"><div><span style="font-family: courier; font-size: x-small;">#endif</span></div></div></blockquote><div><br /></div><div>This shows all T-SQL from Entity Framework in the output window. This showed that EF wasn't producing any T-SQL which meant there was either an issue with the variables (those hadn't changed) or there were no changes detected in the entity. </div><div><br /></div><h4 style="text-align: left;">Step to debug issue: see the EF changes detected</h4><div>To see the changes detected, I added the following code to my BotContext class:</div><div><br /></div><div><div> <span style="font-family: courier; font-size: x-small;">public void DisplayTrackedEntities(DbChangeTracker changeTracker)</span></div><div><span style="font-family: courier; font-size: x-small;"> {</span></div><div><span style="font-family: courier; font-size: x-small;"> var entries = changeTracker.Entries();</span></div><div><span style="font-family: courier; font-size: x-small;"> foreach (var entry in entries)</span></div><div><span style="font-family: courier; font-size: x-small;"> {</span></div><div><span style="font-family: courier; font-size: x-small;"> System.Diagnostics.Debug.WriteLine("Entity Name: {0}", entry.Entity.GetType().FullName);</span></div><div><span style="font-family: courier; font-size: x-small;"> System.Diagnostics.Debug.WriteLine("Status: {0}", entry.State);</span></div><div><span style="font-family: courier; font-size: x-small;"> }</span></div><div><span style="font-family: courier; font-size: x-small;"> }</span></div></div><div><span style="font-family: courier; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit;">Then to use the code, call this method after the entity is changed but before it is saved:</span></div><div><span style="font-family: inherit;"><br /></span></div><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><div><div><span style="font-family: courier; font-size: x-small;">account.IsProperty = false;</span></div></div><div><div><span style="font-family: courier; font-size: x-small;"><b>DisplayTrackedEntities(context.ChangeTracker);</b></span></div></div><div><div><span style="font-family: courier; font-size: x-small;">int result = context.SaveChanges();</span></div></div><div><div><span style="font-family: courier; font-size: x-small;"><br /></span></div></div><div><div><span style="font-family: courier; font-size: x-small;">if (result == 0)</span></div></div><div><div><span style="font-family: courier; font-size: x-small;">{</span></div></div><div><div><span style="font-family: courier; font-size: x-small;"><span> </span>throw new Exception("disable-auto-tweets not updated successfully");</span></div></div><div><div><span style="font-family: courier; font-size: x-small;">}</span></div></div><div><div><span style="font-family: courier; font-size: x-small;">return Ok(account);</span></div></div></blockquote><p>At this point, because no changes were detected, I knew the recent switch to a SP caused the issue that changes couldn't be detected on this <i>artificial</i> entity. </p><h4 style="text-align: left;">Step to debug issue<span><span>: get EF entity after SP update</span></span></h4><p style="text-align: left;"><span><span>Originally the code checked a value and returned the account using something like:</span></span></p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><div style="text-align: left;"><span style="font-family: courier; font-size: x-small;">await TwitterAccounts.FirstAsync(table => table.TwitterHandle == twitterHandle);</span></div></blockquote><p>That method changed to use a stored procedure which returned the TwitterAccount entity type. That entity wasn't getting updated. Changing the method to fetch and return the EF entity after the SP updated fixed the issue - the account was updated. </p><h4 style="text-align: left;">Have a better fix? </h4><p>There is probably some way to get EF to update my entity returned from the SP. Do you know what it is? Let me know on Twitter.</p><p><a href="https://twitter.com/dfberry" target="_blank">@dfberry</a></p><p> </p><p><br /></p><p><br /></p>Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-54182501052816005202021-11-02T14:42:00.001-07:002021-11-02T14:42:46.910-07:00Convert GoDaddy PEM certificate to PFX certificate to use in Azure App Service<p> When you purchase GoDaddy certificates, you should get 3 files:</p><p></p><ul style="text-align: left;"><li>*.crt file</li><li>*.pem file</li><li>*-key.txt file</li></ul><div>1. Change the key file's name to the key extension so any future tools can find it by its extension.</div><div><br /></div><div>2. If you download and/or open the key file on a Windows computer, your key file may now have the wrong encoding. Use a bash terminal and the <b>iconv</b> CLI tool to convert to the correct encoding in a new file with a "<b>2</b>" added at the end of the filename to indicate the different file:</div><div><br /></div><div><br /></div><p></p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><p></p><div style="text-align: left;"><span style="font-family: courier;">iconv -c -f UTF-8 -t ASCII your-domain-name.key > your-domain-name.<b>2</b>.key</span></div><p></p></blockquote><p></p><div><br /></div><div><br /></div><div>3. Convert to the PFX format with the <b>openssl</b> CLI tool:</div><div><br /></div><p></p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><p></p><div style="text-align: left;"><span style="font-family: courier;">openssl pkcs12 -export -out your-domain-name.pfx -inkey your-domain-name.<b>2</b>.key -in your-domain-name.crt</span></div><p></p></blockquote><p><span style="font-family: inherit;">4. You need to enter a new password when creating the PFX. Remember the password, you will need it when you add your certificate to Azure App Service. </span></p><p><span style="font-family: inherit;">5. In the Azure portal, for your App Service, select TLS/SSL settings. </span></p><p><span style="font-family: inherit;">6. Add a new TLS/SSL settings. </span></p><p><span style="font-family: inherit;">7. Select your TLS/SSL settings:</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: inherit;"><span>Y</span>our new local file system's PFX file</span></li><li>Your password from step 4</li><li>Select the thumbpint and TLS/SSL type - there should be one choice in the drop down box</li></ul>8. Select <b style="font-family: inherit;">Add Binding</b><span style="font-family: inherit;">. </span><p></p><p><span style="font-family: inherit;">9. Restart your App service.</span></p><p><span style="font-family: inherit;">10. On the Azure portal's Overview for your App Service, select your URL such as https://YOUR-DOMAIN. </span></p><p><span style="font-family: inherit;">11. The browser may take a few seconds to reload. Notice the browser indicates your website is secure with the typical lock icon. </span></p><p><span style="font-family: inherit;"><br /></span></p><p><span style="font-family: inherit;"><a href="https://twitter.com/dfberry">@dfberry</a></span></p>Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-75108077326960992612021-11-02T11:03:00.005-07:002021-11-02T11:03:57.872-07:00Oct 2021 - Copy an Azure SQL Database to dev computer<p><br /></p><p>There are several blog posts on this site answering how to copy an Azure SQL database. Since they are older or in some cases lost (Wayne's Microsoft blog posts are gone), I'll link to the Microsoft docs. </p><h4 style="text-align: left;">Enterprise data or functionality?</h4><div style="text-align: left;">Don't use these processes if you need change detection or other enterprise-level requirements. Copy the Azure SQL database and keep it in the cloud.</div><h4 style="text-align: left;">Make a copy of your Azure Cloud database</h4><p>To copy an existing Azure SQL Database in the Azure portal, you can copy or export. Generally, I choose to <a href="https://docs.microsoft.com/en-us/azure/azure-sql/database/database-export#the-azure-portal">export to Azure Storage Blob container as a bacpac file</a>. This allows me to use it as either a cloud or local database.</p><p>The bacpac file includes data and schema.</p><h4 style="text-align: left;">Watch for export completion</h4><p>To watch for export completion, from the Azure Server (not database) in the portal, use the <b>Import/Export History</b> in the Data Management section.</p><h4 style="text-align: left;">Download bacpac file from Azure Storage</h4><p>To download the bacpac file, Azure Storage container in the Azure portal. Select the bacpac file then download it to your local computer.</p><h4 style="text-align: left;">Restore SQL database to local machine from bacpac file</h4><p>Using SSMS, <a href="https://docs.microsoft.com/en-us/sql/relational-databases/data-tier-applications/import-a-bacpac-file-to-create-a-new-user-database?view=sql-server-ver15#using-the-import-data-tier-application-wizard">import a data-tier application</a>. Select the downloaded bacpac file. </p><p>Because the Azure SQL db is a contained db, you need to change the master db on your local server with the following t-sql executed against the master db.</p><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><p><span style="font-family: courier;">exec sp_Configure 'contained database authentication', 1</span></p><p><span style="font-family: courier;">go </span></p><p><span style="font-family: courier;">reconfigure </span></p></blockquote><p><br /></p><p><a href="https://twitter.com/dfberry">@dfberry</a></p><p><br /></p><p><br /></p><p><br /></p>Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.com0tag:blogger.com,1999:blog-3923359343089034996.post-54985120135021881322021-10-25T06:41:00.009-07:002021-10-25T08:03:42.826-07:00Azure Functions + System.Text.JSON Deserialize exception <p>If you run into a System.IO.FileNotFoundException exception from the Azure Function when it is deserializing JSON with System.Text.Json to your class, make sure you are not using System.Text.Json 5.0.2. </p><h2><b>Issue</b></h2><p>FileNotFoundException: Could not load file or assembly 'System.Text.Encodings.Web, Version=5.0.0.0, Culture=neutral</p><h2><b>Fix</b></h2><p>Downgrade to System.Text.Json 5.0.1. </p><h2 style="text-align: left;"><b>Project description</b></h2><p>The issue was found while moving code from a working .NET Framework 4.6.1 web api project into a .NET Core 3.1 class library, which is called from an Azure Function 3. The deserialization happens in the class library. The manual and automated testing described in the post were both local to my development machine, not on the Azure Cloud.</p><p>Initially it was tested by the Azure Function manually. Later, as I thought the issue was about the JSON returned, I added automated programmatic tests to call into the class library in a separate test project. The test project worked so the issue had to be the Azure Function runtime or its dependencies. </p><h2><b>Before unit tests</b></h2><p>Before the unit test, I knew the FileNotFound exception was a symptom but I assumed the real problem was the JSON being deserialized. The deserialization code went from the HTTP response content directly to a stream wrapped in the deserialization code, so it immediately threw without seeing, in the Visual Studio 2019 debugger, what JSON was returned. </p><h2><b>Adding unit tests</b></h2><p>I broke apart the response from the deserialization. That allowed me to see the JSON and create unit tests. When I realized the JSON was deserializable from unit tests, I thought it was something about how the debugger was compensating for the text. There could be some difference between the raw text in the unit test and the text processed by the Azure Function. Adding my Debug.Write statements between maual and automated testing runs showed that the text was the same and that the problem was still with deserialization. </p><p>At this point, I assumed it was a runtime issue but thought it was something about the HTTP call and how it was creating the JSON.</p><h2><b>Offload deserialization to a queue</b></h2><p>As a bonus, breaking up the JSON fetch from the deserialization allows the system to offload the deserialization and downstream tasks to a queue. In that architecture, where an Azure Function timeout isn't at risk for the caller, I could add as much data cleaning as needed in future sprints. </p><h2><b>The runtime problem</b></h2><p>Now that tests could deserialize, the hunt was on for the runtime problem. The JSON deserialization worked in .NET 4.6.1 Framework with Newtonsoft deserialization but not the Azure Function with System.Text.Json. At this point, searching the Internet led to several issues about System.Text.Json in Azure Functions. Downgrading the library to 5.0.1 was the listed fix. </p><h2><b>Other problems</b></h2><p>Before the unit tests, other things tried:</p><p>* Downloaded and setup the Fusion logger to look for mismatched dependencies - nothing turned up with that. </p><p>* Tried to add a lock around the code to see into the function call, because it was in an async loop. The thought was this was some missed async handling somewhere that was showing up here. The lock in .NET Core was cumbersome and unfamiliar and wasn't blocking when I wanted it to so I stopped going down that rabbit hole. </p><p><br /></p><p><a href="https://twitter.com/dfberry" target="_blank">@dfberry</a></p><p><br /></p><p><br /></p>Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-14240026477208841462021-08-22T09:39:00.004-07:002021-08-22T09:41:39.764-07:00Create Azure DevOps Pipeline for React App deployment to Azure app service<p> Disclaimer: All opinions in this post are mine and not my employer (Microsoft). If you know of a more correct or performant way to accomplish work discussed in this post, please let me know at email <a href="mailto:javascript-developer@outlook.com">javascript-developer@outlook.com</a>. Many projects I work on are in progress by the time I work on them. I can't change previous design or architecture choices, but just solve a specific technical issue. </p><h1 style="text-align: left;">Secrets stored in Azure Key Vault</h1><p>All secrets for the React app are stored in Azure Key Vault. These secrets need to be pulled from Key Vault and set into the environment so that the `npm build` script uses those values. In order for the Azure DevOps Pipeline to connect to Azure Key Vault, you need to complete some work before you develop your Pipeline:</p><p></p><ul style="text-align: left;"><li><a href="https://docs.microsoft.com/azure/key-vault/general/quick-create-portal">Create a Key Vault</a> and <a href="https://docs.microsoft.com/azure/key-vault/secrets/quick-create-portal">store</a> your React build secrets, such as an Azure Functions key, used to authenticate and use the Function. Your secret doesn't have to have the same name as your React build variable. Please don't try. Key vault secrets don't allow underscores in names anyway. Just give the variable a human readable name. The pipeline can map between the secret name and the build environment name.</li><li><a href="https://docs.microsoft.com/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#create-a-service-connection">Create a connection from Pipelines to Key Vault</a> - In Azure DevOps, in the project settings, add a service connection to Azure Key Vault. This process creates a service principal. You can find all your service principals in Azure Portal, under the Azure Active Directory section. <a href="https://docs.microsoft.com/azure/active-directory/develop/app-objects-and-service-principals#service-principal-object">Service Principals</a> are part of Azure App Registrations. </li><li><a href="https://docs.microsoft.com/azure/devops/pipelines/release/azure-key-vault?view=azure-devops#set-up-azure-key-vault-access-policies" target="_blank">Set up Azure Key Vault access policies</a> - In the Azure portal, find your Key Vault, and add the Pipeline's Service Principal for `list` and `get`. </li></ul><h1 style="text-align: left;">Create an Azure DevOps Pipeline to build React app</h1><div>The React app is deployed to an Azure app service wrapped in a .NET Core application. The vmImage is `windows-latest`. </div><div><br /></div><div>The YAML file is:</div><div><br /></div><div><span style="font-family: courier;"><br /></span></div><div><div style="background-color: #fffffe; font-size: 14px; line-height: 19px; white-space: pre;"><div><span style="color: #007200;"><span style="font-family: courier;"># ASP.NET Core (.NET Framework)</span></span></div><span style="font-family: courier;"><br /><br /></span><div><span style="color: #007200;"><span style="font-family: courier;"># Build and test ASP.NET Core projects targeting the full .NET Framework.</span></span></div><div><span style="color: #007200;"><span style="font-family: courier;"># Add steps that publish symbols, save build artifacts, and more:</span></span></div><div><span style="color: #007200;"><span style="font-family: courier;"># https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core</span></span></div><span style="font-family: courier;"><br /></span><div><span style="font-family: courier;"><span style="color: teal;">trigger</span>:</span></div><div><span style="font-family: courier;">- <span style="color: #0451a5;">main</span></span></div><span style="font-family: courier;"><br /></span><div><span style="color: #007200;"><span style="font-family: courier;"># </span></span></div><div><span style="font-family: courier;"><span style="color: teal;">pool</span>:</span></div><div><span style="font-family: courier;"> <span style="color: teal;">vmImage</span>: <span style="color: #0451a5;">'windows-latest'</span></span></div><span style="font-family: courier;"><br /></span><div><span style="color: #007200;"><span style="font-family: courier;"># Variables used in this pipeline</span></span></div><div><span style="color: #007200;"><span style="font-family: courier;"># The `dinatrue` variables is a test used in the echo command to understand the syntax for container:</span></span></div><div><span style="color: #007200;"><span style="font-family: courier;"># bringing in variables.</span></span></div><div><span style="font-family: courier;"><span style="color: teal;">variables</span>:</span></div><div><span style="font-family: courier;"> <span style="color: teal;">solution</span>: <span style="color: #0451a5;">'**/*.sln'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">buildPlatform</span>: <span style="color: #0451a5;">'Any CPU'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">buildConfiguration</span>: <span style="color: #0451a5;">'Release'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">dinatrue</span>: <span style="color: #0451a5;">'hello dina'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">buildDate</span>: <span style="color: #0451a5;">$[format('{0:yyyy}{0:MM}{0:dd}', pipeline.startTime)]</span></span></div><span style="font-family: courier;"><br /><br /></span><div><span style="font-family: courier;"><span style="color: teal;">steps</span>:</span></div><span style="font-family: courier;"><br /></span><div><span style="color: #007200;"><span style="font-family: courier;"># Get React app secrets from Key Vault</span></span></div><div><span style="color: #007200;"><span style="font-family: courier;"># Key Vault is used for projects beyond this single client app. If the Key Vault</span></span></div><div><span style="color: #007200;"><span style="font-family: courier;"># were only for this client app, change the `SecretsFilter` value to `*`.</span></span></div><div><span style="font-family: courier;">- <span style="color: teal;">task</span>: <span style="color: #0451a5;">AzureKeyVault@2</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">inputs</span>:</span></div><div><span style="font-family: courier;"> <span style="color: teal;">azureSubscription</span>: <span style="color: #0451a5;">'SQL Projects (98c...)'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">KeyVaultName</span>: <span style="color: #0451a5;">'MSTwitterKeyVault'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">SecretsFilter</span>: <span style="color: #0451a5;">'PublicApiMessageBeforeLoginKey,PublicApiGetUtcNowKey,PublicApiUrl,ServerUri'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">RunAsPreJob</span>: <span style="color: blue;">false</span></span></div><span style="font-family: courier;"><br /></span><div><span style="color: #007200;"><span style="font-family: courier;"># Verify/debug variables</span></span></div><div><span style="font-family: courier;">- <span style="color: teal;">task</span>: <span style="color: #0451a5;">CmdLine@2</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">inputs</span>:</span></div><div><span style="font-family: courier;"> <span style="color: teal;">script</span>: <span style="color: #0451a5;">'echo %dinatrue% %buildDate%'</span></span></div><span style="font-family: courier;"><br /></span><div><span style="color: #007200;"><span style="font-family: courier;"># Set Key vault secrets to React app environment variables</span></span></div><div><span style="color: #007200;"><span style="font-family: courier;"># Verify/debug values with SET command</span></span></div><div><span style="color: #007200;"><span style="font-family: courier;"># secrets' values will be `***` on purpose</span></span></div><div><span style="font-family: courier;">- <span style="color: teal;">task</span>: <span style="color: #0451a5;">CmdLine@2</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">inputs</span>:</span></div><div><span style="font-family: courier;"> <span style="color: teal;">script</span>: <span style="color: #0451a5;">'SET > env.log && cat env.log'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">env</span>:</span></div><div><span style="font-family: courier;"> <span style="color: teal;">REACT_APP_APP_SERVER_BASE_URL_PUBLIC_API_APP_MESSAGE_BEFORE_LOGIN_KEY</span>: <span style="color: #0451a5;">$(PublicApiMessageBeforeLoginKey)</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">REACT_APP_APP_SERVER_BASE_URL_PUBLIC_API_GET_UTC_NOW_KEY</span>: <span style="color: #0451a5;">$(PublicApiGetUtcNowKey)</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">REACT_APP_APP_SERVER_BASE_URL_PUBLIC_API</span>: <span style="color: #0451a5;">$(PublicApiUrl)</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">REACT_APP_SERVER_URL</span>: <span style="color: #0451a5;">$(ServerUri)</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">REACT_APP_CACHE_BUST</span>: <span style="color: #0451a5;">$(buildDate)</span></span></div><span style="font-family: courier;"><br /></span><div><span style="color: #007200;"><span style="font-family: courier;"># Get source code from repo</span></span></div><div><span style="font-family: courier;">- <span style="color: teal;">task</span>: <span style="color: #0451a5;">NuGetCommand@2</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">inputs</span>:</span></div><div><span style="font-family: courier;"> <span style="color: teal;">restoreSolution</span>: <span style="color: #0451a5;">'$(solution)'</span></span></div><span style="font-family: courier;"><br /></span><div><span style="color: #007200;"><span style="font-family: courier;"># Build project, which ultimately builds React app into `$(build.artifactStagingDirectory)\WebApp.zip`</span></span></div><div><span style="font-family: courier;">- <span style="color: teal;">task</span>: <span style="color: #0451a5;">VSBuild@1</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">inputs</span>:</span></div><div><span style="font-family: courier;"> <span style="color: teal;">solution</span>: <span style="color: #0451a5;">'$(solution)'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">msbuildArgs</span>: <span style="color: #0451a5;">'/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:DesktopBuildPackageLocation="$(build.artifactStagingDirectory)\WebApp.zip" /p:DeployIisAppPath="Default Web Site"'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">platform</span>: <span style="color: #0451a5;">'$(buildPlatform)'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">configuration</span>: <span style="color: #0451a5;">'$(buildConfiguration)'</span></span></div><span style="font-family: courier;"><br /></span><div><span style="color: #007200;"><span style="font-family: courier;"># Deploy Zip file to Azure app service, slot named `</span></span><span style="color: #0451a5; font-family: courier;">client-stage</span><span style="color: #007200; font-family: courier;">` using webDeploy</span></div><div><span style="font-family: courier;">- <span style="color: teal;">task</span>: <span style="color: #0451a5;">AzureRmWebAppDeployment@4</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">inputs</span>:</span></div><div><span style="font-family: courier;"> <span style="color: teal;">ConnectionType</span>: <span style="color: #0451a5;">'AzureRM'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">azureSubscription</span>: <span style="color: #0451a5;">'SQL Projects (98c...)'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">appType</span>: <span style="color: #0451a5;">'webApp'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">WebAppName</span>: <span style="color: #0451a5;">'MSTwitterApp'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">deployToSlotOrASE</span>: <span style="color: blue;">true</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">ResourceGroupName</span>: <span style="color: #0451a5;">'MSTwitterBot'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">SlotName</span>: <span style="color: #0451a5;">'client-stage'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">packageForLinux</span>: <span style="color: #0451a5;">'$(build.artifactStagingDirectory)\WebApp.zip'</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">enableCustomDeployment</span>: <span style="color: blue;">true</span></span></div><div><span style="font-family: courier;"> <span style="color: teal;">DeploymentType</span>: <span style="color: #0451a5;">'webDeploy'</span></span></div><span style="font-family: courier;"><br /></span></div></div><p></p><p><br /></p>Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-90975705055291091242021-08-06T11:52:00.003-07:002021-08-06T11:52:24.532-07:00Moving database from Azure SQL to localdb<p>I recently moved an Azure SQL database back to a local development database and ran into a few issues. I took these notes so that they might help the next person that hits the problem.</p><p>In my local SSMS, I use the Import/Export wizard with the datasource using SQL Server native client 11.0. This moves the tables and data. Any destination tables will not have IDENTITY as the source tables did. </p><h3 style="text-align: left;">Solution # 1 </h3><p>Move away from INT Identity to use GUIDS. This requires work in the database and client code but is the better choice if you need to move data out of the source datatabase then back into the source database. </p><h3 style="text-align: left;">Solution #2</h3><p>More immediate fix to get past the block that your inserts don't autoincrement. </p><h4 style="text-align: left;">Steps:</h4><div>The following steps are completed in SSMS in the destination (local) database and should have all the data but not the IDENTITY column.</div><p></p><ul style="text-align: left;"><li>Rename the mytable to mytable2.</li><li>Generate CREATE, INSERT, and SELECT scripts for the table.</li><li>Modify the CREATE script to use the table name (change mytable2 to mytable) and change the PK row to include the identity requirement.</li></ul><div><br /></div><p></p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><div>CREATE TABLE [dbo].[mytable](</div><div><div><span style="white-space: pre;"> </span>[Id] [int] <span style="color: red;"><b>IDENTITY (1,1)</b></span> NOT NULL,</div><div><span style="white-space: pre;"> </span>[Text] [nvarchar](40) NULL,</div><div>) ON [PRIMARY]</div><div>GO</div></div></blockquote><p></p><ul style="text-align: left;"><li>Run the creation script.</li><li>Create second script from the INSERT/SELECT scripts</li></ul><p></p><p></p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><div style="text-align: left;">SET IDENTITY_INSERT mytable ON<br />INSERT INTO [dbo].[mytable]<br /> ([Id]<br /> ,[Text])<br />SELECT [Id]<br /> ,[Text]<br /> FROM [dbo].[mytable2] <br />SET IDENTITY_INSERT mytable OFF</div></blockquote><p></p><p><br /></p>Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-25624488895086313992020-12-10T15:24:00.003-08:002020-12-10T15:33:56.590-08:00Node.js, npm, yarn, & those lock files<div style="text-align: left;">The following is my opinion and doesn't represent my employer. </div><h2 style="text-align: left;">Install Node.js</h2><div>If you are like me and work across operating systems and environments (local, container, cloud), you have one or two bullet-proof ways you install Node.js. The Node.js organization has done a great job of listing those. </div><div><br /></div><div>I'm sticking with the following:</div><div><br /></div><div>* For Windows installations - use the <a href="https://nodejs.org/en/download/">Windows download</a>. </div><div>* For all other installations, including VM, Container, Mac, *Nix - <a href="https://github.com/nodesource/distributions/blob/master/README.md#debinstall">use the bash script</a></div><div><br /></div><div>Never, under any circumstances, use the apt or apt-get package manager to install Node.js. At this point, that is equivalent to a code-smell. </div><div><br /></div><h2 style="text-align: left;">NPM vs YARN</h2><div>NPM should be your package manager of choice when installing an NPM package. If you run into problems, <a href="https://github.com/npm/cli/issues">log an issue</a>. </div><div><br /></div><h2 style="text-align: left;">Debugging Node.js projects with NVM and lock files</h2><div>The Node Version Manager (nvm) and lock files are for the developer of a project to be able to get back to an exact version of the entire development environment to debug an issue. When you install and use someone's package, you don't need their lock file. NPM doesn't install dependencies for a package based on the log file. </div><div><br /></div><div>Check in the lock file so you need to get back to a specific development environment. </div><p><br /></p><p><br /></p>Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.com0tag:blogger.com,1999:blog-3923359343089034996.post-30581460550543270422020-03-06T06:05:00.000-08:002020-03-06T06:35:15.513-08:00Hosting front-end applications on AzureI have a catalog of small front-end Javascript apps built with Angular (ng) and React (CRA and Next) I would like to host on Azure.<br />
<br />
<b>Hosting on Azure</b><br />
<b><br /></b>
<a href="https://azure.microsoft.com/en-us/" target="_blank">Azure</a> provides features for a web host:<br />
<br />
* Options from big to small - full <a href="https://azure.microsoft.com/en-us/services/virtual-machines/" target="_blank">VM</a>, <a href="https://azure.microsoft.com/en-us/services/container-instances/" target="_blank">container</a>, <a href="https://azure.microsoft.com/en-us/services/app-service/web/" target="_blank">web app</a>, or <a href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website-host" target="_blank">host static website</a><br />
* HTTPS and URL - every Azure resource is served via HTTPS with a dedicated URL - no need to buy a certificate or domain name until needed.<br />
<br />
<b>No Configuration changes</b><br />
<b><br /></b>
In order to reduce hidden problems, each front-end app should be installed and running with no configuration change away from the development environment such as a to change the routing of assets from absolute to relative, or folder and subfolder naming.<br />
<br />
<b>Consistent & immediate deployment</b><br />
<b><br /></b>
Once the app is ready to deploy as a collection of static files, there shouldn't be a need to spend time preparing the hosting environment. The front-end system deployment steps should be consistent regardless of which front-end framework the project uses. Deployment failure and debugging should be minimized considering it is just a static front-end app.<br />
<br />
<b>Reverse proxy considerations</b><br />
<b><br /></b>
One solution I've used in previous years requires a reverse-proxy like Nginx and domain name control. This violates the configuration and immediate deployment goals but is a strong consideration when the project is ready for production deployment - the cost and control of an Azure VM makes that an easy choice.<br />
<br />
<b>Azure Storage versus Azure Web app</b><br />
<b><br /></b>
This narrowed the choices to:<br />
* Azure Blob Storage static website - would only handle front-end apps completely disconnected from the back-end<br />
* Azure Web app allows both front and back-end apps.<br />
<br />
Both are easy to configure with minimal changes in the <a href="http://portal.azure.com/" target="_blank">Azure portal</a>.<br />
<br />
<b>Pricing and availability</b><br />
<b><br /></b>
* Azure Blob Storage is priced by data storage and throughput<br />
* Azure Web app comes with a monthly charge. Since these are very small hobby apps, Azure Blob Storage seems the best choice for now.<br />
<br />
<b>Preparing a test app</b><br />
<b><br /></b>
To test Azure Blob storage, use the <a href="https://nextjs.org/docs/advanced-features/static-html-export" target="_blank">NextJS static export process</a> to build a static app to a <i>local</i> <b>out</b> directory in the <i>local</i> project folder.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRv88d3ttWUIURFrKBuNH-C74bUjS8mRw1Q1o7E7U49hoRvC9dksGwqiluSWG50tWnsQiqRFr41aPulyantwzVmq3E9n71g8F2m1CiCEA5vgHbEkW-agKHzQzOpul_ICZZBC-fFxDSWBM/s1600/next-out-folder-view.PNG" imageanchor="1"><img border="0" data-original-height="113" data-original-width="126" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRv88d3ttWUIURFrKBuNH-C74bUjS8mRw1Q1o7E7U49hoRvC9dksGwqiluSWG50tWnsQiqRFr41aPulyantwzVmq3E9n71g8F2m1CiCEA5vgHbEkW-agKHzQzOpul_ICZZBC-fFxDSWBM/s1600/next-out-folder-view.PNG" /></a></div>
<br />
<b>How to deploy static files </b><br />
<b><br /></b>
After creating an <a href="https://docs.microsoft.com/en-us/azure/storage/common/storage-account-create?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json&tabs=azure-portal" target="_blank">Azure Storage resource</a>, in the Azure portal, configure the Static website. This creates a Blob container named <b>$web</b> in the Storage account.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDZAW6f2ls2va3cxXSgO_Odir4oCJutc3fd298qZtFeJQ1KXC9Ec2rDMvDNl-zxkZpVAIooTZQCGY9LZ-Uf9xsgIFyowCGRz2Yv5PsdkKwV6P1Q0O8-dDb6CFV1KNAwM4f9UVbDZGCLjY/s1600/static-web.png" imageanchor="1"><img border="0" data-original-height="685" data-original-width="1128" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDZAW6f2ls2va3cxXSgO_Odir4oCJutc3fd298qZtFeJQ1KXC9Ec2rDMvDNl-zxkZpVAIooTZQCGY9LZ-Uf9xsgIFyowCGRz2Yv5PsdkKwV6P1Q0O8-dDb6CFV1KNAwM4f9UVbDZGCLjY/s400/static-web.png" width="400" /></a></div>
<br />
Copy one of the endpoints to use later to test that the static website works.<br />
<br />
<br />
<b>Upload files to the $web container. </b><br />
<br />
<a href="https://azure.microsoft.com/en-us/features/storage-explorer/" target="_blank">Download</a> and use the storage explorer to move the front-end website files and folders to the new $web container. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi88KAtSktI90w38oOxLr6UxtDSX3mr-s2jEGJVy4TQcc11VQvh2lQspsdGx5Z2JgpxNZGftR7ReiYZOh7WnOOda9KmWySgQZfKzkn7FaroSjThSKaWPXB30vOE3ZdiZRT6a7GqOc2x8to/s1600/storage-explorer.png" imageanchor="1"><img border="0" data-original-height="425" data-original-width="1382" height="122" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi88KAtSktI90w38oOxLr6UxtDSX3mr-s2jEGJVy4TQcc11VQvh2lQspsdGx5Z2JgpxNZGftR7ReiYZOh7WnOOda9KmWySgQZfKzkn7FaroSjThSKaWPXB30vOE3ZdiZRT6a7GqOc2x8to/s400/storage-explorer.png" width="400" /></a></div>
<br />
<b>Test the static website</b><br />
<b><br />
</b> Use the URL endpoint provided (when you configured the static website) to verify your website works.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwSPKaKjb2Mhg-rv9RquVk3H2O7DcGDk-pu8yK_fVvNm479JhyewRG6BVgjTovXggIdKgIB0WUmllSHT2CGPgh67qQIUNTWViOYInTiTs8GwXZRpwtJ064dfZ2cnQyJZL2p88DYgjcwD8/s1600/website-test.png" imageanchor="1"><img border="0" data-original-height="487" data-original-width="504" height="309" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwSPKaKjb2Mhg-rv9RquVk3H2O7DcGDk-pu8yK_fVvNm479JhyewRG6BVgjTovXggIdKgIB0WUmllSHT2CGPgh67qQIUNTWViOYInTiTs8GwXZRpwtJ064dfZ2cnQyJZL2p88DYgjcwD8/s320/website-test.png" width="320" /></a></div>
<b>View usage metrics</b><br />
<br />
Azure provides metrics to see how the website is doing.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTGvZ6aTM6SA-rwtRVmaeUj5i4yc9HRx4mqGOBWxfEir1hyphenhyphenJf2l95DnZ5V5QjtldQMn9CHnmH2_psr-WZmmnZY08M6sClLWBzeyF63zAVUB-avHcBU3FSqqIMioOYE-RsQoxnAD2aYdS8/s1600/storage-metrics.png" imageanchor="1"><img border="0" data-original-height="914" data-original-width="1312" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTGvZ6aTM6SA-rwtRVmaeUj5i4yc9HRx4mqGOBWxfEir1hyphenhyphenJf2l95DnZ5V5QjtldQMn9CHnmH2_psr-WZmmnZY08M6sClLWBzeyF63zAVUB-avHcBU3FSqqIMioOYE-RsQoxnAD2aYdS8/s320/storage-metrics.png" width="320" /></a> </div>
<br />
<br />
<b>Hosting more sites</b><br />
<b><br /></b>
Azure Storage builds out containers with URL routes: <i>domain / container / file</i>. The route includes the container name and doesn't, by default, make assumptions about the content type to return when serving the file.<br />
<br />
In order to host more than 1 static website from the same Azure Storage resource, all the of the configuration I'm trying to avoid would need to be done for each site and I would need to manage content types.<br />
<br />
Creating a new Storage account is easy, cheap, and very simple so each new site will be hosted in its own Azure Storage resource. When it is time to assign a custom domain name, create a <a href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-custom-domain-name?tabs=azure-portal#map-a-custom-domain-with-https-enabled" target="_blank">CDN then map the name to that resource</a>.<br />
<b><br /></b>
<b>CLI to create static website</b><br />
<br />
Now that basic usage through the portal is done, use the Azure CLI to <a href="https://docs.microsoft.com/en-us/azure/storage/common/storage-account-create?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json&tabs=azure-cli" target="_blank">create Azure Storage</a> and <a href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website-how-to?tabs=azure-cli" target="_blank">configure a static website</a>.<br />
<br />
<b>Further investigation</b><br />
<b><br /></b>
The solution needs to solve for management takes such as listing all Static Websites and updating static websites via GitHub hook. Building the automation is a next step.<br />
<br />
<br />
<br />
<br />
<br />Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-56369137175541726782020-02-28T07:50:00.001-08:002020-02-28T07:50:48.423-08:00OSS @Microsoft - Docs<a href="https://opensource.microsoft.com/" target="_blank">Open source software (OSS) at Microsoft</a> allows everyone to see, comment, and contribute to the products, services, documentation, sample code, and SDKs they use. I work at Microsoft and my opinions are my own.<br />
<br />
The <a href="http://docs.microsoft.com/" target="_blank">Microsoft documentation</a> set is not a single GitHub repository. It is many repositories, all with active writers, support engineers, and SLAs.<br />
<br />
When you see an issue in the docs or you think a concept or technique is unclear, GitHub repositories allow you to:<br />
<br />
<ul>
<li>Add an issue, via an <b>Edit button</b>, that is sent directly to the Product group or Content Developer. </li>
<li>Create a pull request (PR), that is sent directly to the Product group or Content Developer. </li>
</ul>
<br />
<br />
Is this open source though? Absolutely. You can immediately impact all users of the docs in a positive way.<br />
<br />
<b>2 things you can do when logging an issue against the docs:</b><br />
<br />
<ol>
<li>Be specific. Your comment is attached to the entire doc. Be specific where in the doc the issue is and what wording, image, or sample code is problematic. </li>
<li>Be available. Some times an issue is deeper than a simple fix. If someone has a followup question, respond with information if you have it. </li>
</ol>
<br />
<br />
Can you make the fix via a pull request? Yes. That speeds up the process.<br />
<br />
<br />Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.com0tag:blogger.com,1999:blog-3923359343089034996.post-63314220838275444622019-05-01T09:38:00.001-07:002019-05-02T12:15:38.221-07:00Fetching a Private Key From An Azure Key Vault CertificateIf you create a private certificate in Azure Key Vault and use the fancy features like auto rotation, you might like to be able to fetch the private key from the vault and rehydrate it as a X509Certificate2 class in your C# code.<br />
<br />
Here is how you do that:<br />
<br />
KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetToken));<br />
var certificateBundle = await keyVaultClient.GetCertificateAsync(certificateIdentifier);<br />
var certficiateSecret = await keyVaultClient.GetSecretAsync(certificateBundle.SecretIdentifier.Identifier);<br />
byte[] certificateDecoded = Convert.FromBase64String(certficiateSecret.Value);<br />
var certificate = new X509Certificate2(certificateDecoded, password: "");<br />
<br />
The Certificate Bundle passed back from the <span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">GetCertificateAsync call has a .Cer property, however that is just the bytes for the pubic key, if you do this:</span><br />
<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></span>
<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-variant: normal; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">var publicCertificate = new X509Certificate2(<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">certificateBundle.Cer</span>);</span></span><br />
<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-variant: normal; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><b></b><i></i><u></u><sub></sub><sup></sup><strike></strike><br /></span>
<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-variant: normal; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">The <span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">X509Certificate2 instance will only contain the public key. Instead you need to fetch the full secret and decode it to bytes, once you do that the only other thing you need to know is that Azure Key Vault stores the private certificate with a blank password.</span></span><br />
<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-variant: normal; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></span></span>
<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-variant: normal; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">GetToken is a method above, that the Key Vault Client uses to fetch the authication that will be used to access both the certificate and the secrets. Notice the caller needs both secrets Get, and certificate Get access policy set in the portal for the Azure Key Vault. </span></span><br />
<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-variant: normal; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></span></span>
<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-variant: normal; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">For More Information About How GetToken Works <a href="https://docs.microsoft.com/en-us/azure/key-vault/key-vault-developers-guide">https://docs.microsoft.com/en-us/azure/key-vault/key-vault-developers-guide</a></span></span><br />
<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-variant: normal; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></span></span>
<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-variant: normal; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-variant: normal; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="-webkit-text-stroke-width: 0px; background-color: white; color: #333333; display: inline !important; float: none; font-family: Georgia,Serif; font-size: 13.33px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">{6230289B-5BEE-409e-932A-2F01FA407A92}</span><b></b><i></i><u></u><sub></sub><sup></sup><strike></strike></span></span><br />
<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-variant: normal; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><b></b><i></i><u></u><sub></sub><sup></sup><strike></strike><br /></span></span>
<span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-variant: normal; letter-spacing: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><span style="background-color: white; color: black; display: inline; float: none; font-family: "times new roman"; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></span></span>Wayne Walter Berryhttp://www.blogger.com/profile/07116744675621334568noreply@blogger.com0tag:blogger.com,1999:blog-3923359343089034996.post-3861086301187027922018-06-24T07:51:00.001-07:002018-06-24T07:51:57.538-07:00Regex to search VSCode for Azure subscription keysBefore you check in code, make sure the Azure subscription keys are removed or replaced with obvious markers.<br />
<br />
In VSCode, select the magnifying glass, the select the last icon on the line, "*." indicating the search is by regular expression. Enter <b>[a-z0-9]{32}</b> in the search text box and select enter.<br />
<br />
The search results appear below the search text box. Scan the results for any highlighted keys that are real key values.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq8izMQvT9vLs6thzrOl7mFw0qgJtM3CY1n6gA0U9UXMlFWnhxhyphenhyphenuc50mODSpETctdk8_AiqWbh9vB7_hPnj7aIC3UENtzjtORVgUg-ZnOh0GBPPA8AK1OWcpjr9iinWWm-nHZg67PcKA/s1600/regex-subscription-key.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="728" data-original-width="1366" height="340" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq8izMQvT9vLs6thzrOl7mFw0qgJtM3CY1n6gA0U9UXMlFWnhxhyphenhyphenuc50mODSpETctdk8_AiqWbh9vB7_hPnj7aIC3UENtzjtORVgUg-ZnOh0GBPPA8AK1OWcpjr9iinWWm-nHZg67PcKA/s640/regex-subscription-key.png" width="640" /></a></div>
<br />Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-17112222116143097322018-05-16T15:38:00.000-07:002018-05-16T15:38:17.612-07:00Changing TLS setting for Azure web apps including Bot FrameworkIf you need to change the TLS setting for you Azure web apps, including Bot Framework apps, go to the Azure portal. In the left navigation, select <b>All Resources</b>, sort the table by the type column.<br />
<br />
Any row with the type of <b>app service</b> may need the TLS setting updated based on on the service announcement <a href="https://github.com/Azure/app-service-announcements/issues/104">here</a>.<br />
<br />
On each service, select the <b>SSL section</b>, and change the <b>Minimum TLS Version</b>.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisY1xA0UEW9iylVltb3tG5yM6RGJIW6ujmWXCxHcrBw0BYa2ZRQlIg7Z7uImpFCF0ZkBwsX_1TLHKT813hr0rSkQaHX4VtspkQpR0awp8zV3AoqP30y_jUDyNBQDtm48W3X9Ei6aUs2O4/s1600/Untitled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1004" data-original-width="964" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisY1xA0UEW9iylVltb3tG5yM6RGJIW6ujmWXCxHcrBw0BYa2ZRQlIg7Z7uImpFCF0ZkBwsX_1TLHKT813hr0rSkQaHX4VtspkQpR0awp8zV3AoqP30y_jUDyNBQDtm48W3X9Ei6aUs2O4/s640/Untitled.png" width="614" /></a></div>
Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-69991727100680031682018-01-20T11:04:00.001-08:002018-01-20T11:04:59.229-08:00Community TypeScript conference in SeattleSeattle is getting its own community-driven <a href="https://tsconf.io/">TypeScript conference</a> March 12, 2018. <a href="https://ti.to/SitePen-Consulting/tsconf-2018">Get your tickets now. </a>Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-75756408263050317132018-01-16T08:23:00.000-08:002018-01-16T08:23:44.459-08:00Curl command for Microsoft Cognitive Services product QnA MakerThis is the curl command to send <a href="https://www.qnamaker.ai/">QnA Maker</a> a question and receive the answer:<br />
<br />
<span style="background-color: white; color: #212121; font-family: "Lucida Console", serif, EmojiFont; font-size: 12px;">curl -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key:<subscriptionKey>" -X POST -d '{"question":"<question>"}' https://westus.api.cognitive.microsoft.com/qnamaker/v2.0/knowledgebases/<appID>/generateAnswer</span><br />
<span style="background-color: white; color: #212121; font-family: "Lucida Console", serif, EmojiFont; font-size: 12px;"><br /></span>
<subscriptionKey> found on <a href="https://www.qnamaker.ai/UserSettings">https://www.qnamaker.ai/UserSettings</a><br />
<appID> found in url when view app, ?kbid=<appID><br />
<question> question such as "How do I ...?"Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-21624084507730585022018-01-15T13:06:00.000-08:002018-01-15T13:06:30.256-08:00Debug mocha.js with VSCodeThis is my cheat sheet for debugging the <a href="https://github.com/mochajs/mocha">mocha.js</a> project from <a href="https://code.visualstudio.com/">VSCode</a> while adding fixes to it. This is <b>not</b> about how to debug ANY project that is using mocha for testing.<br />
<br />
The mocha.js repository has a build system that builds into /bin/mocha.<br />
<br />
I don't use a <b>package.json</b> script. I just use a <b>launch.json</b> mocha test configuration:<br />
<br />
<div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Consolas, "Courier New", monospace; font-size: 14px; line-height: 19px; white-space: pre;">
<div>
{</div>
<div>
<span style="color: #608b4e;">// Use IntelliSense to learn about possible attributes.</span></div>
<div>
<span style="color: #608b4e;">// Hover to view descriptions of existing attributes.</span></div>
<div>
<span style="color: #608b4e;">// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387</span></div>
<div>
<span style="color: #9cdcfe;">"version"</span>: <span style="color: #ce9178;">"0.2.0"</span>,</div>
<div>
<span style="color: #9cdcfe;">"configurations"</span>: [</div>
<div>
{</div>
<div>
<span style="color: #9cdcfe;">"type"</span>: <span style="color: #ce9178;">"node"</span>,</div>
<div>
<span style="color: #9cdcfe;">"request"</span>: <span style="color: #ce9178;">"launch"</span>,</div>
<div>
<span style="color: #9cdcfe;">"name"</span>: <span style="color: #ce9178;">"Mocha Tests"</span>,</div>
<div>
<span style="color: #9cdcfe;">"program"</span>: <span style="color: #ce9178;">"${workspaceFolder}/bin/_mocha"</span>,</div>
<div>
<span style="color: #9cdcfe;">"args"</span>: [</div>
<div>
<span style="color: #ce9178;">"--colors"</span>,</div>
<div>
<span style="color: #ce9178;">"${workspaceFolder}/test/reporters/dina.spec.js"</span></div>
<div>
],</div>
<div>
<span style="color: #9cdcfe;">"internalConsoleOptions"</span>: <span style="color: #ce9178;">"openOnSessionStart"</span></div>
<div>
}</div>
<div>
]</div>
<div>
}</div>
</div>
<br />
<br />
<ul>
<li>The program value has to be changed from the node_modules directory to the /bin directory. The top level file is supposed to be bin/_mocha but it won't debug. </li>
<li>Remove any <b>timeout args</b> from the args array. </li>
<li>Specify the exact file you want to debug into such as "dina.spec.js"</li>
</ul>
Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-91369988149808975242017-10-15T07:25:00.000-07:002017-10-15T07:27:06.667-07:00Paperspace.com for Windows 10 Desktops in the cloudI recently needed a clean Windows 10 desktop for testing purposes. I couldn't use Docker, Vagrant, VirtualBox or any of the other local-to-my-computer VM solutions. I tried the Amazon Workspaces solution but it had the typical UX of 30 questions I don't know the answer to. I just wanted a desktop that could download from the Internet.<br />
<br />
<a href="http://paperspace.com/">Paperspace.com</a> to the rescue!<br />
<br />
Within 5 minutes I had a Windows 10 desktop in a browser and the hardest questions where how much CPU and ram I wanted. The cost was incredibly inexpensive too.<br />
<br />
The test only took 10 minutes and I destroyed the cloud machine after that.<br />
<br />
This was the easiest, fastest, and cheapest solution to the problem.Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-32196275719304398202017-09-18T13:37:00.002-07:002017-09-18T13:39:39.307-07:00SQL Server AAD Authentication ErrorAre you seeing this error from your ADO.NET Code Trying to Connect To Your SQL Server via Active Directory Authentication:
<br />
<br />
<i>Exception=System.Data.SqlClient.SqlException (0x80131904): Failed to authenticate the user NT Authority\Anonymous Logon in Active Directory (Authentication=ActiveDirectoryIntegrated). Error code 0x800703FA; state 10 Illegal operation attempted on a registry key that has been marked for deletion. </i><br />
<i>
</i>
<br />
The issue might be that you are running a windows service or a scheduled task with a user that has logged off. In Windows Server the registry hive for the current user is loaded when the user logs into the machine, and unloaded when they log off. This means that if you service account is running under a user that is logged off then the registry hive will not be available. ADO.NET AAD in .NET 4.6.1 uses the registry hive of the running user -- which could be the user of a service. <br />
<br />
To solve this problem you need to tell Windows Server not to unload the registry hive for users when they log off.
<br />
<br />
{6230289B-5BEE-409e-932A-2F01FA407A92}
<br />
<br />
<br />
Wayne Walter Berryhttp://www.blogger.com/profile/07116744675621334568noreply@blogger.com0tag:blogger.com,1999:blog-3923359343089034996.post-30394707573600839792017-09-18T12:18:00.001-07:002017-09-19T11:59:49.937-07:00The Asp.net Core 2.0 Environment for NodeJs Developers <h2>
NodeJs & .Net Core</h2>
<a href="https://nodejs.org/en/">NodeJs</a> and the <a href="https://www.asp.net/">Asp.net</a> ecosystems have used very different paradigms until recently. This article will show you where they are similar – the 10,000 feet view – when using the Asp.net Core 2.0 environment. <br />
<br />
With NodeJs, as the developer you might have chosen to build a web server or a cli tool. Your favorite interactive development environment (IDE) might just be a terminal window or Google Chrome DevTools. <br />
<br />
With Asp.net (not .Net Core), Microsoft provided the web server (<a href="https://www.iis.net/">IIS</a>) and the IDE (<a href="https://www.visualstudio.com/">Visual Studio</a>). You can develop many different applications including web sites and cli tools. With <a href="https://www.microsoft.com/net/download/core">.Net Core 2.0</a>, the focus is on portable code, and the result feels much closer to NodeJs. <br />
<br />
For this article, I'm going to ignore all issues that would make the comparison apples to oranges and instead focus on issues that make the comparison apples to apples. <br />
<br />
Moving forward, any reference to Asp.net Core 2.0 will be just .<b>Net Core</b>. NodeJs 6.9.1 will be just <b>Node</b>. The example project name will be <b>kittens</b> so you can see how it is used when it is relevant.<br />
<h2>
Text Only</h2>
The files of both .Net Core and Node are both text files. A project has a single configuration file. The top of each code file references the libraries that are used in the file. <br />
<br />
In .Net Core 1.0, the project file was a <a href="https://docs.npmjs.com/files/package.json">package.json</a>, but in .Net Core 2.0, the project file is a <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/csproj">*.csproj </a>file. The package file for .Net Core is created with the cli of <b>"dotnet new..."</b>. The XML of the .Net Core file will be familiar to .Net developers. <br />
<br />
<Project Sdk="Microsoft.NET.Sdk"><br />
<PropertyGroup><br />
<OutputType>Exe</OutputType><br />
<TargetFramework>netcoreapp2.0</TargetFramework><br />
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;linux-x64;ubuntu.14.04-x64</RuntimeIdentifiers><br />
</PropertyGroup><br />
<ItemGroup><br />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /><br />
</ItemGroup><br />
</Project><br />
<br />
In Node, the project file is the package.json created by the NPM cli of <b>"npm init"</b> with the result of a JSON object containing information about the project. I added expressjs to the package so the dependencies object would have an entry.<br />
<br />
{<br />
"name": "kittens",<br />
"version": "1.0.0",<br />
"description": "",<br />
"main": "kittens.js",<br />
"scripts": {<br />
"test": "echo \"Error: no test specified\" && exit 1"<br />
},<br />
"keywords": [],<br />
"author": "",<br />
"license": "ISC",<br />
"dependencies": {<br />
"express": "^4.15.4"<br />
}<br />
}<br />
<br />
In their own way, each of the package files configure the project but in very different ways. The .Net Core file is focused on the .Net Core version and final built assets of the project – things the compiler and dependencies need to run. <br />
<br />
The Node package.json file lists all dependencies to pull in, as well as meta data about the project – it is the single location a developer touches to control the project as a whole, including building and testing. I usually have a long list of items in the Node package.json scripts section for building, testing, and running. <br />
<h2>
Execution </h2>
Both Node and .Net Core applications are built via terminal/command line. Both are executed in the context of the parent application: <b>dotnet </b>or <b>node</b>.<br />
<br />
While Node needs a single point of entry of a javascript file, such as kitten.js, .Net Core uses the project name (<name>.csproj). <br />
<br />
> node kittens.js<br />
<br />
> dotnet kittens.dll<br />
<br />
Dependencies are added to Node projects with the <a href="https://www.npmjs.com/">npm</a> or <a href="https://yarnpkg.com/en/">yarn</a> package managers. The dependencies are placed in a folder named node_modules. <br />
<br />
> npm add <packagename><br />
<br />
For .Net Core dependencies, use the <a href="https://www.nuget.org/">NuGet</a> package manager. There isn't a single list of dependencies in a human readable format that is opened/viewed by developers on a regular basis. <br />
<br />
> dotnet add package <packagename><br />
<br />
Both npm and dotnet allow you to specify versions but it is optional. Npm and yarn have been dealing with package interdepencies and version conflicts. I believe both are now able to avoid version conflicts of interdepencies.<br />
<h2>
Deployment </h2>
Both platforms allow you to <b>'git clone'</b> then install the package dependencies and run.<br />
<br />
.Net Core uses a folder containing many files depending on the execution platform (windows, mac, linux). For Node, just install and run a single file. Node will then find the rest of the files.<br />
<br />
> dotnet restore && dotnet ./<path-to-bin-directory>/kittens.dll<br />
<br />
> npm install && node kittens.js<br />
<h2>
Serverless </h2>
The reason I mention <a href="https://en.wikipedia.org/wiki/Serverless_computing">serverless</a> is you may not want to deal with the execution environment details. <br />
Node has a variety of host platforms and open-source projects to run serverless. <br />
<br />
Currently, the best way to run .Net Core serverless right now is <a href="https://azure.microsoft.com/en-us/services/functions/">Azure Functions</a>. While there are other platforms such as <a href="https://aws.amazon.com/lambda/">AWS Lamdba</a> that can run .Net Core code, those platforms may be slightly behind (or vastly behind) release .Net Core platform ability.<br />
<h2>
Docker </h2>
Docker containers are a great way to develop and deploy applications. I always look for owner created containers. If it works for them, it will work for me.<br />
<br />
Here are the owner created containers for each:<br />
<br />
<a href="https://hub.docker.com/_/node/">node</a><br />
<a href="https://hub.docker.com/r/microsoft/aspnetcore/">microsoft/aspnetcore</a><br />
<br />
For Node, the specific owner container isn't that interesting because there are a million ways you may want to run Node and a different container may get you much closer to your needs in terms of dependencies and tools. <br />
<br />
For .Net Core, the owner container is probably the best bet for the short-term while the project is still new-ish.<br />
<br />
<br />Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-49979709491945456112017-05-07T15:46:00.000-07:002017-05-07T15:47:03.205-07:00Agile Manifesto -- Some 16 years later"<span style="background-color: #ececec; color: #333333; font-family: "arial" , sans-serif; font-size: 16px;">In 2001, 17 individuals gathered in the Wasatch mountains of Utah to find common ground around Agile. After much skiing, talking, relaxing, and eating, they arrived at four common values that led to the development of the Agile Manifesto."[<a href="https://www.scrumalliance.org/why-scrum/core-scrum-values-roles" target="_blank">source</a>] [<a href="https://en.wikipedia.org/wiki/Agile_software_development#The_Agile_Manifesto" target="_blank">Wikipedia</a>]</span><br />
<span style="background-color: #ececec; color: #333333; font-family: "arial" , sans-serif; font-size: 16px;"><br /></span>
<span style="background-color: #ececec; color: #333333; font-family: "arial" , sans-serif; font-size: 16px;">Going to <a href="http://agilemanifecto.org/">AgileManifecto.org</a>, we see just 14 people listed, what appears to be their feeling on what promised so much hope some 15 years ago.</span><br />
<span style="background-color: #ececec; color: #333333; font-family: "arial" , sans-serif; font-size: 16px;"><br /></span>
<br />
<table style="width: 600px;"><tbody>
<tr><td><br />
<ol>
<li><b style="font-size: large;">Mike Beedle</b><span style="font-size: medium;"> </span></li>
<li><b style="font-size: large;">Arie van Bennekum</b></li>
<li><b style="font-size: large;">Alistair Cockburn</b></li>
<ol>
<li><b style="font-size: large;">"</b> “Agile has become overly decorated. Let’s scrape away those decorations for a minute, and get back to the center of agile. The center of agile is … ” [<a href="http://alistair.cockburn.us/Rediscovering+the+Heart+of+Agile" target="_blank">2015</a>]</li>
</ol>
<li><b style="font-size: large;">Ward Cunningham</b></li>
<ol>
<li><b style="font-size: large;">"</b> "I have seen my ideas diluted as they diffused through the industry". You said "I’d much rather move to the next idea than struggle to keep the last idea pure." [<a href="https://www.infoq.com/interviews/ward-cunningham-agile-10" target="_blank">2011</a>]</li>
</ol>
<li><b style="font-size: large;"><a href="http://www.martinfowler.com/">Martin Fowler</a></b></li>
<li><a href="http://jimhighsmith.com/" style="font-size: large;"><b>Jim Highsmith</b></a><span style="font-size: medium;"> - </span></li>
<ol>
<li><span style="font-size: medium;"><a href="http://jimhighsmith.com/dont-try-control-agile-projects/" target="_blank">Don’t “Control” Agile Projects</a></span></li>
<li><a href="http://jimhighsmith.com/agile-bureaucracy-when-practices-become-principles/" target="_blank">Agile Bureaucracy: When Practices become Principles</a></li>
</ol>
<li><b style="font-size: large;">Andrew Hunt <a href="http://blog.toolshed.com/2015/05/the-failure-of-agile.html" target="_blank">The Failure of Agile (2015)</a></b></li>
<li><b style="font-size: large;">Ron Jeffries</b></li>
<ol>
<li><span style="font-size: medium;"><b>Do you want Crappy Agile? [<a href="http://ronjeffries.com/articles/016-03/you-want/" target="_blank">2016</a>] "</b></span> it encourages you to track “metrics”. Do you want Crappy Agile? That’s how you get Crappy Agile, at least far too often."</li>
<li>"Scrum is good, when done as intended. Otherwise it can be oppressive and dangerous to developers. Let's study: Defense Against the Dark Arts of Scrum." <a href="http://ronjeffries.com/articles/016-09ff/defense/" style="background-color: #ececec; color: #1756a9; font-family: Helvetica, Arial, sans-serif; font-size: 22px; text-decoration-line: none;">Dark Scrum</a></li>
</ol>
<li><b style="font-size: large;">Jon Kern</b></li>
<ol>
<li><b style="font-size: large;">"</b>The only thing that has me mildly torn--and only mildly, because "to each his own" and "what-evs" come to mind--is the craze surrounding Scrum. Scrum, scrum, scrum, scrum. Part of me is happy that there are legions out there turning the sod under, trying to sow the agile seeds via Scrum. Another part of me thinks it is like Corn-to-Ethanol. A waste of energy for the dumbfounded among us, spurred on by lots of lobbying." [<a href="http://www.informit.com/articles/article.aspx?p=1739476" target="_blank">2011</a>]</li>
<li>Have not posted on his blog about agile since 2011</li>
</ol>
<li><b style="font-size: large;">Brian Marick</b><span style="font-size: medium;"> "</span>In his keynote at the <a href="http://www.sqe.com/Agiledevpractices/" style="background-color: white; border: 0px; color: #286ab2; font-family: Arial, Helvetica, sans-serif; font-size: 14px; margin: 0px; outline: none !important; padding: 0px; text-decoration-line: none;">Agile Development Practices</a><span style="background-color: white; font-family: "arial" , "helvetica" , sans-serif; font-size: 14px;"> conference, </span><a href="http://www.exampler.com/about.html" style="background-color: white; border: 0px; color: #286ab2; font-family: Arial, Helvetica, sans-serif; font-size: 14px; margin: 0px; outline: none !important; padding: 0px; text-decoration-line: none;">Brian Marick</a><span style="background-color: white; font-family: "arial" , "helvetica" , sans-serif; font-size: 14px;"> described values missing from the </span><a href="http://www.agilemanifesto.org/" style="background-color: white; border: 0px; color: #286ab2; font-family: Arial, Helvetica, sans-serif; font-size: 14px; margin: 0px; outline: none !important; padding: 0px; text-decoration-line: none;">Agile Manifesto</a><span style="background-color: white; font-family: "arial" , "helvetica" , sans-serif; font-size: 14px;">. His view is that the Manifesto was essentially a marketing document, aimed at getting business to give agile a chance." [<a href="https://www.infoq.com/news/2008/11/Marick-on-Agile-Manifesto" target="_blank">2008</a>]</span></li>
<ol>
<li><span style="background-color: white; font-family: "arial" , "helvetica" , sans-serif; font-size: 14px;">"</span>As Agile moves into bigger companies and into less adventurous ones, those undocumented values are getting watered down. If that continues, I’m afraid Agile will be this decade’s fad that changes nothing."</li>
</ol>
<li><b style="font-size: large;">Robert C. Martin (aka Uncle Bob) moved on to "Clean Code" </b></li>
<li><b style="font-size: large;">Ken Schwaber owns Scrum.org</b></li>
<li><b style="font-size: large;">Jeff Sutherland CEO of Scrum Inc</b></li>
<li><b style="font-size: large;">Dave Thomas </b><h3 class="r" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 18px; font-weight: normal; margin: 0px; overflow: hidden; padding: 0px; text-overflow: ellipsis; white-space: nowrap;">
<a href="https://pragdave.me/blog/2014/03/04/time-to-kill-agile.html" style="color: #660099; cursor: pointer;">Agile is Dead (Long Live Agility) - PragDave</a></h3>
</li>
<li><div>
<h3 class="r" style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 18px; font-weight: normal; margin: 0px; overflow: hidden; padding: 0px; text-overflow: ellipsis; white-space: nowrap;">
<a href="https://www.youtube.com/watch?v=a-BOSpxYJ9M" style="color: #660099; cursor: pointer;">GOTO 2015 • Agile is Dead • Pragmatic Dave Thomas - YouTube</a></h3>
</div>
</li>
</ol>
<div>
<span style="font-size: medium;"><b>Missing are: [<a href="https://www.slideshare.net/FreekHermkens/the-agile-manifesto" target="_blank">source</a>]</b></span></div>
<div>
<ul>
<li><b style="font-size: large;">Kent Beck - does not mention it</b><b style="font-size: large;"> on <a href="https://www.facebook.com/notes/kent-beck/" target="_blank">his facebook</a> site...</b></li>
<li><b style="font-size: large;">James Grenning</b></li>
<ul>
<li><b style="font-size: large;"><a href="http://blog.wingman-sw.com/archives/568" target="_blank">Why do engineers dislike Agile</a> "</b>As it turns out, Agile as practiced is dominated with management in 2016. "</li>
</ul>
<li><b style="font-size: large;">Steve Mellor moved on to </b><a href="http://www.amazon.com/MDA-Distilled-Stephen-J-MELLOR/dp/0201788918" style="background-color: white; color: #0088cc; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; text-align: justify; text-decoration-line: none;">MDA Distilled: Principles of Model-Driven Architecture</a><span style="background-color: white; color: #333333; font-family: "helvetica neue" , "helvetica" , "arial" , sans-serif; font-size: 14px; text-align: justify;">,as well as the use of UML.</span></li>
</ul>
<h2 style="text-align: justify;">
<span style="color: #333333; font-family: "helvetica neue" , "helvetica" , "arial" , sans-serif;"><span style="font-size: 14px;">Question - Agile is good if selling it is your bread and butter</span></span></h2>
</div>
<div>
<span style="color: #333333; font-family: "helvetica neue" , "helvetica" , "arial" , sans-serif;"><span style="font-size: 14px;">Many agile signatures appear to have become disillusioned by how Agile is commonly being adapted in the industry. Some people have stopped writing and posting on it. Others have proposed derivatives of it in the hope of getting back to core values. Others are making a good living from preaching the gospel of agile.</span></span></div>
<div>
<span style="font-size: medium;"><b><br /></b></span></div>
<div>
<span style="font-size: medium;"><b>My view? </b> Simple, I started using RAD back in 1979 and been using the concepts (without the dogma) for the last 37 years. The best implementation have been where the product owner/customer was very technical and detail orientated and put in the needed hours. The worst cases were scrum was magically expected to make management easy and not require their heavy engagement or hours with the products they owned or manage.</span></div>
<div>
<span style="font-size: medium;"><br /></span></div>
<div>
<span style="font-size: medium;">I like the concepts and practice them instinctively, I hate the "rote-application of the manifesto" </span></div>
<div>
<span style="font-size: medium;"><b><br /></b></span></div>
</td></tr>
</tbody></table>
Ken Lassesen, Dr.Gui (MSDN) retiredhttp://www.blogger.com/profile/13429731290092618600noreply@blogger.com0tag:blogger.com,1999:blog-3923359343089034996.post-24447140550833124892017-05-01T08:35:00.000-07:002017-05-01T12:54:42.539-07:00Running Tests in Docker for Front-end Developers (ng2+)<h4>Unit tests (karma/jasmine) & End-to-end tests (protractor)</h4>If you are comfortable with Docker and Angular 2, all you need is the Dockerfile. If you are new to testing in Docker, this short article will bring you up to speed. If you need more help getting up to speed with Docker, begin with my previous article: <a href="http://www.31a2ba2a-b718-11dc-8314-0800200c9a66.com/2016/10/docker-for-angular-2-devs.html">Docker for Angular 2 devs</a>.<br />
<h4>Installation </h4>In order to develop Angular 2+ in a container, you need to <a href="https://docs.docker.com/engine/installation/">install Docker</a> on a computer or VM. Docker takes a bit of memory and can take a lot of space so the biggest box you can give it is best. Once Docker is installed, start is up.<br />
<br />
Make sure all your docker commands are run from the folder that contains the Dockerfile.<br />
<h4>Dockerfile </h4>Docker works by reading the description of a Dockerfile (or several in conjunction), to build out an image. Once the image is running, it is called a container. <br />
<br />
This particular Dockerfile is based on a Docker image that already has headless chrome, markadams/chromium-xvfb-js:7. There are several Dockerfiles at <a href="https://hub.docker.com/">Docker hub</a> for headless chrome. If this base image or my additions do not work, feel free to play around with other Dockerfiles. You will find references/websites at the bottom of this article. <br />
<h4>What Does this Dockerfile do </h4>This Dockerfile installs the angular2-webpack-starter (and all dependencies). I use it as a development environment that I connect to and run the tests myself as I develop. I'm using the angular2-webpack-starter as my base test that the Dockerfile has all the needed dependencies to complete both the unit tests and the end-to-end tests successfully.<br />
<br />
If the starter can run both types of tests, it should be fairly straightforward to add your own repository to the container for development and testing. The container has the full stack for this: Git, NPM, Yarn, Node, and Angular+, ng-cli, Webpack, Karma, Jasmine, Protractor, http-server. <br />
<h4>Why use the angular2-webpack-starter?</h4>I wanted an Angular 2+ project that used as much of the same stack as my current projects that also had unit tests and e2e tests. In order to validate I have the right Dockerfile configuration, all I have to do is run both types of tests in this repository. If they succeed, my own tests for my own projects should succeed as well.<br />
<h4>Can I see it working? </h4>Yes, I have a <a href="https://youtu.be/CgVJMTGmO9Y">short 4 minute video</a> showing it from building the docker image to the final e2e test run. I've cut out 11 minutes of Docker building the image as there is a lot of installation of dependencies.<br />
<br />
<iframe width="560" height="315" src="https://www.youtube.com/embed/CgVJMTGmO9Y" frameborder="0" allowfullscreen></iframe><br />
<br />
<h4>Using as a Development Environment </h4>I use this container as my main development & testing environment. I share my local repository folder into the container with the –v param and expose a small range of ports to allow for several front-end and api servers to run at once. <br />
<br />
The angular2-webpack-starter runs on port 3000 so I open 3000-3005. This allows you to use your host computer to access the website (http://localhost:3000) as long as the port isn't in use on your host machine. <br />
<h4>What are the important parts of the Dockerfile? </h4>There are definitely packages and settings in the Dockerfile you may not use, but there are a few you need to keep. <br />
<br />
Protractor needs to know where the Chrome bin directory is. If you remove that environment variable, Protractor will not be able to run the tests. Protractor also needs the default-jre. <br />
<br />
Getting karma/jasmine tests working in a container using headless chrome seems to be easy compared to protractor e2e tests. If you change the file, always use the protractor e2e test run as the verification that the change did no harm. <br />
<h4>Git Commit Hash </h4>Since the repositories for both my Dockerfile and the angular2-webpack-starter will change over time, I'm noting the git commit hashes of the versions I used. <br />
<br />
<a href="https://github.com/AngularClass/angular2-webpack-starter">https://github.com/AngularClass/angular2-webpack-starter</a><br />
commit e9521a42 - Sat Apr 22 19:27:33 2017 -0400<br />
<br />
<a href="https://github.com/dfberry/DockerFiles/blob/master/headless-chromium/Dockerfile">https://github.com/dfberry/DockerFiles/blob/master/headless-chromium/Dockerfile</a><br />
commit 38b7554c Sun Apr 30 13:23:17 2017 -0700<br />
<h4>References </h4><a href="https://github.com/mark-adams/docker-chromium-xvfb">https://github.com/mark-adams/docker-chromium-xvfb</a><br />
<a href="https://hub.docker.com/r/yukinying/chrome-headless/">https://hub.docker.com/r/yukinying/chrome-headless/</a><br />
<a href="https://hub.docker.com/r/justinribeiro/chrome-headless/">https://hub.docker.com/r/justinribeiro/chrome-headless/</a>Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.comtag:blogger.com,1999:blog-3923359343089034996.post-79096258897950733202016-10-20T10:05:00.000-07:002016-10-20T10:05:48.846-07:00Docker for Angular 2 devs<b>Docker is a Virtual Environment </b><br />
Docker containers are great for adding new developers to existing projects, or for learning new technologies without polluting your existing developer machine/host. Docker allows you to put a fence around the environment while still using it. <br />
<br />
<b>Why Docker for Angular 2?</b><br />
Docker is an easy way to get up and going on a new stack, environment, tool, or operating system without having to learn how to install and configure the new stack. A collection of docker images are available from <a href="https://hub.docker.com/">Docker Hub</a> ranging from simple to incredibly complex -- saving you the time and energy.<br />
<br />
Angular 2 examples frequently include a Dockerfile in the repository which makes getting the example up and running much quicker -- if you don't have to focus on package installation and configuration.<br />
<br />
The base Angular 2 development stack uses Node, TypeScript, Typings, and a build system (such as <a href="https://github.com/systemjs/systemjs">SystemJs</a> or <a href="https://webpack.github.io/">Webpack</a>). Instead of learning each stack element before/while learning Angular 2, just focus on Angular 2 itself -- by using a Dockerfile to bring up a working environment.<br />
<br />
The repositories for Angular 2 projects will have a package.json file at the root which is common for NodeJs/NPM package management projects. The Docker build will install the packages in the package management system as part of the build. The build can also transpile the typescript code , and start a static file web server -- if the package.json has a start script. <br />
<br />
In order to get a new development environment up and a new project in the browser, you just need to build the Dockerfile, then run it. Running these two commands at the terminal/cli saves you time in find and learning the Angular 2 stack, and then building and running the project.<br />
<br />
<b>The Angular 2 Quickstart</b><br />
For this article, I use the <a href="https://github.com/angular/quickstart">Angular 2 Quickstart repository</a> including the <a href="https://github.com/angular/quickstart/blob/master/Dockerfile">Dockerfile</a> found in the repository.<br />
<br />
I use a Macintosh laptop. If you are using a Windows-based computer/host, you may have more or different issues than this article.<br />
<br />
<b>Docker via Terminal/Cli</b><br />
I prefer the code-writing environment and web browser already installed and configured on my developer laptop/host. I configure the Docker container to share the hosted files. The changes are reflected in the container – and I run the Angular 2 project in watch mode so the changes immediately force a recompile in the container.<br />
<br />
<b>Viewing the Angular Project in a Browser</b><br />
Since the Angular 2 project is a website, I access the container by the port and map the container's port to the host's port – so access to the running Angular project is from a web browser on the host laptop with http://localhost:3000. <br />
<br />
<b>Install Docker </b><br />
Before you install Docker, make sure you have a bit of space on the computer. Docker, like <a href="https://www.vagrantup.com/">Vagrant</a><br />
and <a href="https://www.virtualbox.org/wiki/Downloads">VirtualBox</a>, uses a lot of space. <br />
<br />
Go to <a href="https://www.docker.com/">Docker</a> and install it. Start Docker up.<br />
<br />
<b>Check Docker </b><br />
Open a terminal/cli and check the install worked and Docker started by requesting the Docker version <br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker –v
>Docker version 1.12.1, build 6f9534c
</code></pre>
</div>
<br />
If you get a docker version as a response, you installed and started Docker correctly. <br />
<br />
<b>Images and Containers </b><br />
Docker Images are defined in the Dockerfile and represent the virtual machine to be built. The instantiation of the image is a container. You can have many containers based on one image. <br />
<br />
Each image is named and each container can also be named. You can use these names to indicate ownership (who created it), as well as base image (node), and purpose (xyzProject). <br />
<br />
Pick a naming schema for your images and containers and stick with it.<br />
<br />
I like to name my images with my github name and the general name such as dfberry/quickstart. I like to name the containers with as specific a name as possible such as ng2-quickstart.<br />
<br />
The list of containers (running or stopped) shows both names which can help you organize find the container you want.<br />
<br />
<b>The Angular 2 Docker Image </b><br />
The fastest way to get going with Docker for Angular 2 projects is to use the latest node as your base image -- which is also what the Angular 2 quickstart uses.<br />
<br />
The image has the latest node, npm, and git. <a href="https://hub.docker.com/">Docker hub</a> hosts the <a href="https://hub.docker.com/_/node/">base image</a> and <a href="https://nodejs.org/">Node</a> keeps it up to date. <br />
<br />
Docker's philosophy is that the containers are meant to execute then terminate with the least privileges possible. In order to make a container work as a development container (i.e. stay up and running), I'll show some not-best-practice choices. This will allow you to get up and going quickly. When you understand the Docker flow, you can implement your own security. <br />
<br />
<b>The Docker Images </b><br />
Docker provides no images on installation. I can see that using the command <br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker images
</code></pre>
</div>
<br />
When I build the nodejs image, it will appear in the list with information about the image.<br />
<br />
<div class="separator" style="clear: both;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1HzgO-MyGri1Q6nXU3Ywef8B5BDhUJI9MxL5IioY4lnrX2OFX4l8TpMKPD8wfEBfWEykDMivAAS4ll_P-17zJsReIrh3yHMSI7e7CiNM5MtFUls5Sqe_ehKlmDVLCS-8Ey9s3cXQcSRU/s1600/Snip20161019_5.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="82" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1HzgO-MyGri1Q6nXU3Ywef8B5BDhUJI9MxL5IioY4lnrX2OFX4l8TpMKPD8wfEBfWEykDMivAAS4ll_P-17zJsReIrh3yHMSI7e7CiNM5MtFUls5Sqe_ehKlmDVLCS-8Ey9s3cXQcSRU/s640/Snip20161019_5.png" width="640" /></a></div>
<br />
<br />
For now, the two most important columns are the REPOSITORY and IMAGE ID. The REPOSITORY field is the image name I used to build the image. My naming schema indicates my user account (dfberry) and the base image or purpose (node). This helps me find it in the image list.<br />
<br />
The IMAGE ID is the unique id used to identify the image. <br />
<br />
<b>The Dockerfile </b><br />
In order to create a docker image, you need a Dockerfile (notice the filename has no extension). This is the file the docker cli will assume you want to use. For this example, the Dockerfile is small. It has the following features:<br />
<ul>
<li>creates a group</li>
<li>creates a user</li>
<li>creates a directory structure with appropriate permissions</li>
<li>copies over the package.json file from the host</li>
<li>installs the npm packages listed in the package.json</li>
<li>runs the package.json's "start" script – which should start the website</li>
</ul>
<br />
For now, make sure this is the only Dockerfile in the root of the project, or anywhere below the root.<br />
<br />
<div style="background-color: wheat;">
<pre><code>
# To build and run with Docker:
#
# $ docker build -t ng-quickstart .
# $ docker run -it --rm -p 3000:3000 -p 3001:3001 ng-quickstart
#
FROM node:latest
RUN mkdir -p /quickstart /home/nodejs && \
groupadd -r nodejs && \
useradd -r -g nodejs -d /home/nodejs -s /sbin/nologin nodejs && \
chown -R nodejs:nodejs /home/nodejs
WORKDIR /quickstart
COPY package.json typings.json /quickstart/
RUN npm install --unsafe-perm=true
COPY . /quickstart
RUN chown -R nodejs:nodejs /quickstart
USER nodejs
CMD npm start
</code></pre>
</div>
<br />
The nodejs base image will install nodejs, npm and git. The image will just be used for building and hosting the Angular 2 project.<br />
<br />
If you have scripts that do the bulk of your build/startup/run process, change the Dockerfile to copy that file to the container and execute it as part of the build.<br />
<br />
<b> Build the Image</b><br />
<a href="https://www.blogger.com/(https://docs.docker.com/engine/reference/commandline/build/)">Usage: docker build [OPTIONS] PATH | URL | - </a><br />
<br />
In order to build the image, use the docker cli. <br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker build –t <user>/<yourimagename> .
Example $: docker build –t dfberry/ng-quickstart .
</code></pre>
</div>
<br />
<br />
If you don't want to annotate the user, just leave that off.<br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker build –t <yourimagename> .
Example $: docker build –t ng-quickstart .
</code></pre>
</div>
<br />
Note: the '.' at the end of the string is the url/location of the Dockerfile. I could have used a Github repository url instead of the local folder.<br />
<br />
In the above examples, the REPOSITORY name is 'ng-quickstart'. If you don't use the –t naming param, your image will have a name of <none> which is annoying when they pile up on a team server.<br />
<br />
The build will give you some feedback to let you know how it is going.<br />
<br />
<div style="background-color: wheat;">
<pre><code>
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM node:latest </code></pre>
<pre><code>
... </code></pre>
<pre><code>
Removing intermediate container 2cb50f334393
Successfully built 1265b22b5b90
</code></pre>
</div>
<br />
Since the build can return a lot of information, I didn't include the entire response. <br />
<br />
The build of the quickstart takes less than a minute on my Mac.<br />
<br />
The last line gives you the IMAGE ID. Remember to view all docker images after building to check it worked as expected.<br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker images
</code></pre>
</div>
<br />
<b> Run the Container</b> <br />
<a href="https://docs.docker.com/engine/reference/run/">Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] </a><br />
<br />
Now that the image is built, I want to run the image to see the website.<br />
<br />
If you don't have an Angular 2/Typescript website, use the <a href="https://github.com/angular/quickstart">ng2 Quickstart</a>. <br />
<br />
<b>Run switches</b><br />
The run command has a lot of switches and configurations. I'll walk you through the choices for this container.<br />
<br />
I want to name the container so that I remember the purpose. This is optional but helpful when you have a long list of containers.<br />
<br />
<div style="background-color: wheat;">
<pre><code>
--name ng2-quickstart
</code></pre>
</div>
<br />
I want to make sure the container's web ports are matched to my host machine's port so I can see the website as http://localhost:3000. Make sure the port isn't already in use on your host machine.<br />
<br />
<div style="background-color: wheat;">
<pre><code>
-p 3000:3000
</code></pre>
</div>
<br />
I want to map my HOST directory (/Users/dfberry/quickstart to the container's directory (/home/nodejs/quickstart) that was created in the build so I can edit on my laptop and the changes are reflected in the container. The /home/nodejs/quickstart directory was created as part of the Dockerfile.<br />
<br />
<div style="background-color: wheat;">
<pre><code>
-v /Users/dfberry/quickstart/:/home/nodejs/quickstart
</code></pre>
</div>
<br />
I want the terminal/cli to show the container's responses including transpile status and the file requests.<br />
<br />
<div style="background-color: wheat;">
<pre><code>
-it
</code></pre>
</div>
<br />
<br />
The full command is:<br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker run -it -p 3000:3000 -v /Users/dfberry/quickstart:/home/nodejs/quickstart --name ng2-quickstart dfberry/ng-quickstart
</code></pre>
</div>
<br />
Notice the image is named dfberry/ng-quickstart while the container is named ng2-quickstart.<br />
<br />
Run the "docker run" command at the terminal/cli.<br />
<br />
The container should be up and the website should be transpiled and running.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE1xez7jUDkd0AHfcSkIa5AEXSGZIy-NBIhKuXH0SwmoDG1d3xE7-SDckYxp27SH3y8covMQ65vZDwWZ55c2r4e2ZKT3dfiKyyVZpunSzs7lzZbFJaVLz1apVt1iYoX93e1wD4PriMjfE/s1600/Snip20161019_7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="336" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE1xez7jUDkd0AHfcSkIa5AEXSGZIy-NBIhKuXH0SwmoDG1d3xE7-SDckYxp27SH3y8covMQ65vZDwWZ55c2r4e2ZKT3dfiKyyVZpunSzs7lzZbFJaVLz1apVt1iYoX93e1wD4PriMjfE/s640/Snip20161019_7.png" width="640" /></a></div>
<br />
At this point, you should be able to work on the website code on your host with your usual editing software and the changes will reflect in the container (re-transpile changes) and in the web browser.<br />
<br />
<b>List Docker Containers</b><br />
In order to see all the containers, use<br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker ps -a
</code></pre>
</div>
<br />
If you only want to see the running containers, leave the -a off. <br />
<br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker ps
</code></pre>
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBEbbfcwb2aXbYnKen2jHO2kfAFJxnOmTQabg5-eVTbf48TxpdITz12qhrRCBljoacnkzlYDwj8c9WeXDJIWMRx-P5PbbtPv8DQ7Tre0IkCUpaqn1nYjqbLPMvKrB-jg3-gUyQp_1pKaU/s1600/Snip20161019_9.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="17" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBEbbfcwb2aXbYnKen2jHO2kfAFJxnOmTQabg5-eVTbf48TxpdITz12qhrRCBljoacnkzlYDwj8c9WeXDJIWMRx-P5PbbtPv8DQ7Tre0IkCUpaqn1nYjqbLPMvKrB-jg3-gUyQp_1pKaU/s640/Snip20161019_9.png" width="640" /></a></div>
<br />
<br />
At this point, the easy docker commands are done and you can work on the website and forget about Docker for a while. When you are ready to stop the container, stop Docker or get out of interactive mode, read on.<br />
<br />
<b>Interactive Mode (-it) versus Detached Mode (-d) </b><br />
Interactive Mode means the terminal/cli shows what is happening to your website in the container. Detached mode means the terminal/cli doesn't show what is happening and the terminal/cli returns to your control for other commands on your host.<br />
<br />
To move from interactive to detached mode, use control + p + control + q.<br />
<br />
This leaves the container up but you have no visual/textual feedback about how the website is working from the container. You can use the developer tools/F12 in the browser to get a sense, but won't be able to see http requests and transpiles.<br />
<br />
You are either comfortable with that or not.<br />
<br />
If you want the interactive mode and the website transpile/http request information, don't exit interactive mode. Instead, use control + c. This command stops and removes the container from Docker, but doesn't remove the image. You can re-enter interactive mode with the same run command above.<br />
<br />
If you are more comfortable in detached mode, where the website gives transpiles and http request information via a different method such as logging to a file or cloud service, change the docker run command.<br />
<br />
Instead of using –it as part of the "docker run" command, use –d for detached mode.<br />
<b><br /></b>
<b>Exec Mode to run commands on container</b> <br />
<a href="https://docs.docker.com/engine/reference/commandline/exec/">Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]</a><br />
<br />
When you want to connect to the container, you the same -it for interactive mode but with "docker exec." The end command tells the docker container what environment to enter in the container -- such as the bash shell. <br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker exec –it ng2-quickstart /bin/bash
</code></pre>
</div>
<br />
You can log in as root if you need elevated privileges.<br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker exec –it –u root ng2-quickstart /bin/bash
</code></pre>
</div>
<br />
The terminal/cli should now show the prompt changed to indicate you are now on the container: <br />
<br />
<div style="background-color: wheat;">
<pre><code>
nodejs@faf83c87c12e:/quickstart$
</code></pre>
</div>
<br />
When you are done running the commands, use control + p + control + q to exit. The container is still running. <br />
<br />
<b>Sudo or Root</b><br />
In this particular quickstart nodejs docker container, sudo has not been installed. Sudo may be your first choice and you can install. Or you could use the "docker exec" with root. Either way has pros and cons.<br />
<br />
<b>Stopping and Starting the Container </b><br />
When you are done with the container, you need to stop it. You can stop, and restart it as you need by container id or name.<br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker stop ng2-quickstart
docker stop 7449222ec26b </code></pre>
<pre><code>
docker start ng2-quickstart
docker start 7449222ec26b
</code></pre>
</div>
<br />
Stopping the container may take some time – be patient. Mine takes up to 10 seconds on my Mac. When you restart the container, it is in detached mode. If you really want interactive mode, remove the container, and use docker run again with –it.<br />
<br />
<b>Cleanup </b><br />
Make sure to stop all containers when they are not needed. When you are done with a container, you can remove it<br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker rm –fv ng2-quickstart
</code></pre>
</div>
<br />
When you are done with an image, you can remove that as well <br />
<br />
<div style="background-color: wheat;">
<pre><code>
docker rmi ng-quickstart
</code></pre>
</div>
<br />
<b>Stop Docker</b><br />
Remember to stop Docker when you are done with the containers for the moment or day.Dina Berryhttp://www.blogger.com/profile/17551385503209857751noreply@blogger.com2tag:blogger.com,1999:blog-3923359343089034996.post-58606790406182273162016-09-05T10:32:00.001-07:002016-09-05T10:32:59.733-07:00An interesting Interview Question: Fibonacci Sequence<p>Write a function to calculate the nth Fibonacci Sequence is a common interview question and often the solution is something like</p> <p> </p> <p>int Fib(int n)</p> <p>{</p> <p>   if(n < 1) return 1;</p> <p>   return Fib(n-1) + Fib(n-2);</p> <p>}</p> <p> </p> <p>The next question is to ask <strong>for n=100, how many items will be on the stack</strong>. The answer is not 100 but actually horrible! It is closer to 2^100.</p> <p>take the first call – we start a stack on Fib(99) and one on Fib(98). There is nothing to allow Fib(99) to <em>borrow </em>the result of Fib(98).  So one step is two stack items to recurse.  Each subsequent call changes one stack item into 2 items.   For example</p> <ul> <li>2 –> call [Fib(1), Fib(0)]</li> <li>3 –> calls [ Fib(2)->[Fib(1), Fib(0)], Fib(1) –> Fib(0) ]</li> <li>4 –> calls [ Fib(3)->[[[ Fib(2)->[Fib(1), Fib(0)], Fib(1) –> Fib(0) ]], Fib(2)->[Fib(1), Fib(0)], Fib(1) –> Fib(0) ]</li> </ul> <p>Missing this issue is very often seen with by-rote developers (who are excellent for some tasks).</p> <p> </p> <p>A better solution is to cache the values as each one is computed – effectively creating a lookup table. You are trading stack space for memory space.</p> <p> </p> <p>Placing constraints on memory and stack space may force the developer to do some actual thinking. A solution that conforms to this is shown below</p> <p> </p> <p>  private static long Fibonacci(int n) { <br />        long a = 0L; <br />        long b = 1L; <br />        for (int i = 31; i >= 0; i—)  //31 is arbitrary, see below</p> <p>        { </p> <p>            long d = a * (b * 2 - a); <br />            long e = a * a + b * b; <br />            a = d; <br />            b = e; <br />            if ((((uint)n >> i) & 1) != 0) { <br />                long c = a + b; <br />                a = b; <br />                b = c; <br />                } <br />           } <br />        return a; <br />    }</p> <p> </p> <p>The output of the above shows what is happening  and suggests that the ”31”  taking the log base 2 of N can likely be done to improve efficiency</p> <p><a href="https://lh3.googleusercontent.com/-jbpMFGaAn4k/V82sOXqIhkI/AAAAAAAALEk/MjtppB_zIrk/s1600-h/image%25255B3%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjN-3kcDYypN6ICdE6vXoCoQoFu9RHJ6FCfNwl3Nbk-OvbQatbNfy-s35y0roh31Ykge6kIGYFDq3BB0QIpyc0-SQFfVCJvCSUdL5WTeBwDmvblOU_pxJ7sFLrxhIOvlUN0XLjIawAlWjq8/?imgmax=800" width="394" height="397" /></a></p> <p>for 32:</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEB7loaubi5kKkFDDtibeyvQD6gmTk8ztDbHpzENDEL2W_XRPL23ilv8yX-Enf37Aep0mOJ1uA7yhGfBeIlLaGQj8SRvng21VdbvrP3LG7ZBBlIMBncgDX7jBxr10513i59NNCcOaSDPee/s1600-h/image%25255B10%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://lh3.googleusercontent.com/-ACC5SuR3fJs/V82sP90PQjI/AAAAAAAALEw/APIdsqyCrjw/image_thumb%25255B4%25255D.png?imgmax=800" width="394" height="155" /></a></p> <p>for 65</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSnItPyE63e5QWjOh2FTWloFiceLO-JFS0JyhdFVdTmf9wmvsYfJu6xhAQKLpWTBUVyHjhwmwAFHLsXBi6EAeIN5e4OfWo5DGPB5G6FMKKwB0tYJzGfbfcX6uYnoZccZnDBIeDWHYUkmXf/s1600-h/image%25255B16%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://lh3.googleusercontent.com/-qPLUMvQCNeY/V82sQ0lTMgI/AAAAAAAALE4/XgzjKCfvp3c/image_thumb%25255B8%25255D.png?imgmax=800" width="627" height="177" /></a></p> <p>for 129</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8XKxANplBCqUe-QKOpq3y1fv0_M1WG2xRuOn_OIzG_MTw0c0_2ZROXKyyW-6RnsT9VYH_Tpa4Nv-2D8yuj3eJ2d5NF1K83VDXNXOlirwf0N8rSspneZERvNewqhKgmd1okbJTivNJOJ55/s1600-h/image%25255B17%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhL9lJ8B0oeXmyqAKA6nyrcZx4Fio8ffJQh_mSIkr5wGx4bWvrjWqHx9P1CRjNZ5EVrJDVrhmWnvkQwF16mxZlUj1gqGybqb8M1XSvgqciHqkQfiyE23Bq0I3cCwgG5QFJeCVILYqBarkms/?imgmax=800" width="630" height="174" /></a></p> <p> </p> <p>What is the difference in performance for the naive vs the latter?</p> <p>I actually did not wait until the naive solution finished… I aborted at <strong>4 minutes</strong></p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHN63KNwBv-Z89vwJwxXuck6QFzRaLwQEF29M-sWX0uZOG3S8Xl45GPdrMxcUwVFd7Fj5y10ZPzs02JJUxyYTDbx0Pgie9mA8Hb25yOYzwev55Qk0l8kBIqBpOUmWWPA-MQnx8fVg6UIEd/s1600-h/image%25255B21%25255D.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="https://lh3.googleusercontent.com/-CO_cqVnF8UQ/V82sSomkVGI/AAAAAAAALFI/7SZQ3ZyXHSQ/image_thumb%25255B11%25255D.png?imgmax=800" width="571" height="382" /></a></p> <p>The new improved version was 85 ms, over a 3000 fold improvement.</p> <h1>Take Away</h1> <p>This question:</p> <ol> <li>Identify if a person knows what recursion is and can code it.</li> <li>Identify if he understands what the consequence of recursion is and how it will be executed(i.e. think about what the code does)</li> <ol> <li>Most recursion questions are atomic (i.e. factorial) and not composite (recursion that is not simple)</li> </ol> <li>Is able to do analysis of a simple mathematical issue and generate a performing solution.</li> </ol>Ken Lassesen, Dr.Gui (MSDN) retiredhttp://www.blogger.com/profile/13429731290092618600noreply@blogger.com1