[{"data":1,"prerenderedAt":956},["ShallowReactive",2],{"search":3},[4,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,205,210,215,220,225,230,235,240,245,250,255,260,266,271,276,281,286,291,296,301,306,311,316,321,326,331,336,341,346,351,356,361,366,371,376,381,386,391,396,401,406,411,416,421,426,431,436,441,446,451,456,461,466,471,476,481,486,491,496,501,506,511,516,521,526,531,536,541,546,551,556,561,566,571,576,581,586,591,596,601,606,611,616,621,626,631,636,641,646,651,656,661,666,671,676,681,686,691,696,701,706,711,716,721,726,731,736,741,746,751,756,761,766,771,776,781,786,791,796,801,806,811,816,821,826,831,836,841,846,851,856,861,866,871,876,881,886,891,896,901,906,911,916,921,926,931,936,941,946,951],{"id":5,"title":6,"titles":7,"content":8,"level":9},"/2025/09/01-crm-using-nuxt-content","01 CRM Using Nuxt Content",[],"CRM using Nuxt Content I was looking for an alternative to existing blogging technology. Preferrably without database backing, support static side generator (SSG) so I can host it cheaply, and less painful to update content. I have used Next.js with json on my other site, but json isn't easy to write post on. When I read on Nuxt content, I decided to give it a try. Installation It didn't go very smooth as of this writing. First, I created a Nuxt project. It prompted for additional tools that I would like to install. One of the tools is Nuxt Content. Well, it's a convenient start. Sadly, that's also when the inconvenient starts. Nuxt Content failed to install on my Windows machine due to missing better-sqlite3. Based on the error, better-sqlite3 failed to install due to missing VC++ toolset. After few failed tries, I stumble upon this: https://github.com/WiseLibs/better-sqlite3/blob/HEAD/docs/troubleshooting.md. Basically, I need to make sure my Node JS is supported and then run the script in C:\\Program Files\\nodejs\\install_tools.bat. It will install Chocolatey, Python, and Visual Studio Build Tools 2019. Both Chocolatey and Python installations went smoothly, but Visual Studio Build Tools 2019 installation failed. I ended up finishing the installation through Visual Studio Installer. Then, re-installing better-sqlite3 finally completed. Contents On how to add posts as contents are pretty easy. I have to define a collection, add my posts to content folder, and render it with a slug page and queryCollection() method. As expected, Nuxt will use folder path as url path which makes it easy to track down the location of a content. Navigation Tree So, I tried to create a list of posts. This is when queryCollectionNavigation() is useful. One thing that's not documented is the result is to be rendered one level at a time. I use children property to get to the next level. Frontmatter This is a great way to add metadata to the markdown. Also, I bind it to the component, so I can render some properties without having to write them twice. Just one thing to note, it has to be on the top of the markdown. For more details: https://content.nuxt.com/docs/files/markdown#frontmatter Custom Style with MDC MDC syntax is what I used to customize the style of some part of the markdown. In my case, the title, date, and the code block. Basically it allows the content to be wrapped in a Vue component with styling included. The content is wrapped with double colon ::. For more details: https://content.nuxt.com/docs/files/markdown#frontmatter Date Formatting This is the most painful case. For somewhat reason, formatting date is not easy. First, I tried to format it in the markdown itself and it didn't work even with MDC syntax data binding. I ended up using a Vue component to enhance the rendering, so I can format it using Javascript. Refer to GitHub repo for more details. Check the top of the markdown under content and the PostTitle components. Data Binding In order not to duplicate metadata, I utilize data binding. I tried binding data in markdown itself using the supported: {{ $doc.variable || 'defaultValue' }} But it doesn't support much formatting when I tried to render the data. So, I bind the metadata to a prop to Vue component instead. For more details: https://content.nuxt.com/docs/files/markdown#props Custom Font As for custom font, I used Nuxt Fonts + Google Fonts. Once Nuxt Fonts is installed, the rest is just css and Nuxt font will pull the font from built-in repository, in my case, it is Google font. For more details: Nuxt Fonts: https://nuxt.com/modules/fontsGoogle Fonts: https://fonts.google.com/ Attribute Styling This is a powerful feature. It allows me to use tailwind class in markdown for styling. For more details: https://content.nuxt.com/docs/files/markdown#attributes Conclusion Finally, this blog is done. I learned a lot and can share what I learn with the world. GitHub Repository https://github.com/nik-yo/Nikki-no-Nikki",1,{"id":11,"title":12,"titles":13,"content":14,"level":9},"/2025/09/02-override-default-endpoint-in-aspire","02 Override Default Endpoint In Aspire",[],"Override Default Endpoint in .NET Aspire I have been using .NET Aspire for a while now, but this is still not something that's obvious to me. One thing that's great about Aspire is it will launch resources, generate endpoint, and pass it to the application. In my case, I want to launch a Mongo DB container and pass the connection string to my application. However, I want it in the format that's easy for me to maintain. In .NET Aspire MongoDB database integration article, the supported connection string format doesn't meet my requirements, so my first attempt is to retrieve the data, format them and pass it as environment variable. Something along the line: var mongodb = ...; // for brevity\n\nvar username = mongoDB.Resource.UserNameParameter?.Value;\nvar password = mongoDB.Resource.PasswordParameter?.Value;\nvar port = mongoDB.Resource.PrimaryEndpoint.Port.ToString();\n\nbuilder.AddProject\u003CProjects.AsyloSoft_Market_Api>(\"market-api\")\n       .WithEnvironment(\"Database__ConnectionString\", $\"mongodb://{username}:{password}@localhost:{port}\")\n       .WaitFor(mongoDB); However, that didn't work with an error because some data are generated at runtime. System.InvalidOperationException: 'The endpoint `tcp` is not allocated for the resource `mongo`.' My second attempt is to override the generated connection string particularly the host port because, by default, .NET Aspire will randomly use unused port which is great, but it becomes unpredictable. By doing this, the connection string is static, and it doesn't have to be passed to the application every time they are launched. var mongodb = builder.AddMongoDB(\"mongo\")\n                .WithEndpoint(27017, 27017, \"tcp\")\n                .WithLifetime(ContainerLifetime.Persistent); For somewhat reason, this overload tried to create a new endpoint that's mapped to the same target port, which caused conflict and thus error. Aspire.Hosting.DistributedApplicationException: 'Endpoint with name 'tcp' already exists. ... After multiple trials and errors, I managed to override the default generated endpoint using a different overload. var mongodb = builder.AddMongoDB(\"mongo\")\n                .WithEndpoint(\"tcp\", (endpointAnnotation) =>\n                {\n                    endpointAnnotation.Port = 27017;\n                    endpointAnnotation.TargetPort = 27017;\n                    endpointAnnotation.Protocol = ProtocolType.Tcp;\n                })\n                .WithLifetime(ContainerLifetime.Persistent); It is strange to me that two overloads of a method work differently at its core. GitHub Repository (TBA)",{"id":16,"title":17,"titles":18,"content":19,"level":9},"/2025/09/03-generate-large-text-files","03 Generate Large Text Files",[],"Generate Large Text Files As part of my work, I need to ensure I can upload and download a reasonably large document. Just to ensure that I can validate that downloaded document is the same document after uploading. I decided to find a way to create a large text file with random string. After quick search, the easiest and reliable way for me is to use Linux. On Windows, I simply use WSL and change directory to /mnt/c/... which is the same directory as C:\\... in Windows, e.g. /mnt/c/Users/username/Downloads. That way I know where the file is saved to and can access it on Windows side. And to generate the text file, I modified the command that I found online since I want to specify the size of the file and ends up with: tr -dc \"A-Za-z0-9\" \u003C /dev/urandom | fold -w100 | head -c 100M > textfile.txt tr -dc \"A-Za-z0-9\" \u003C /dev/urandom will generate random alphanumeric string. fold -w100 will insert a new line every 100 characters. This helps to be able to open the file fast which works very well in Notepad++ compared to putting all the characters in a single line. head -c 100M > textfile.txt will take the first 100MB of randomly generated characters and save them in textfile.txt. There you go. I managed to create text files with various sizes for my testing. Obviously, the larger the file, the longer it takes. GitHub Repository (TBA)",{"id":21,"title":22,"titles":23,"content":24,"level":9},"/2025/09/04-handle-cors-with-proxy-config","04 Handle Cors With Proxy Config",[],"Handle CORS with Proxy Config I was trying to run application that serves MFE (Micro Front-End) component locally. This application, let's call it parent MFE, in turn, retrieves MFE component from a different application, let's call this child MFE. Primary application -> Parent MFE -> Child MFE I managed to get the child MFE application running, but parent MFE application has trouble retrieving from child MFE application due to CORS (Cross-Origin Resource Sharing) policy. Since all applications are Angular based, I learned a neat feature of proxy.conf.json. With proxy, instead of doing direct call to the child MFE, the parent will call itself and Angular will translate the call by changing the origin to the child MFE origin. Parent MFE -> self -- translate origin --> Child MFE This requires a few steps: Create proxy.conf.json if not already exists on the project. This file can reside anywhere in the project.Add the following entry to proxy.conf.json: {\n  \"/call-path-on-parent-mfe\": {\n    \"target\": \"https://child-mfe-url\",\n    \"secure\": false,\n    \"changeOrigin\": true\n  }\n} Add the following into angular.json: ...\n\"serve\": {\n  \"options\": {\n    \"proxyConfig\": \"path/to/proxy.conf.json\"\n  }\n} Change the call on parent MFE to call itself. For example: From http.get(\"https://child-mfe-url/path-to-resource\"); To http.get(\"/path-to-resource\"); This will work in the case of frontend tried to call backend but was blocked by CORS as well. GitHub Repository (TBA)",{"id":26,"title":27,"titles":28,"content":29,"level":9},"/2025/09/05-analytics-with-umami","05 Analytics With Umami",[],"Analytics with Umami I'm thinking of using third party to check how many visitors to my new blog. Of course, the first thing that came to mind is Google Analytics. But I'm wondered if there's a good alternative. In online forum, some suggested Umami, so I decided to sign up. The process from sign up to integration was smooth. It took me less than 5 minutes from zero to running. One thing that I need to adjust is because I used Nuxt, I had to configure Umami's script tag from: \u003Cscript defer src=\"https://cloud.umami.is/script.js\" data-website-id=\"...\">\u003C/script> to the following, which is to be placed under app.vue: \u003Cscript setup lang=\"ts\">\nuseHead({\n  ...\n  script: [ \n    { \n      defer: true,\n      src: 'https://cloud.umami.is/script.js', \n      'data-website-id': '...'\n    }\n  ]\n})\n\u003C/script> For more information: Nuxt useHead: https://nuxt.com/docs/4.x/getting-started/seo-meta#useheadUmami: https://umami.is/ GitHub Repository https://github.com/nik-yo/Nikki-no-Nikki",{"id":31,"title":32,"titles":33,"content":34,"level":9},"/2025/09/06-download-passthrough-using-dotnet-web-api","06 Download Passthrough Using Dotnet Web Api",[],"Download Passthrough using .NET Web API In one of my projects, one of the feature is to be able to upload to and download from existing service/API. Basically, the backend will act as a middle man. The first approach is for the backend to download the file, store it as byte array and then send it down to the frontend like the following: public async Task\u003Cbyte[]> DownloadFromServiceAsync(CustomRequest request) {\n  ...\n\n  using (var response = await httpClient.GetAsync(url)) \n  {\n    var byteArray = await response.Content.ReadAsByteArrayAsync();\n\n    return byteArray;\n  }\n} But the method above means the file is retained in the memory on the backend before being sent down to the frontend, thus the server needs to have enough memory to hold the full file size. It gets worse when there are multiple downloads at the same time. The file is then returned to the frontend similar to the following: [HttpGet]\npublic async Task\u003CIActionResult> DownloadFile(CustomRequest request)\n{\n  var byteArray = await DownloadFromServiceAsync(request);\n\n  return Ok(new CustomResponse() { ByteArray = byteArray });\n} Another issue with the method above is the download time. It means frontend has to wait longer since backend has to fully download the file from the existing service before sending it. To solve the issues, the content has to be streamed end-to-end. From existing file service to backend and backend to frontend. Backend to Frontend Apparently the reason why it was done that way is we can't get MemoryStream to work with download. I decided to play with it to try understanding the issues and hopefully find a solution. I started with tackling backend to frontend piece and take care of existing service to backend later. My first try didn't work. [HttpGet]\npublic async Task\u003CIActionResult> DownloadFile(CustomRequest request)\n{\n  var byteArray = await DownloadFromServiceAsync(request);\n\n  var memoryStream = new MemoryStream(byteArray);\n  memoryStream.Position = 0;\n\n  return Ok(new FileStreamResult(memoryStream, \"application/octet-stream\"));\n} And it immediately threw an error when I tried it through Swagger UI. Part of the error message said: Timeouts are not supported on this stream. I found out later that by default, web api will serialize the content as json. I happened to read about FileContentResult but it suffers from the same problem. So I decided to experiment a little and finally got it to work by removing the Ok() method, so it becomes: [HttpGet]\npublic async Task\u003CIActionResult> DownloadFile(CustomRequest request)\n{\n  var byteArray = await DownloadFromServiceAsync(request);\n\n  var memoryStream = new MemoryStream(byteArray);\n  memoryStream.Position = 0;\n\n  return new FileStreamResult(memoryStream, \"application/octet-stream\");\n} Alternatively: [HttpGet]\npublic async Task\u003CIActionResult> DownloadFile(CustomRequest request)\n{\n  var byteArray = await DownloadFromServiceAsync(request);\n\n  var memoryStream = new MemoryStream(byteArray);\n  memoryStream.Position = 0;\n\n  return File(memoryStream, \"application/octet-stream\"));\n} File Service to Backend The other half of the solution has something to do with getting the file streamed from existing file service. The httpClient.GetAsync has to be replaced with httpClient.GetStreamAsync. I ended up just passing the stream all the way to the backend endpoint. So instead of: public async Task\u003Cbyte[]> DownloadFromServiceAsync(CustomRequest request) {\n  ...\n\n  using (var response = await httpClient.GetAsync(url)) \n  {\n    var byteArray = await response.Content.ReadAsByteArrayAsync();\n\n    return byteArray;\n  }\n} It becomes: public async Task\u003CStream> DownloadFromServiceAsync(CustomRequest request) {\n  ...\n\n  return await httpClient.GetStreamAsync(url);\n} And the endpoint code has to be updated: [HttpGet]\npublic async Task\u003CIActionResult> DownloadFile(CustomRequest request)\n{\n  var stream = await DownloadFromServiceAsync(request);\n\n  return new FileStreamResult(stream, \"application/octet-stream\");\n} Testing Sadly I can't attach a screenshot at the moment, but I tested with 150 MB of text file. Without streaming, the memory used started from 160 MB, shot up to 380 MB after getting the file from file service, and then to 549 MB when Swagger UI finally got hold of the file. With streaming code, since we passed the stream, the memory usage only went from 160 MB to 218 MB for the same file. This is my first attempt to passthrough stream to download file using ASP.NET Web API. GitHub Repository (TBA)",{"id":36,"title":37,"titles":38,"content":39,"level":9},"/2025/09/07-under-dollar1-a-month-hosting","07 Under $1 A Month Hosting",[],"Under $1 a month Hosting This is probably one of my exciting finds from few years ago. At that time, I wanted to modernize my old personal site and not having to pay $12 a month for hosting. My requirements were cheap to host, using newer technology, and easy to maintain. I started addressing the requirements one by one. Starting from cost, I found out that compute is expensive, so I need something that doesn't require much compute power. For website, the answer is static files, such as plain HTML, CSS, Javascript files. But static files are hard to maintain. That's when newer technology helps. In this area, the answer is SPA (Single-Page Application). However, I need one that supports SSG (Static Site Generator). It means, the application will be transformed into static files. Now, my old site has database. But I really only care about the data, so I decided to use JSON (Javascript Object Notation) files which can be easily parsed by SPA. That solves my data issue. Finally hosting. The cheapest hosting I can find is $2-3 a month. So, I turned to cloud, in this case, I use AWS. With it, I can finally host my personal site under $1 a month. My October 2025 cost was only $0.53. And it's not only for 1 site, I have multiple sites hosted in AWS. Sitehttps://www.nikkiyodo.com GitHub Repositoryhttps://github.com/nik-yo/NikkiYodo",{"id":41,"title":42,"titles":43,"content":44,"level":9},"/2025/09/08-truthy-or-falsey-on-non-existing-element-using-jquery-selector","08 Truthy Or Falsey On Non Existing Element Using JQuery Selector",[],"Truthy or Falsey on Non-Existing Element Using jQuery Selector This is a repost from my old blog. First posted in 3/16/2016. In JavaScript, there are terms called truthy and falsey. It is a very interesting way to find if an expression evaluates to true or false, so I decided to make use of it to evaluate whether the element selected by jQuery exists. For example: if ($('#elementId')) {\n   //Do something if element exists\n} else {\n   //Do something else if element doesn't exist\n} However, when I used it against a jQuery variable that is supposed to hold HTML elements that met certain selector, it didn't work correctly. The problem is there is no element in the variable but it evaluates to true. This is due to jQuery returns Object  which is empty array of object and the array itself exists thus the expression returns true. Some suggestions I found online are:\nUse length properties, so it becomes if ($('#elementId').length){}\nIn jQuery version 1.4 or above, you can use $.isEmptyObject() function\nAnother way that works for me is to get its first element: if ($('#elementId')[0]){} The one that I often used lately is: var elements;\n\nif (elements && elements.length) { }",{"id":46,"title":47,"titles":48,"content":49,"level":9},"/2025/09/09-if-operator-and-nothing-on-vb.net","09 If Operator And Nothing On VBNet",[],"If Operator and Nothing on VB.Net This is a repost from my old blog. First posted in 9/27/2016. I encountered an interesting thing recently in my programming experience. I have the following method: Private Sub SomeMethod(parameter As Nullable(Of Double))\n   If parameter.HasValue Then\n      'Do something\n   Else\n      'Do something else\n   End If\nEnd Sub To call it, I use the following: SomeMethod(If(someObject.IsTrue, Nothing, someDouble)) However, it didn't work as I expect it to be. The one that confused me is, the HasValue always returns true although Nothing is being passed to the method. It took me awhile to realize that the If operator in this case will return the same type for both results (true and if false). And in VB.Net, Nothing equals default value which for Double is 0.0 while I want Nothing to act as Null. Thus to fix the issue, I have to rewrite it as: If someObject.IsTrue Then\n   SomeMethod(Nothing)\nElse\n   SomeMethod(someDouble)\nEnd If",{"id":51,"title":52,"titles":53,"content":54,"level":9},"/2025/09/10-adding-search-to-nuxt-content","10 Adding Search To Nuxt Content",[],"Adding Search to Nuxt Content In this blog, finding a post that contains a certain word can be hard. So, I was looking for a way to easily implement a search feature.Nuxt content doc has a nice write up on full-text search, so I started from there. The example in the doc uses Nuxt UI, but I managed to use just a simple input tag: \u003Cinput v-model=\"query\" type=\"text\" placeholder=\"Search...\" /> For the search package, I decided to use minisearch which is very easy to use. Just on the implementation side, I need to add check on the data.value to pass typescript null check. if (data.value) {\n  miniSearch.addAll(toValue(data.value))\n} One additional thing is the example will display whole content of the page. However, I wanted to limit it to few rows. One option is to use textarea and set it to readonly, but it's not quite the purpose of text area. Tailwind has truncate class but it doesn't limit based on number of lines. Tailwind v3.3, however, has line-clamp class built-in which works perfectly in my case. \u003Cp class=\"text-gray-600 text-xs line-clamp-3\">{{ link.content }}\u003C/p> Check it out by clicking the search button above.",{"id":56,"title":57,"titles":58,"content":59,"level":9},"/2025/09/11-add-multiple-reviewers-with-gitlab-quick-actions","11 Add Multiple Reviewers With Gitlab Quick Actions",[],"Add Multiple Reviewers with GitLab Quick Actions At one point, I was moved to a new team at work. Since the team number increased and we were required to add everyone as reviewers when we made merge request (or pull request), clicking got tedious. So, we were looking for a way to create a group and hope we can just add the group as reviewers. GitLab does support that but we didn't have the permission. Asking and waiting for the permission can take a long time and might not be granted. As we look around for solution, we happened to bump into GitLab Quick Actions. And it's a great workaround. By simply add the following text into the description box, it automatically adds everyone as reviewers when the merge request is created. /reviewer @user1 @user2 @user3",{"id":61,"title":62,"titles":63,"content":64,"level":9},"/2025/09/12-deleted-data-row-and-linq","12 Deleted Data Row And LINQ",[],"Deleted Data Row and LINQ This is a repost from my old blog. First posted in 9/27/2016. Another interesting programming problem. I have the following code in VB.Net which throws error: dataRow.Delete() 'One of the rows in dataSet\n\ndataSet.Tables(\"TableName\").Rows.Cast(Of DataRow).FirstOrDefault(Function(dr) dr(\"ColumnName\") = certainCondition) The error says \"Deleted row information cannot be accessed through the row\". Pretty clear message, so I did the following: dataSet.Tables(\"TableName\").Rows.Cast(Of DataRow).FirstOrDefault(Function(dr) dr(\"ColumnName\") = certainCondition AndAlso dr.RowState \u003C> DataRowState.Deleted) But the code above throws the same error. Apparently the deleted check has to be the first condition which again makes sense. Thus, the following code runs perfectly fine: dataSet.Tables(\"TableName\").Rows.Cast(Of DataRow).FirstOrDefault(Function(dr) dr.RowState \u003C> DataRowState.Deleted AndAlso dr(\"ColumnName\") = certainCondition) There you go.",{"id":66,"title":67,"titles":68,"content":69,"level":9},"/2025/09/13-asp.net-migration-error","13 ASPNet Migration Error",[],"ASP.Net Migration Error This is a repost from my old blog. First posted in 9/30/2016. I did a lot of updates on my project and since I use Entity Framework Code First, I depend on migration commands. This time, my Visual Studio suddenly does not recognize the commands. I have the following error message when attempting to enable migration: The term 'Enable-Migrations' is not recognized as the name of a cmdlet, function, script file, or operable program Some people say to reinstall entity framework with the following command: Install-Package EntityFramework -IncludePrerelease But it didn't work for me since I have it installed, so I find a way to force reinstall the package which works! The command as follow: Update-Package -reinstall EntityFramework -IncludePrerelease",{"id":71,"title":72,"titles":73,"content":74,"level":9},"/2025/09/14-asp.net-membership-create-user-and-invalid-email","14 ASPNet Membership Create User And Invalid Email",[],"ASP.Net Membership, Create User and Invalid Email This is a repost from my old blog. First posted in 10/3/2016. I was testing ASP.Net Membership user registration logic in my server. It runs fine till it throws The E-mail supplied is invalid error. Weird thing is I found out that all my data are correct through debugging and double checking my entry. Quick search says that requiresUniqueEmail attribute on Membership provider tag set to true is the problem. Ironically, I only have one email in the database. Brushing my confusion aside, I remove the attribute, but it still doesn't work. And eventually found out that setting requiresUniqueEmail=\"false\" fixed the whole thing. Later on I also found out that by default, the attribute has value of true. That explains why removing the attribute doesn't work. https://msdn.microsoft.com/en-us/library/system.web.security.membershipprovider.requiresuniqueemail(v=vs.110).aspx I have yet found out why it doesn't work when it has true value and no data in the database. Hopefully one day when I have time to dig deeper.",{"id":76,"title":77,"titles":78,"content":79,"level":9},"/2025/09/15-diagram-as-a-code-using-mermaid","15 Diagram As A Code Using Mermaid",[],"Diagram as a Code Using Mermaid Today I need to visualize a data flow using diagram. I started with my go-to tools, Draw.io. It's quickly getting complicated. I need to move elements around, ensure the arrows are still correct, update the formatting, and soon I can see it taking a lot of time. I decided to use a different approach. In KCDC, there's a session about diagram and I remember the tool is Mermaid, so I decided to learn it. And within minutes, I'm able to create very dynamic sequence diagram and entity relation diagram in markdown file. With Mermaid Plugin in VS Code This is how I originally have it. Basically install Mermaid plugin for VS Code. Then on the markdown, add the following text: ```mermaid\nsequenceDiagram\n    participant user as User\n    participant web as Web UI\n    participant api as API\n    user->>web: GET /\n    web->>user: return &lt;html&gt;\n    user-->>api: GET /api/resource\n    api-->>user: return {json}\n``` Show preview on VS Code and the diagram will be rendered. For more information:\nhttps://www.mermaidchart.com/ In Nuxt Content Markdown using NPM Package For the purpose of showing the diagram in this blog, I had to approach it differently as it will be rendered as html. Instead of plugin, I installed the npm package. yarn add mermaid It actual does server side rendering, but since I'm not going to have a server, I need a client side rendering. Good thing is there's a workaround: https://github.com/nuxt/content/issues/1866. Thank to all the folks that contribute to the solutions! First, we need to create a client side plugin under \u003Capp>/plugins/mermaid.client.ts with the following content: import mermaid from 'mermaid'\n\nexport default defineNuxtPlugin((nuxtApp) => {\n  nuxtApp.provide('mermaid', () => mermaid)\n}) Next, we need a custom component, let say \u003Capp>/components/mermaid.vue: \u003Cscript setup lang=\"ts\">\n  const { $mermaid } = useNuxtApp();\n  const mermaidContainer = ref\u003CHTMLPreElement | null>(null)\n\n  onMounted(async () => {\n    const { $mermaid } = useNuxtApp();\n  const mermaidContainer = ref\u003CHTMLPreElement | null>(null)\n\n  onMounted(async () => {\n    if (mermaidContainer.value?.textContent) {\n      await nextTick()\n      try {\n        $mermaid().initialize({ startOnLoad: false, theme: 'default' })\n        await $mermaid().run({\n          nodes: [mermaidContainer.value],\n        })\n      }\n      catch (e) {\n        console.error('Error running Mermaid:', e)\n        mermaidContainer.value.innerHTML = '⚠️ Mermaid Chart Syntax Error'\n      }\n    }\n  })\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cpre ref=\"mermaidContainer\" class=\"mermaid\">\n    \u003Cslot mdc-unwrap=\"p\" />\n  \u003C/pre>\n\u003C/template> Then, add a type to make typescript happy at \u003Capp>/types/mermaid.d.ts: import type { mermaid } from 'mermaid'\n\ndeclare module '#app' {\n  interface NuxtApp {\n    $mermaid: () => mermaid\n  }\n}\n\nexport {} Finally, on the markdown: ::mermaid\nsequenceDiagram\n    participant user as User\n    participant web as Web UI\n    participant api as API\n    user->>web: GET /\n    web->>user: return \u003Chtml>\n    user-->>api: GET /api/resource\n    api-->>user: return {json}\n:: which renders the diagram: sequenceDiagram\nparticipant user as User\nparticipant web as Web UI\nparticipant api as API\nuser->>web: GET /\nweb->>user: return \nuser-->>api: GET /api/resource\napi-->>user: return {json} For more information:\nhttps://mermaid.js.org/",{"id":81,"title":82,"titles":83,"content":84,"level":9},"/2025/09/16-html-object-tag-and-silverlight-plugin-reload","16 HTML Object Tag And Silverlight Plugin Reload",[],"HTML Object Tag and Silverlight Plugin Reload This is a repost from my old blog. First posted in 10/6/2016. I have a Silverlight plugin that I don't want it to be refreshed or reloaded. But in my case, it always reloaded itself though nothing on the page caused a postback. Later on, I found out that I have a javascript code that hide and show the container of the plugin (div with id of someDiv in the code below). \u003Cdiv id=\"someDiv\">\n  \u003Cobject data=\"data:application/x-silverlight-2,\" type=\"application/x-silverlight-2\">\n  ...\n  \u003C/object>\n\u003C/div> Apparently that causes the object tag to reload the plugin. My workaround thus is to set the height of the object tag to 0 px, that solves the problem.",{"id":86,"title":87,"titles":88,"content":89,"level":9},"/2025/09/17-autocomplete-and-radio-button","17 Autocomplete And Radio Button",[],"Autocomplete and Radio Button This is a repost from my old blog. First posted in 10/7/2016. When I created my web page, I noticed that the state of my radio buttons stays when I navigated away to another page and then back to the same page. I was confused at first and quickly found out that by default the browser (in my case, firefox) has autocomplete enabled by default and was saving the state somehow. Quick search online allow me to turn the feature on/off by adding autocomplete attribute. \u003Cinput type=\"radio\" autocomplete=\"off\"/> https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion",{"id":91,"title":92,"titles":93,"content":94,"level":9},"/2025/09/18-display-inline-block","18 Display Inline Block",[],"Display: inline-block; This is a repost from my old blog. First posted in 10/7/2016. Ok, I have two div tag that I want to put side by side, so I use display: inline-block; css property. \u003Cdiv style=\"display: inline-block; width: 30%;\">...\u003C/div>\n\u003Cdiv style=\"display: inline-block; width: 70%;\">...\u003C/div> I'm surprised to see there is a gap between the two divs somehow. And found out the way to fix the problem is to bring the divs together in the markup without any gap: \u003Cdiv style=\"display: inline-block; width: 30%;\">\n...\u003C/div>\u003Cdiv style=\"display: inline-block; width: 70%;\">...\u003C/div> Ugly, yes, but it fixes the problem. Edit: I have another case in which I want a gap between the two divs, so I don't bring the two divs together but I found out that somehow the second div is being put under the first one when printing. I ended up setting the second div with width of 69% so the total is 99% instead of 100% to make it work.",{"id":96,"title":97,"titles":98,"content":99,"level":9},"/2025/09/19-import-text-files-with-garbage-characters","19 Import Text Files With Garbage Characters",[],"Import Text Files with Garbage Characters This is a repost from my old blog. First posted in 10/21/2016. I had a case in which we use VB.NET to import a text file and it didn't work properly. My code at first was: Dim someString As String = Encoding.ASCII.GetString(someByteArray) After researching for a while, I found out that the text file is encoded using UTF-8. Thus, switching it to the following code make it work properly: Dim someString As String = Encoding.UTF8.GetString(someByteArray) Encoding matters!",{"id":101,"title":102,"titles":103,"content":104,"level":9},"/2025/09/20-putting-2-html-elements-side-by-side","20 Putting 2 HTML Elements Side By Side",[],"Putting 2 HTML Elements Side by Side This is a repost from my old blog. First posted in 10/24/2016. Many times I have to battle on which methods are the best in putting two HTML elements side-by-side. Let say we have the following elements: \u003Cdiv class=\"Container\">\n   \u003Cdiv class=\"LeftColumn\">\u003C/div>\n   \u003Cdiv class=\"RightColumn\">\u003C/div>\n\u003C/div> Based on my own experience and preference, I usually use one of these 3 css options. For clarification, they are by no means comprehensive ways to style two elements nor the points are meant to capture all possibilities. Option 1: .LeftColumn, .RightColumn {\n   display:inline-block;\n   width: 50%;\n} Option 2: .LeftColumn {\n   float: left;\n}\n.RightColumn {\n   float: right;\n} Option 3: .Container { display: flex; flex-direction: row; justify-content: space-between; } Each option has its own characteristics. Option 1: It will create a gap between the two elements.\nIf browser is shrinked width-wise, the second element will not be automatically wrapped. Option 2: The first element will be anchored to the left and the second element will be anchored to the right.\nTo prevent the next element from being rendered unexpected, a third element with css property of clear: both is needed.\nIf browser is shrinked width-wise, the second element will be placed underneath the first.\nvertical-align property and some other properties have no effect. Option 3: Same points as option 2 but without the need of the third element.\nNew CSS 3 properties but it has more ways for customization.",{"id":106,"title":107,"titles":108,"content":109,"level":9},"/2025/09/21-identityserver-authorizeattribute","21 IdentityServer AuthorizeAttribute",[],"IdentityServer AuthorizeAttribute This is a repost from my old blog. First posted in 11/10/2016. I attempted to use ResourceAuthorize attribute in my personal project which uses Thinktecture IdentityServer 3. When testing around, I suddenly realize not only ResourceAttribute is not working, the AuthorizeAttribute was broken as well. Spent hours testing and finally found out that it was caused by a slash (\"/\") at the end of my issuer. So \"https://www.test.com/\" does not work, but \"https://www.test.com\" works somehow. The AuthorizeAttribute now works but at this time, I'm still checking why troubleshooting my ResourceAttribute. Edit: Apparently my ResourceAttribute was not working because one of the scopes is invalid and my intended scope is after that which eventually was not processed. And the requested claims will be included in the access_token.",{"id":111,"title":112,"titles":113,"content":114,"level":9},"/2025/09/22-black-background-on-combined-images","22 Black Background On Combined Images",[],"Black Background on Combined Images This is a repost from my old blog. First posted in 11/30/2016. I was asked to research about a strange behavior when we combine two images, each image becomes small and the rest of the extra space is filled with black color. After doing a bit of research and making sample applications, I found out that it has something to do with image dpi. Each image is scanned with 240 dpi while Windows default to 96 dpi. That means, the image is scaled down, so I simply get the least dpi and set it as dpi for the combined image. It works for now, though I can see the potential problem if somehow the horizontal and vertical dpi are different. Dim image1 As Bitmap = ...(code to get image) --> has 240 dpi\nDim image2 As Bitmap = ...(code to get image) --> has 240 dpi\n\nDim combinedImage As New Bitmap(...) --> default to 96 dpi\n\nDim horizontalResolution As Single = Math.Min(image1.HorizontalResolution, image2.HorizontalResolution)\nDim verticalResolution As Single = Math.Min(image1.VerticalResolution, image2.VerticalResolution)\n\ncombinedImage.SetResolution(horizontalResolution, verticalResolution)",{"id":116,"title":117,"titles":118,"content":119,"level":9},"/2025/09/23-bad-image-quality-on-scaled-down-image","23 Bad Image Quality On Scaled Down Image",[],"Bad Image Quality on Scaled Down Image This is a repost from my old blog. First posted in 1/18/2017. The image in \u003Ccanvas> appears to be bad quality when we scale it down. Apparently it is due to linear interpolation algorithm used by the browser because it is fast. I also learn that scaling down requires resampling while scaling up requires interpolation. Searching online, I found pixel perfect resampling algorithm. http://stackoverflow.com/questions/18922880/html5-canvas-resize-downscale-image-high-quality I thus ran the image over the algorithm before having the canvas redraw it. It is a good stuff and improve the quality of the image.",{"id":121,"title":122,"titles":123,"content":124,"level":9},"/2025/09/24-path.combine-and-path.getfullpath","24 PathCombine And PathGetFullPath",[],"Path.Combine and Path.GetFullPath This is a repost from my old blog. First posted in 5/5/2017. I bumped into a case in which I need to resolve a relative path to a file, but the problem is it doesn't resolve as expected when Path.GetFullPath is used. For example: path1 = \"C:\\file\\\"\npath2 = \"..\\test.txt\" Path.Combine produces \"C:\\file..\\test.txt\" Path.GetFullPath((New Uri(Path.Combine(path1,path2))).LocalPath) produces \"C:\\test.txt\" which is correct. The problem starts when I realized another slash was accidentally appended to the end of path1. path1 = \"C:\\file\\\"\npath2 = \"..\\test.txt\" Path.Combine produces \"C:\\file\\..\\test.txt\" Path.GetFullPath((New Uri(Path.Combine(path1,path2))).LocalPath) produces \"C:\\file\\test.txt\" which is correct but unexpected.",{"id":126,"title":127,"titles":128,"content":129,"level":9},"/2025/09/25-xmlserializer-and-boolean","25 XMLSerializer And Boolean",[],"XMLSerializer and Boolean This is a repost from my old blog. First posted in 5/5/2017. I rewrote a project to utilize XMLSerializer instead of manually append xml tags. It works great until I encountered problem with backward compatibility on Boolean type. Our client is sending boolean value with first letter capitalized. \"True\" and \"False\" and apparently XMLSerializer were unable to deserialize the value as boolean. Because by convention, boolean in XML has to be all lower case. Searching online I found out that I need to do a small trick. Instead of: \u003CXmlElement(\"isvalid\")>\nPublic Property IsValid As Boolean I have to rewrite it as: \u003CXmlElement(\"isvalid\")>\nPublic Property IsValidString As String\n   Get\n      Return IsValid.ToString().ToLower()\n   End Get\n   Set\n      Boolean.TryParse(value, IsValid)\n   End Set\nEnd Property\n\n\u003CXmlIgnore>\nPublic Property IsValid As Boolean The modified version can handle both formats.",{"id":131,"title":132,"titles":133,"content":134,"level":9},"/2025/09/26-adobe-reader-caused-firefox-to-crash","26 Adobe Reader Caused Firefox To Crash",[],"Adobe Reader Caused Firefox to Crash This is a repost from my old blog. First posted in 5/18/2017. We have an object tag on the page and it points to a pdf. \u003Cobject data=\"https://www.somedomain.com./somedocument.pdf\">\n\u003C/object> Weird scenario is some of us experience Adobe reader unable to open the document and crashed Firefox altogether. After many hours of search, I found out the problem was due to html encoded url. It is supposed to be https://www.somedomain.com/somedocument.pdf#page=1&viewrect=1,2,3,4. Instead, it becomes https://www.somedomain.com/somedocument.pdf#page=1&amp;viewrect=1,2,3,4 and Adobe crashed after parsing that the encoded part. Removing the encoding fixed the issue.",{"id":136,"title":137,"titles":138,"content":139,"level":9},"/2025/09/27-how-to-craft-multipart-form-data","27 How To Craft Multipart Form Data",[],"How to Craft Multipart Form Data This is a repost from my old blog. First posted in 8/23/2018. Ok, it is all started from me trying to send image from android to my web service using Google Volley. By default, Volley doesn't have built-in request to send image, but allows you to extend the request class. So, I need to extend the request class and create a MultipartFormDataRequest kind of class. Reading after reading, I can't find the information I need to craft one. So I have to combine whatever I read with trial and error. The first one is the concept of boundary. It is a required information under Content-Type header. It acts as a separator between fields and can be any random string as long as it meets the requirements such as it can't exist in actual field data. More information such as length and size limit can be found under RFC 2046 Section 5.1. So, the content-type header will be: Content-Type: multipart/form-data; boundary=anyrandomstring Next is how to use the boundary. The http body will start with two hyphens followed by the boundary. Underneath it is the Content-Disposition and Content-Type key value pair for each field. Between each field, it will be another two hyphens followed by the boundary as the separator. The one that caught me off guard was the closing boundary, it is two hyphens followed by the boundary and then followed by another two hyphens, so the http body will be: --anyrandomstring\n\nContent-Disposition: form-data; name=textFieldName\nContent-Type: text/plain\n\nTextFieldValue\n\n--anyrandomstring\n\nContent-Disposition: form-data; name=imageFieldName; filename=imageFilename.jpg\nContent-Type: image/jpeg\n\n[ImageBytes]\n\n--anyrandomstring-- And then it works wonderfully.",{"id":141,"title":142,"titles":143,"content":144,"level":9},"/2025/09/28-entity-framework-(ef)-6-database.sqlquery-mapping","28 Entity Framework (EF) 6 DatabaseSqlQuery Mapping",[],"Entity Framework (EF) 6 Database.SqlQuery Mapping This is a repost from my old blog. First posted in 8/27/2018. I bumped into a problem with mapping results from manually crafted sql query to object using EF. Somehow, it doesn't seem to recognize the column attribute. And I found out that it really doesn't and they don't plan to enhance EF 6, although there seems to have the option in EF Core to do the mapping. To illustrate my problem better, suppose my database column name is pk and would like to map it to ID property. Usually, using [Column(\"pk\")] will solve the mapping, however, it doesn't work if the query was executed via dbContext.Database.SqlQuery(\"SELECT pk FROM TableName\"). So I have to either change the ID property to pk or the one that I preferred is to change the query to dbContext.Database.SqlQuery(\"SELECT pk AS ID FROM TableName\").",{"id":146,"title":147,"titles":148,"content":149,"level":9},"/2025/09/29-entity-framework-(ef)-include()-lambda-extension-method-namespace","29 Entity Framework (EF) Include() Lambda Extension Method Namespace",[],"Entity Framework (EF) Include() Lambda Extension Method Namespace This is a repost from my old blog. First posted in 8/29/2018. As of this writing, seems like Visual Studio still unable to provide suggestion on what namespace to import for extension methods. I was looking into doing eager loading in EF and I am aware that I can use Include() method with lambda function. By default, it is not available and I can't remember which namespace it is located under. Of course, Visual Studio was not much help. After searching online, I found out that it is an extension method under System.Data.Entity namespace. I gotta remember from now on.",{"id":151,"title":152,"titles":153,"content":154,"level":9},"/2025/09/30-a2-hosting-with-.net-core-2.1","30 A2 Hosting With NET Core 21",[],"A2 Hosting with .NET Core 2.1 This is a repost from my old blog. First posted in 9/5/2018. Technology advances so fast and I have a new web application which I built using .NET Core 2.1. However, my current web hosting provider does not support .NET Core and I have to look for a new web hosting. Reading some forums, found out that A2 Hosting plans to install .NET Core 2.1 in their shared hosting on August 2018. So on September 5th, 2018, I signed up for a new account with them. The coupon HOSTINGFACTS that I found from a web hosting review website still works and gave me 53% one-time discount. Everything went smoothly until I found out that in my Plesk, I was unable to go higher than .NET 4.6.2. So, I decided to chat with their customer support. It took a while to get in touch with an agent, which makes sense because they have lots of customers and it was during busy hour. From the chat with their customer support, I found out that .NET Core 2.1 has indeed been installed and what is weird is I don't have to flip the .NET version in Plesk. With that information, I decided to try deploy my web application using web deploy mechanism. I had to enable this on the domain level and Plesk will add a link to download the .publishsettings file which can then be imported to Visual Studio. Deploying my application using web deploy mechanism has a small issue too. A2 Hosting apparently uses self-signed certificate and Visual Studio rejects the deployment because it can't trust it. To workaround it, I found many solutions. One of them is to trust the certificate. However, I don't think it is a good idea to trust untrusted certificate, so I decided to add \u003CAllowUntrustedCertificate>True\u003C/AllowUntrustedCertificate> tag on the publish profile xml file. To add the tag, I can't find the UI in VS2017, so I have to go to my project folder, under Properties > PublishProfiles and manually add it to the .pubxml file. At last I managed to deploy my application and it worked great.",{"id":156,"title":157,"titles":158,"content":159,"level":9},"/2025/10/01-a2-windows-hosting-https-redirect-conflict","01 A2 Windows Hosting HTTPS Redirect Conflict",[],"A2 Windows Hosting HTTPS Redirect Conflict This is a repost from my old blog. First posted in 9/8/2018. With the intention of following best practice, I tried to enforce HTTPS on my websites hosted in A2 Hosting. Under Hosting Settings > Security, I found a check box that says \"Permanent SEO-safe 301 redirect from HTTP to HTTPS\", it sounds like the right one as it will redirect any HTTP to HTTPS. Because it is a windows server, it also has IIS Settings. And I found \"Require SSL/TLS\" check box under IIS Settings > Directory Security Settings. That sounds different from permanent redirect, so I check it as well. When I test the settings by visiting my website using regular HTTP, I received a 403 error. My first attempt to fix the issue was going back to the IIS Settings and set the Authentication from Windows to None. However  that doesn't work. After several trial and error, I have to uncheck the \"Require SSL/TLS\" check box under IIS Settings > Directory Security Settings to redirect the traffic correctly.",{"id":161,"title":162,"titles":163,"content":164,"level":9},"/2025/10/02-autocomplete-bug-in-chrome-form-field","02 Autocomplete Bug In Chrome Form Field",[],"Path.Combine and Path.GetFullPath This is a repost from my old blog. First posted in 9/13/2018. I just update my website and everything works great in Firefox. As I test it in Chrome, I noticed when I navigate to another and then press the back button, my text field was populated with wrong data. The data was the default value of other text field before the navigation. As I was looking around, I found out that it is a bug in WebKit based browsers. Some people suggested to use autocomplete=\"off\" property on all input field. But for my case, it is enough to put the attribute to all text fields \u003Cinput type=\"text\"/>.",{"id":166,"title":167,"titles":168,"content":169,"level":9},"/2025/10/03-entity-framework-(ef)-decimal-mapping-to-sql-server","03 Entity Framework (EF) Decimal Mapping To SQL Server",[],"Entity Framework (EF) Decimal Mapping to SQL Server This is a repost from my old blog. First posted in 9/13/2018. We bumped into a strange issue. Value of our property was not saved to the database. We checked mapping, spelling, data type and none seems wrong. Eventually we found out that the decimal in our database has precision of (12, 6) and the SQL default is (18, 2). Problem is EF map Decimal data type to the SQL default precision thus our value was truncated. To fix the issue, we put the following code in our DbContext under OnModelCreating method and our value was then saved correctly. protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)\n{\n       modelBuilder.Entity\u003CClass>().Property(object => object.property).HasPrecision(12, 6);\n}",{"id":171,"title":172,"titles":173,"content":174,"level":9},"/2025/10/04-entity-framework-sorting-ordering-and-dynamic-linq","04 Entity Framework Sorting Ordering And Dynamic LINQ",[],"Entity Framework Sorting/ Ordering and Dynamic LINQ This is a repost from my old blog. First posted in 10/2/2018. One of my coworkers would like me to update my IEnumerable SortBy extension method to support multiple columns. As I was working on it, I stumbled upon a nice StackOverflow question on Dynamic LINQ OrderBy on IEnumerable. They are all awesome. I decided to try Dynamic LINQ by adding it through Nuget. However, I soon found that Dynamic LINQ only support property names. In some cases, we want to be able to sort by specifying column attribute value, so I still use my own code which works just fine although it might not be optimized for performance. For example in VB.NET: Public Class Customer\n    \u003CColumn c_name=\"\">\n    Public Property Name As String\n\n    \u003CColumn c_age=\"\">\n    Public Property Age As Integer\nEnd Public\n\nDim sortedByName = dbContext.Customers.AsEnumerable().SortBy(\"c_Name, c_Age DESC\") The gist for my code can be found in:\nhttps://gist.github.com/nikyodo85/202fc2d417d9eb030d30896ccc862b7d",{"id":176,"title":177,"titles":178,"content":179,"level":9},"/2025/10/05-unc-and-url","05 UNC And URL",[],"UNC and URL This is a repost from my old blog. First posted in 10/10/2018. Found something weird today. For a long time, we have published our project to the test environment using the following UNC pattern: \\\\testservername.productiondomain.com\\shared-path. However, when I did that today, it accidentally connected to production. Removing the domain as part of the UNC solves the problem. The weird thing is the same UNC points to our test environment when run on my coworker's computer. Nothing is weird on our hosts file. I have not figured out why this is so.",{"id":181,"title":182,"titles":183,"content":184,"level":9},"/2025/10/06-invoke-webrequest-powershell-command-through-aws-system-manager","06 Invoke WebRequest PowerShell Command Through AWS System Manager",[],"Invoke-WebRequest PowerShell Command through AWS System Manager This is a repost from my old blog. First posted in 10/25/2018. I had a small issue with running Invoke-WebRequest through Amazon AWS System Manager. Somehow it doesn't seem to load the module properly. I ended up replacing: Invoke-WebRequest -Uri \u003Curl> with: $WebClient = New-Object System.Net.WebClient\n$WebClient.DownloadString(\u003Curi>) which works perfectly for my case.",{"id":186,"title":187,"titles":188,"content":189,"level":9},"/2025/10/07-powershell-split-string-by-whitespaces-or-multiple-spaces-using-regex","07 PowerShell Split String By Whitespaces Or Multiple Spaces Using Regex",[],"PowerShell Split String by Whitespaces or Multiple Spaces Using Regex This is a repost from my old blog. First posted in 10/25/2018. I was looking into a way to split string that can take regular expression in PowerShell. Surprisingly, they have the capability: $StringArray = $StringInput -split '\\s+'",{"id":191,"title":192,"titles":193,"content":194,"level":9},"/2025/10/08-from-aws-system-manager-document-to-linux-ec2-powershell-script","08 From AWS System Manager Document To Linux EC2 PowerShell Script",[],"From AWS System Manager Document to Linux EC2 PowerShell Script This is a repost from my old blog. First posted in 10/25/2018. Let me start from what I'm trying to accomplished. Basically, I need to map partitions in Linux with EBS volumes. I first tried \"df\" command which works great. Through the following article, I found a way to retrieve corresponding volumes attached to the EC2 instance. https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-windows-volumes.html Next, it is just a matter to marry both of them and output them as json. After many web searches and pages, I decided to install PowerShell Core to utilize its ConvertTo-Json function. All went great and I would like to create a new AWS System Manager Command Document so I can fire up an api call to execute the script. I first tried AWS System Manager's RunPowerShellScript document which claims to be able to execute PowerShell script on Linux. However, it somehow failed. I checked the requirements, update SSM Agent to no avail. Eventually, we submitted support ticket and waiting for the reply. While waiting for the support reply, I found a workaround. The RunShellScript document works fine and PowerShell supports running command as argument, so I tried: pwsh -Command \"\u003Cthe_command>\" And it failed. Through trial and error, I found out that I need to escape the $ sign on the document side. I then tried again. And of course, it failed again. Next, I remembered that double quotes needs to be escaped in the document. However, it can create confusion on the execution side, so it has to be escaped the second time for PowerShell argument. On the document, it becomes: \" pwsh -Command \\\"\\$PS_Variable=\\\\\\\"Intended String\\\\\\\"\\\"\" The double escape works for the double quotes, but it is troublesome, so I decided to change the internal double quotes to single quote because PowerShell can handle it too and no escape needed. \" pwsh -Command \\\"\\$PS_Variable='Intended String (cleaner, no?)'\\\"\" However, I found out another issue, single quote does not handle insert of variable and thus for my case, it still failed. \" pwsh -Command \\\"\\$PS_Variable='This does work'\\\"\"\n\n\" pwsh -Command \\\"\\$PS_Variable='NOT' \\$YetAnotherVariable='This does \\$PS_Variable work'\\\"\" Well, it is easy, just return it to double-escaped double quotes. Next, I had another issue that it is unable to access AWS API. After another set of trials and errors, I found out that I need to import AWS Powershell module in the document, thus I have to add the following line: \" Import-Module AWSPowerShell.NetCore\" or shorthand: \" ipmo AWSPowerShell.NetCore\" And now it is 5 and works perfectly. Edit 10/26/2018: AWS support replied that there is indeed an issue with the RunPowerShell script command. Edit 11/01/2018: AWS support said the internal team were able to replicate the issue and working on the fix. No ETA as of today.",{"id":196,"title":197,"titles":198,"content":199,"level":9},"/2025/10/09-supressing-output-in-powershell","09 Supressing Output In PowerShell",[],"Supressing Output in PowerShell This is a repost from my old blog. First posted in 11/1/2018. I was working with DiskPart, PowerShell, and Amazon SSM. Whenever I run DiskPart from PowerShell, the output was reflected in the console and it was recorded as Amazon SSM run command output, thus my run command was not completely clean. Such as the following: Microsoft DiskPart version 6.3.9600\nCopyright (C) 1999-2013 Microsoft Corporation.\nOn computer: MyComputer\nDISKPART>\nDisk 1 is now the selected disk.\nDISKPART>\nDiskPart successfully converted the selected disk to dynamic format. Reading Q&A and documentation online, seems like no straightforward way to suppress output from DiskPart. I then tested something, how about if I assign the output to a variable and ignore it. It works and the command is still executed. For example, listing volume will be like the following in PowerShell: $DiskPartOutput = 'list volume' | diskpart",{"id":201,"title":202,"titles":203,"content":204,"level":9},"/2025/10/10-entity-framework-(ef)-slow-insert-and-sqlbulkcopy-to-the-rescue","10 Entity Framework (EF) Slow Insert And SqlBulkCopy To The Rescue",[],"Entity Framework (EF) Slow Insert and SqlBulkCopy to the Rescue This is a repost from my old blog. First posted in 11/1/2018. There was a need to insert bulk data into the database and we are using Entity Framework as our ORM strategy. However, bulk insert took forever. Disabling Auto Detect Changes helps a little. So I decided to look into SqlBulkCopy and ended up writing one for Entity Framework. It is generic enough and can be found in https://gist.github.com/nikyodo85/b82ffd56bb2f0d45a9860dadcdfdc01d. It works well so far. Some of the drawbacks are: It won't be able to auto insert relationshipNo validation check But very fast. To use it will be very similar to SqlBulkCopy: Dim efSqlBulkCopy As New EFSqlBulkCopy(Of MyEntityClass)(myDbContext)\nefSqlBulkCopy.WriteToServer(listOfMyEntityClass)",{"id":206,"title":207,"titles":208,"content":209,"level":9},"/2025/10/11-unable-to-getpassword-on-aws-ec2-launched-from-windows-server-2016-custom-ami","11 Unable To GetPassword On AWS EC2 Launched From Windows Server 2016 Custom AMI",[],"Unable to GetPassword on AWS EC2 Launched from Windows Server 2016 Custom AMI This is a repost from my old blog. First posted in 11/19/2018. We found out that our custom AMI doesn't allow us to enable GetPassword from AWS console on any EC2 launched from it. After reading and some trial and error, we found out that InitializeInstance.ps1 has to be enabled for the next boot. https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2launch.html#ec2launch-inittasks To be complete, LaunchConfig.json has to have adminPasswordtype set to Random (default). Then, run the following PowerShell command: C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeInstance.ps1 -Schedule",{"id":211,"title":212,"titles":213,"content":214,"level":9},"/2025/10/12-aws-systems-manager-(ssm)-run-command-troubleshooting","12 AWS Systems Manager (SSM) Run Command Troubleshooting",[],"AWS Systems Manager (SSM) Run Command Troubleshooting This is a repost from my old blog. First posted in 1/17/2019. I have been working with AWS SSM for couple of months, but I found the troubleshooting document on their website lacks straightforward answers. So I provide the problems that I encountered and the solution based on my experience. Problem #1: The instance is not visible in AWS Systems Manager Console although documentation says the agent has been installed by default. Problem #2: The instance is visible, but \"Run Command\" took too long and even timed out. Solution:\nFirst thing I would check is whether the instance has a role attached to it.\nIf so, make sure the role has AmazonEC2RoleforSSM policy attached to it since permission is required for the agent to do health check.\nIf after all the above has been confirmed, check if the latest SSM agent has been installed and running. If SSM agent is at the latest and running, check if it is hibernating. The hibernate logic has exponential backoff, so it might not respond for a long time. If it is hibernating, we can simply restart the agent. On Windows, we can run Restart-Service AmazonSSMAgent PowerShell command. On Linux, we can run sudo restart amazon-ssm-agent shell command. If all the above fails, it is time to get into the log files. On Windows: %PROGRAMDATA%\\Amazon\\SSM\\Logs\\amazon-ssm-agent.log\n%PROGRAMDATA%\\Amazon\\SSM\\Logs\\errors.log On Linux: /var/log/amazon/ssm/amazon-ssm-agent.log\n/var/log/amazon/ssm/errors.log If log files doesn't give enough information, we can enable debug logging which will give more information. This requires quite a number of steps, so refer to the reference link below. https://docs.aws.amazon.com/systems-manager/latest/userguide/troubleshooting-remote-commands.html#systems-manager-ssm-agent-debug-log-files",{"id":216,"title":217,"titles":218,"content":219,"level":9},"/2025/10/12-hack-midwest-2025","12 Hack Midwest 2025",[],"Hack Midwest 2025 We assembled a team of 4 to join Hack Midwest for the first time. It was great time and we won Best Design. Our app is on Digital Carnival backed by Stablecoin. There were some hiccups on the event itself, but overall great time. I also saw Carl and Patrick. Both are great friends in tech communities. My team:",{"id":221,"title":222,"titles":223,"content":224,"level":9},"/2025/10/13-troubleshooting-aws-instance-profile-role-and-ssm-agent","13 Troubleshooting AWS Instance Profile Role And SSM Agent",[],"Troubleshooting AWS Instance Profile, Role, and SSM Agent This is a repost from my old blog. First posted in 1/17/2019. During some AWS troubleshooting session, I happened to notice that there is a possibility of stale role attached to EC2. My scenario is as follow: We launched a new EC2 and by default no role attached to it. Then we programmatically create a role, let's call it EC2Role which we then associate it with a new Instance Profile. We then attach the Instance Role to our new EC2. In our case, the EC2Role allows SSM Agent to have permission to run commands. For somewhat reason, we decided to delete the EC2Role and again programmatically recreate a new role with the same name and associate it with a new Instance Profile. We noticed that when we don't detach the old role (which has the same name with the new one) from the EC2, the old role will still be attached to the EC2 although the old role itself has been deleted. Hence, we were confused on why the EC2 which has the right role attached to it will not run command sent by SSM. The SSM Agent log keeps saying the token is invalid. I did couple of troubleshooting steps. First, I restarted the SSM Agent and that didn't solve the problem. Second, in a different instance with the same problem, I detached and reattached the role and that didn't work either. Third, I combined previous two steps on a single instance, so I detached and reattached the role then restarted the agent and it works afterwards.",{"id":226,"title":227,"titles":228,"content":229,"level":9},"/2025/10/14-understanding-aws-security-group","14 Understanding AWS Security Group",[],"Understanding AWS Security Group This is a repost from my old blog. First posted in 2/8/2019. We were playing with AWS Aurora Serverless. After figuring out how to configure and start the database cluster, we were having trouble connecting to it from our EC2 instance. Few hours later, I tried tracing what was going on with Flow Logs in the subnet. We realized it was a network and/or security issue. Checking all possible connections and security, we think everything has been configured correctly. But only after trial and error, we found out that our understanding of security group was incorrect. Due to AWS security group being promoted as stateful, we understand it as if we specify an entry in Inbound tab, we don't need to specify it in Outbound. Sadly, that is not what stateful means. Each entry specifies the allowed origin of the network request and the response will be automatically allowed. For example, if we allow in Inbound only, a request can come from outside and allowed to the EC2 instance and out, but a request from the instance won't be allowed to go out of the instance. And that is precisely what our problem is, we have an entry in the Inbound tab, but we try to connect from inside the EC2 instance, but was rejected because we don't allow the connection on the Outbound tab. As soon as we allow the connection on the Outbound tab, the problem is fixed.",{"id":231,"title":232,"titles":233,"content":234,"level":9},"/2025/10/15-read-only-file-system-error-in-linux","15 Read Only File System Error In Linux",[],"Read-only File System Error in Linux This is a repost from my old blog. First posted in 2/8/2019. I was moving the content of CentOS boot drive to a new hard drive. CentOS has MBR partition with xfs file system. It worked great, boot fine, but when I tried to do yum install, it barked that it can't do the install because the file system is read-only. After a decent amount of research, I found out that the problem lies on the /etc/fstab. Because it is new hard drive, the UUID is different and grub2-mkconfig used the new UUID to configure the grub.cfg. However, when it is booted, it checked the /etc/fstab and found the discrepancy. Once I changed the /etc/fstab to reflect the new UUID, the error went away.",{"id":236,"title":237,"titles":238,"content":239,"level":9},"/2025/10/16-lzma-sdk-compress-decompress","16 LZMA SDK Compress Decompress",[],"LZMA SDK Compress Decompress This is a repost from my old blog. First posted in 2/27/2019. 7z is one of the best if not the best file compression available. Best of all, it is open source. The engine behind it is the LZMA compression method. I was integrating the sdk (https://www.7-zip.org/sdk.html) in my project, but however, can't get a quick start on the compress decompress process. After searching the internet, I figured out on a surface level how it all works. Partially thanks to the question in https://stackoverflow.com/questions/7646328/how-to-use-the-7z-sdk-to-compress-and-decompress-a-file. So, below, I write down my basic understanding. Compress Basically, the compressed file will contain 3 things with the first 2 are metadata: The first 5 bytes are compression properties\nThe next 8 bytes are file size before compression\nThe compressed bytes var encoder = New Encoder();\nencoder.WriteCoderProperties(outStream); // Write properties\nencoder.Write(BitConverter.GetBytes(inputFileSize), 0, 8); // Write uncompressed file size\nencoder.Code(inStream, outSteam, inStream.Length, -1, null); // Actual compress Decompress To decompress the file, the metadata needs to be provided to the decoder. My code initially threw an error because there is no metadata. var properties = new byte[5];\ninStream.Read(properties, 0, 5); // Read properties\n\nvar fileSizeBytes = new byte[8];\ninStream.Read(fileSizeBytes, 0, 8); // Read uncompressed file size\nvar fileSize = BitConverter.ToInt64(fileSizeBytes, 0);\n\nvar decoder = New Decoder();\ndecoder.SetDecoderProperties(properties); // Provide the properties to decoder\ndecoder.Code(inStream, outStream, inStream.Length, fileSize, null); // Actual decompress",{"id":241,"title":242,"titles":243,"content":244,"level":9},"/2025/10/17-linux-script-conditional-conditions","17 Linux Script Conditional Conditions",[],"Linux Script Conditional Conditions This is a repost from my old blog. First posted in 3/21/2019. Like most people, I guess, I came from Windows background. Just recently, I have projects exploring multiple flavors of Linux and spending a lot of time to understand how conditions work in bash and/or shell script in Linux. And then my code didn't work and that took me on a journey. Long time ago, I tried to do something as simple as the following: if (\u003Cexpr1> or \u003Cexpr2>) and (\u003Cexpr3> or \u003Cexpr4>) then \u003Cdo this> fi But things get complicated as the expressions involve which and grep commands. For example, I'm checking if any python is installed, so my first attempt was if [ \"`which python`\" = \"\" -a \"`which python3`\" = \"\" ]; then echo \"no python\"; fi then I realize that in RedHat, if there is no python installed, it will return a string containing \"no python\" instead of empty string, so my code becomes if [ \\( \"`which python`\" = \"\" -o \"`which python | grep 'no python'`\" = \"\" \\) -a \\( \"`which python3`\" = \"\" -o \"`which python3 | grep 'no python3'`\" = \"\" \\) ]; then \n\n     echo \"no python\"; \n\nfi Well, it didn't work. Scrutinizing it a bit more. I found out that when there is no python, grep doesn't return empty string, but instead a failure code, so that turns my code into: if [ \\( \"`which python`\" = \"\" -o \"`which python | grep 'no python'`\" \\) -a \\( \"`which python3`\" = \"\" -o \"`which python3 | grep 'no python3'`\" \\) ]; then \n\n     echo \"no python\"; \n\nfi Which seems to work so far, but for consistency, I prefer to use the flag -z to check for empty string and -n to check for non empty string, so the code becomes if [ \\( -z \"`which python`\" -o -n \"`which python | grep 'no python'`\" \\) -a \\( -z \"`which python3`\"  -o -n \"`which python3 | grep 'no python3'`\" \\) ]; then \n\n     echo \"no python\"; \n\nfi",{"id":246,"title":247,"titles":248,"content":249,"level":9},"/2025/10/18-aws-ssm-linux-shell-script-closing-paren-expected-error","18 AWS SSM Linux Shell Script Closing Paren Expected Error",[],"AWS SSM Linux Shell Script Closing Paren Expected Error This is a repost from my old blog. First posted in 3/21/2019. I ran my scripts through AWS SSM and received the \"closing paren expected\" error message. Quick check on my code, I was missing items in two different situations: I was missing closing parentheses \\), so adding it solves the issue. My code was like: if [ \\( \u003Cexpr> ]; then \u003Cdo this>; fi My closing parentheses was not prefixed by space, so adding a space fixed it. It was like: if [ \\( \u003Cexpr>\\) ]; then \u003Cdo this>; fi",{"id":251,"title":252,"titles":253,"content":254,"level":9},"/2025/10/19-where-is-my-environment-variables-journey-to-linux-service","19 Where Is My Environment Variables Journey To Linux Service",[],"Where is My Environment Variables? Journey to Linux Service This is a repost from my old blog. First posted in 3/29/2019. Ok, I had a .NET Core Web App running in Ubuntu behind Nginx. Everything else is fine except I can't retrieve the value of the environment variables that I put in /etc/environment. After hours of googling, turns out systemd service strips all out except some variables. Two ways to fix this: Put the environment variable in the .service config file [Service]\nEnvironment=MY_ENV_VAR=thevalue Include /etc/environment in the service. (I don't think this is a good idea, especially for my use case). [Service]\nEnvironmentFile=/etc/environment",{"id":256,"title":257,"titles":258,"content":259,"level":9},"/2025/10/20-method-not-found-system.net.http.httpcontentextensions.readasasync","20 Method Not Found SystemNetHttpHttpContentExtensionsReadAsAsync",[],"",{"id":261,"title":262,"titles":263,"content":264,"level":265},"/2025/10/20-method-not-found-system.net.http.httpcontentextensions.readasasync#date-2025-10-20","date: 2025-10-20",[257],"Method not found System.Net.Http.HttpContentExtensions.ReadAsAsync This is a repost from my old blog. First posted in 3/30/2019. Bumped into this error when moving my web app to another server. It happened to me before but this time the cause is different. So two ways that worked for me: Install package Microsoft.AspNet.WebApi.Client. This will provide access to HttpFormatting.dll which actually contains the ReadAsAsync method and fixed the issue for me before.I found out that my System.Net.Http was not referenced properly because it depends on the dll installed in the machine. So, installing System.Net.Http NuGet package fix the current issue for me.",2,{"id":267,"title":268,"titles":269,"content":270,"level":9},"/2025/10/21-model-binding-issue-asp.net-core-in-ubuntu-using-postman","21 Model Binding Issue ASPNET Core In Ubuntu Using Postman",[],"Model Binding Issue ASP.NET Core in Ubuntu using Postman This is a repost from my old blog. First posted in 4/5/2019. I spent a fair amount of time trying to troubleshoot my ASP.NET Core web server in Ubuntu. The issue starts when I noticed a failed model binding in Ubuntu using HTTP PUT method when it works locally on my Window machine. I also found out that it binds properly when I used HTTPS compared to HTTP. Looking into the server, I have configured Nginx as reverse proxy server which send a 301 Redirect to HTTPS when the request is made using HTTP. I can't find any issue on the web application itself, Nginx, so I decided to check Postman which I used to generate the request. I found out that by default, Postman always follows redirect. There is nothing wrong with that, except seems like the data is lost during redirect. Eventually I found out that, 301 is meant to be used with GET and thus any POST/PUT data will be scrapped during redirect. Hence, it is the correct logic all along.",{"id":272,"title":273,"titles":274,"content":275,"level":9},"/2025/10/22-salesforce-cpq-lightning-template-content-font-color","22 Salesforce CPQ Lightning Template Content Font Color",[],"Salesforce CPQ Lightning Template Content Font Color This is a repost from my old blog. First posted in 4/5/2019. Somehow I was involved in trying to change the font color in Salesforce CPQ template content. Seems easy but it is not working the way we want. We selected HTML as the content type and it comes with a nice rich text editor. As we change the font color, it looks great on the page. However, when we attach the template content to the quote template and preview the quote with that template, couple of things occurs: The font color is gone and reflected back to blackIt puts the next words which is supposed to be different color in a new line We double-checked the HTML and can't find anything wrong with it. So I decided to check which engine generates the quote preview PDF and found out that it is using Apache FOP. The fun thing is Apache FOP doesn't support HTML inherently, but it does support XSL, so that's what we used. We inject XSL and have Salesforce CPQ interpret it and render the font color that we expect.",{"id":277,"title":278,"titles":279,"content":280,"level":9},"/2025/10/23-xamarin-java.exe-exited-with-code-2-error","23 Xamarin JavaExe Exited With Code 2 Error",[],"Xamarin \"java.exe exited with code 2\" Error This is a repost from my old blog. First posted in 5/11/2019. Bumped into the following error  \"java.exe exited with code 2\" when building Xamarin app today. The only thing change is I added a Syncfusion NuGet package. I managed to solve it by enabling MultiDex. Reference: https://forums.xamarin.com/discussion/97803/getting-error-java-exe-exited-with-code-2https://developer.android.com/studio/build/multidex",{"id":282,"title":283,"titles":284,"content":285,"level":9},"/2025/10/24-aws-aurora-reading-from-the-stream-has-failed-error","24 AWS Aurora Reading From The Stream Has Failed Error",[],"AWS Aurora \"Reading from the stream has failed\" Error This is a repost from my old blog. First posted in 5/14/2019. We had problem with Aurora SQL throwing error when it is in sleep (pause) mode. By default, it is set to sleep when idle for 5 minutes. After few attempts, we managed to extend the timeout which is command timeout (not to be confused with connection timeout) to 60s in our case to prevent the error from happening. The timeout can be set in connection string: Server=server;Database=database;Uid=username;Pwd=password;Default Command Timeout=60 Reference:\nhttps://www.connectionstrings.com/mysql-connector-net-mysqlconnection/specifying-default-command-timeout/ Update 12/3/2019\nThe above didn't work somehow on our ASP.NET application that used EntityFramework, so we have to specify it in our ApplicationDbContext constructor and increase it to 5 minutes (300s). The following is the VB.NET version: Public Sub New(existingConnection As Common.DbConnection, contextOwnsConnection As Boolean)\n    MyBase.New(existingConnection, contextOwnsConnection)\n    Database.CommandTimeout = 300\nEnd Sub",{"id":287,"title":288,"titles":289,"content":290,"level":9},"/2025/10/25-vb.net-exit-sub-finally","25 VBNET Exit Sub Finally",[],"VB.NET Exit Sub Finally This is a repost from my old blog. First posted in 6/10/2019. I have a recurring VB.NET application that will start every 15 minutes. However, as a precaution, the next scheduled instance of the application will immediately exit if the previous instance is still running. To keep track of the status of the application, I put a code in the finally block that will update the status to stopped and save it to the database. I noticed that somehow the status of the application was stopped but the application still running in the task manager. There is no background worker so it should exit when the status is updated. It turns out that the subsequent instance update the status when it exited due to finally block is always executed even on \"Exit Sub\"",{"id":292,"title":293,"titles":294,"content":295,"level":9},"/2025/10/26-aws-code-deploy-error-make-sure-your-appspec-file-specifies-0.0-as-the-version","26 AWS Code Deploy Error Make Sure Your AppSpec File Specifies 00 As The Version",[],"AWS Code Deploy Error: Make sure your AppSpec file specifies \"0.0\" as the version This is a repost from my old blog. First posted in 6/19/2019. I got this error when attempting to deploy using AWS Code Deploy. Checking the appspec.yml, it does have: version: 0.0. One of the suggestions in StackOverflow was the line ending has to Linux. However that did not help in my case. Since I'm deploying to Windows, the line ending has to be Windows. After couple trial and error. I found out that Visual Studio save my appspec.yml with UTF-8 encoding, so I proceed to change it to \"Western European (Windows) - Codepage 1252\" encoding and code deploy works flawlessly. To change the encoding, I use the following steps in VS2017: Select the file in Solution Explorer.Click File menu on Visual StudioSelect Save  As...On the pop up, click the tiny arrow next to the Save buttonSelect Save with Encoding...I select Western European (Windows) - Codepage 1252 for the Encoding and Current Setting for the Line endings.",{"id":297,"title":298,"titles":299,"content":300,"level":9},"/2025/10/27-a2-hosting-new-website-asp.net-default-page-not-shown","27 A2 Hosting New Website ASPNET Default Page Not Shown",[],"A2 Hosting New Website ASP.NET Default Page Not Shown This is a repost from my old blog. First posted in 8/6/2019. This might affect other hosting too, but it just happened that I bumped into it in my A2 hosting account. Basically I created a new website and upload the files. I had the domain name servers updated. Everything looks good. But for somewhat reason, my default page is not shown by default. I checked the DNS propagations and it was done. I try visiting one of the pages in my website and it works great. But somehow when entering only the domain name, it doesn't bring up the default page. After several hours, I figured out that there is index.html that was put when the directory was setup. Renaming it to something other than list of default documents fix the issue.",{"id":302,"title":303,"titles":304,"content":305,"level":9},"/2025/10/28-refresh-system-environment-variables-for-iis-and-visual-studio","28 Refresh System Environment Variables For IIS And Visual Studio",[],"Refresh System Environment Variables for IIS and Visual Studio This is a repost from my old blog. First posted in 8/7/2019. Environment variables can sometimes be a pain to deal with. Since environment variables are often cached or loaded only once, a change might not be immediately reflected in the application that we intend to apply them to. In my case, I need to debug our ASP.NET application and need the new environment variables. Restarting the Visual Studio itself was not enough.\nI tried to kill the worker process and that doesn't help either.\nAt the end, I tried one thing that works which I got from a forum, i.e., enter the following command on command prompt or PowerShell run in admin mode: iisreset",{"id":307,"title":308,"titles":309,"content":310,"level":9},"/2025/10/29-openvpn-client-save-connection-(ip-address)","29 OpenVPN Client Save Connection (IP Address)",[],"OpenVPN Client Save Connection (IP Address) This is a repost from my old blog. First posted in 8/21/2019. When I first used OpenVPN client, it was set up for me so I'm missing out on some configuration know how. And now I need to set up OpenVPN on a new computer and I need to save a connection so I can quickly connect to it the next time I log on. In this case, I'm using a v2.x.x OpenVPN client and I can't seem to figure out how to do that. It turns out that I have to be disconnected from all connections and then select Import > From server.... Then I can enter my connection information and it will be saved and easily accessible just by hovering over it and select Connect...",{"id":312,"title":313,"titles":314,"content":315,"level":9},"/2025/10/30-amazon-aurora-serverless-the-provider-did-not-return-a-providermanifesttoken-string-error","30 Amazon Aurora Serverless The Provider Did Not Return A ProviderManifestToken String Error",[],"Amazon Aurora Serverless \"The provider did not return a ProviderManifestToken string\" Error This is a repost from my old blog. First posted in 8/26/2019. We had a good working application which connect to Amazon Aurora Serverless pretty well and just recently it started to intermittently unable to connect with the error \"The provider did not return a ProviderManifestToken string\". The following is some spec of the application: .NET Framework 4.6.2\nMySQL.Data 6.10.9\nMySQL.Data.Entity 6.10.9\nEntityFramework 6.2.0 (EF6) When I debugged the application, it has inner exception which has the message: \"Sequence contains more than one matching element\". Upon more troubleshooting, I remember that Aurora Serverless is a cluster and it requires at least 2 subnets which reside in 2 different Available Zones. Amazon does not recommend the use of IP address instead provide us with an endpoint to connect to the cluster. That means, the endpoint might resolve to two IP addresses. So, I decided to see what DNS lookup will show and indeed, the endpoint resolves to two IP addresses. Hence, my suspect is the MySQLConnection was expecting a single IP and receive two instead from the URL and thus throws an error. I tried to replace the endpoint in the connection string with one of the IP addresses and no error, but that is not the expected solution. Additionally, there are intermittent errors with the following message:\nAuthentication to host '...' for user '...' using method 'mysql_native_password' failed with message: Reading from the stream has failed With more reading, I stumbled upon the following article: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.html At the end of the articles, it says \"If you use the mysql client to connect, currently you must use the MySQL 8.0-compatible mysql command.\" I then realized that I have been using MySQL.Data version 6.10.9 and that might need an update. However, there is no MySQL.Data.Entity with major version of 8 which I found out later that it has been changed to MySQL.Data.EntityFramework for .NET Framework application (for .NET Core application, use MySQL.Data.EntityFrameworkCore). So I put the endpoint back into the connection string and update the Nuget packages to: MySQL.Data 8.0.20 8.0.17\nMySQL.Data.EntityFramework 8.0.20 8.0.17 And this time, the application is finally able to connect successfully. As a side note, MySQL Workbench with major version of 8 that can connect just fine. Additionally, we need to have a custom DbExecutionStrategy to handle the error that might happen, possibly because of cut-off connection due to scaling, and retry. In my case, it is like the following: Public Class MyCustomDbExecutionStrategy\n        Inherits DbExecutionStrategy\n\n    Sub New(maxRetryCount As Integer, maxDelay As TimeSpan)\n        MyBase.New(maxRetryCount, maxDelay)\n    End Sub\n\n    Protected Overrides Function ShouldRetryOn(exception As Exception) As Boolean\n        Return exception IsNot Nothing AndAlso exception.Message.Contains(\"Reading from the stream has failed\")\")\n    End Function\nEnd Class\n\nAnd the custom DbExecutionStrategy has to be applied manually as follow:\n\nDim executionStrategy As New MyCustomDbExecutionStrategy(5, TimeSpan.FromSeconds(15))\nexecutionStrategy.Execute(\n    Sub()\n        Using dbContext = New MyDbContext()\n        ...\n        End Using\n    End Sub) Please refer to update July 2, 2020 and July 6, 2020 for additional information. Updates\nNovember 14, 2019\nFor somewhat reason, updating the Nuget packages to version 8.0.18 brings back the error, so we stay with 8.0.17 for now. November 27, 2019\nI have a bit of time to play so I checked if the new version really doesn't work. After upgrading it from 8.0.17 to 8.0.18, it truly doesn't work. The following are the error messages and stack traces 3 layer deep exception: Top level exception\n\"The provider did not return a ProviderManifestToken string.\"\n\n   at System.Data.Entity.Core.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection)\n   at MySql.Data.EntityFramework.MySqlManifestTokenResolver.ResolveManifestToken(DbConnection connection)\n   at System.Data.Entity.Utilities.DbConnectionExtensions.GetProviderInfo(DbConnection connection, DbProviderManifest& providerManifest)\n   at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)\n   at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)\n   at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)\n   at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()\n   at System.Data.Entity.Internal.InternalContext.Initialize()\n   at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)\n   at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()\n   at System.Data.Entity.Internal.Linq.InternalSet`1.AsNoTracking()\n   at System.Data.Entity.Infrastructure.DbQuery`1.AsNoTracking()\n   at ... First inner exception \"Unable to connect to any of the specified MySQL hosts.\"\n\n   at MySql.Data.MySqlClient.NativeDriver.Open()\n   at MySql.Data.MySqlClient.Driver.Open()\n   at MySql.Data.MySqlClient.Driver.Create(MySqlConnectionStringBuilder settings)\n   at MySql.Data.MySqlClient.MySqlPool.CreateNewPooledConnection()\n   at MySql.Data.MySqlClient.MySqlPool.GetPooledConnection()\n   at MySql.Data.MySqlClient.MySqlPool.TryToGetDriver()\n   at MySql.Data.MySqlClient.MySqlPool.GetConnection()\n   at MySql.Data.MySqlClient.MySqlConnection.Open()\n   at MySql.Data.MySqlClient.MySqlProviderServices.GetDbProviderManifestToken(DbConnection connection)\n   at System.Data.Entity.Core.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection) Last inner exception \"Sequence contains more than one matching element\"\n\n   at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)\n   at MySql.Data.Common.StreamCreator.GetTcpStream(MySqlConnectionStringBuilder settings)\n   at MySql.Data.Common.StreamCreator.GetStream(MySqlConnectionStringBuilder settings)\n   at MySql.Data.MySqlClient.NativeDriver.Open() Searching online, I found the following thread: https://forums.mysql.com/read.php?38,678859,678859#msg-678859 which leads to the following bug report: https://bugs.mysql.com/bug.php?id=97448 And eventually the actual code change: https://github.com/mysql/mysql-connector-net/commit/9bc44843fda0c2e4aed1e22cc00c1221d17dc00b#diff-7440e953b4e85502ea58c60b17f249ee For now, we still stick with 8.0.17 until further fix. June 25, 2020\nActually from the last update until now, we still experience intermittent issues with the error. So, I did few more testing. In my case, I took the following steps to get it completely error free. Probably some steps are not necessary but I haven't had time to test what is actually necessary. Step 1 (update 7/2/2020, the function somehow is not called)\nCreate custom DbExecutionStrategy. Mine is actually very simple. All I did is retry only when the error message contains \"ProviderManifestToken\". I found out MySqlExecutionStrategy that comes with the Nuget package doesn't work for my case. Protected Overrides Function ShouldRetryOn(exception As Exception) As Boolean\n    Return exception IsNot Nothing AndAlso exception.Message.Contains(\"ProviderManifestToken\")\nEnd Function Step 2\nCreate a custom DbConfiguration. This is where we can set our custom DbExecutionStrategy. My custom class derives from MySqlEFConfiguration to get all the preset goodness. Public Class MyCustomDbConfiguration\n        Inherits MySqlEFConfiguration\n\n    Sub New()\n        MyBase.New()\n        SetExecutionStrategy(MySqlProviderInvariantName.ProviderName, Function() New MyCustomDbExecutionStrategy())\n    End Sub\n\nEnd Class Couple of things to watch out for:\nWe can only use one DbConfiguration per provider per app domain. I got an error when trying to assign different configuration to different DbContext within a single application.\nSomehow SetExecutionStrategy caused an error when we execute raw sql with the following message: \"Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index\". So we still use MySqlEFConfiguration for the application that has raw SQL.\nSetExecutionStrategy is marked to cause an issue with Transactions in MySql GitHub.  For more info: https://github.com/mysql/mysql-connector-net/blob/68c54371821c87ff40a773acc127ce357b46a5ae/Source/MySql.Data.EntityFramework6/MySqlEFConfiguration.cs Step 3\nThere are 3 different ways to apply a DbConfiguration according to the MySQL Connector documentation: https://dev.mysql.com/doc/connector-net/en/connector-net-entityframework60.html Adding the DbConfigurationTypeAttribute on the context classCalling DbConfiguration.SetConfiguration(new MySqlEFConfiguration()) at the application start upSet the DbConfiguration type in the configuration file. What I didn't know is which one takes precedence over which. I found out later that the one in configuration file will take precedence over code-based: https://docs.microsoft.com/en-us/ef/ef6/fundamentals/configuring/code-based In my case, I need the DbContext to default to use MySqlEFConfiguration and overwrite as necessary. So for those applications that need to use the custom DbConfiguration, I added the codeConfigurationType attribute in the config file (app.config/web.config): \u003CentityFramework codeConfigurationType=\"namespace.MyCustomDbConfiguration, assembly\"> Step 4\nOn my applications that has the error, the default connection factory was set to LocalDbConnectionFactory. So, following MySQL Connector documentation, I set it to the following under the \u003CentityFramework> tag: \u003CdefaultConnectionFactory type=\"System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework\"/> I found out later that this step might not be necessary as it will only be used when there is no connection string, but I leave it that way since it doesn't hurt. https://docs.microsoft.com/en-us/ef/ef6/fundamentals/configuring/config-file#code-first-default-connection-factory Step 5\nThe server that hosted my problematic applications might not have MySql connector installed, so according to the MySQL Connector documentation, I should have added the following entry in the config file: \u003Csystem.data>\n   \u003CDbProviderFactories>\n     \u003Cremove invariant=\"MySql.Data.MySqlClient\" />\n     \u003Cadd name=\"MySQL Data Provider\" invariant=\"MySql.Data.MySqlClient\" description=\".Net Framework Data Provider for MySQL\" \n          type=\"MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=8.0.17.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d\" />\n   \u003C/DbProviderFactories>\n\u003C/system.data> Watch out for the version number. It needs to match the MySql.Data.dll assembly version. So far, the error has not re-appeared in my case. Also, there is a new version 8.0.20 Nuget packages as of this update. I haven't tested it extensively so I can't vouch for its compatibility for now. However, I might write an update once I am certain it doesn't cause issue in our applications. July 2, 2020\nThe steps on update June 25, 2020 was not working somehow. When we have a lot of processes hitting the database, the error message returns. I did a quick check and found out that the ShouldRetryOn function was not called. I ended up manually calling the execution strategy. https://docs.microsoft.com/en-us/ef/ef6/fundamentals/connection-resiliency/retry-logic#solution-manually-call-execution-strategy Dim executionStrategy As New MyCustomDbExecutionStrategy()\nexecutionStrategy.Execute(\n    Sub()\n        Using dbContext = New MyDbContext()\n        ...\n        End Using\n    End Sub) On the Nuget version, I found out MySQL.Data and MySQL.Data.EntityFramework version 8.0.20 can connect to Aurora Serverless just fine. July 6, 2020\nAfter diving deeper into the code, I had to make a few adjustment and finally managed to ensure that the exception was properly handled. First, I reanalyzed the exception details and found out the inner exception is slightly different than the one specified in update November 27, 2019 with the following message: Authentication to host '...' for user '...' using method 'mysql_native_password' failed with message: Reading from the stream has failed Second, by the time the exception reaches ShouldRetryOn method, it has been unwrapped. https://github.com/dotnet/ef6/blob/master/src/EntityFramework/Infrastructure/DbExecutionStrategy.cs Third, I have to update my ShouldRetryOn to check for the error message above instead of checking for \"ProviderManifestToken\" string since it is the inner exception will be passed to ShouldRetryOn. In my case, I prefer to check for \"Reading from the stream has failed\" string with hope to capture broader errors. Protected Overrides Function ShouldRetryOn(exception As Exception) As Boolean\n    Return exception IsNot Nothing AndAlso exception.Message.Contains(\"Reading from the stream has failed\")\")\nEnd Function Looking into the log file of my application, it finally retries fine and the application ran without issue.",{"id":317,"title":318,"titles":319,"content":320,"level":9},"/2025/10/31-asp.net-web-forms-auth0-and-owin","31 ASPNET Web Forms Auth0 And OWIN",[],"ASP.NET Web Forms, Auth0 and OWIN This is a repost from my old blog. First posted in 10/16/2019. Sometimes supporting an old technology is much more troublesome, but when you manage to overcome the challenge, you will be feeling so much more satisfied. My boss wants to use Auth0 for authentication, but the application that we need to modify is in ASP.NET Web Forms and there is no Auth0 quickstart for ASP.NET Web Forms and I can't find an example online. I remember I saw somewhere that we can use OWIN on ASP.NET Web Forms with a bit of tweaking. Following the awesome blog post below, I managed to get OWIN to work. https://tomasherceg.com/blog/post/modernizing-asp-net-web-forms-applications-part-2 Next, I followed Auth0 quickstart for ASP.NET (OWIN) https://auth0.com/docs/quickstart/webapp/aspnet-owin/01-login#configure-auth0 One thing to note, the RedirectUri specified in the app has to be registered in Callback URLs in the Auth0 account. Then comes the customization. First, I need to be able to secure pages. Reading online, I found out that simply adding the following to web.config works great. Notice the authentication tag with mode set to None. \u003Csystem.web>\n      \u003Cauthorization>\n        \u003Cdeny users=\"?\"/>\n      \u003C/authorization>\n      \u003Cauthentication mode=\"None\"/>\n    \u003C/system.web> Second, I need to capture the redirect. Based on the Auth0 quickstart, whenever a secure page is requested, it will redirect to https://domain_name/Account/Login. For somewhat reason when I change this path under LoginPath in the quickstart, it doesn't change the redirection at all. So I decided to leave it as is. Per my understanding, unless FriendUrls is enabled in ASP.NET Web Forms, /Account/Login won't work properly. That means I have to handle it manually. At a glance, my options are HTTP Module or OWIN Middleware. Since I already have OWIN installed, I wrote a custom OWIN Middleware. https://www.hanselman.com/blog/IntroducingASPNETFriendlyUrlsCleanerURLsEasierRoutingAndMobileViewsForASPNETWebForms.aspx There are many ways in writing custom middleware, so I just picked one. https://benfoster.io/blog/how-to-write-owin-middleware-in-5-different-steps On my middleware Invoke method, I have the following: public async override Task Invoke(IOwinContext context)\n{\n       if (context.Request.Uri.AbsolutePath.Equals(\"/Account/Login\", StringComparison.OrdinalIgnoreCase))\n       {\n             string auth0RedirectUri = ConfigurationManager.AppSettings[\"auth0:RedirectUri\"];\n             context.Authentication.Challenge(new AuthenticationProperties\n            {\n                RedirectUri = auth0RedirectUri\n            }, \"Auth0\");\n        }\n        else\n        {\n              await Next.Invoke(context);\n         }\n} Then I register my middleware after app.UseOpenIdConnectAuthentication() in Auth0 quickstart with code similar to the following: app.Use(typeof(CustomMiddleware)); And that's it. So far, it has been working well.",{"id":322,"title":323,"titles":324,"content":325,"level":9},"/2025/11/01-remove-git-ssh-passphrase","01 Remove Git Ssh Passphrase",[],"Remove Git SSH Key Passphrase Long story short, the passphrase is getting annoying especially for my personal project. So, I'm removing it with the command: ssh-keygen -p -f /path_to_private_key Usually the private key is located under %USERPROFILE%/.ssh folder in Windows. In my case, it is %USERPROFILE%/.ssh/id_ed25519, so using powershell: ssh-keygen -p -f $env:USERPROFILE/.ssh/id_ed25519",{"id":327,"title":328,"titles":329,"content":330,"level":9},"/2025/11/02-aspire.hosting-package-version-9.0.0-is-not-supported","02 AspireHosting Package Version 900 Is Not Supported",[],"Aspire.Hosting package version 9.0.0 is not supported Today, I try the dedicated Aspire Cli. The installation went smoothly with: dotnet tool install -g Aspire.Cli --prerelease For more information: https://learn.microsoft.com/en-us/dotnet/aspire/cli/install Running Aspire project is easy as well as I can be at any parent directory/folder and simply run the following command and it will search for AppHost.csproj recursively. aspire run However, during my attempt, it throws the following error: The Aspire.Hosting package version 9.0.0 is not supported. Please update to the latest version. So, I ensure all packages in my projects are updated to the latest, but it didn't work. I found out later that the Sdk was not updated as I still found the following entry in my AppHost.csproj file even after all packages updated to version 9.5.2. \u003CSdk Name=\"Aspire.AppHost.Sdk\" Version=\"9.0.0\" /> Following the instructions in: https://learn.microsoft.com/en-us/dotnet/aspire/get-started/upgrade-to-aspire-9?pivots=dotnet-cli, I updated the version manually to 9.5.2 so it becomes: \u003CSdk Name=\"Aspire.AppHost.Sdk\" Version=\"9.5.2\" /> Rerun the aspire run command and voilà! Back and running.",{"id":332,"title":333,"titles":334,"content":335,"level":9},"/2025/11/03-kernel-not-updated-on-ubuntu-14.04-in-aws-ec2-nitro-based-instance","03 Kernel Not Updated On Ubuntu 1404 In AWS EC2 Nitro Based Instance",[],"Kernel not Updated on Ubuntu 14.04 in AWS EC2 Nitro-based Instance This is a repost from my old blog. First posted in 11/13/2019. Sometimes a simple thing which works for many others doesn't work for us and this time it is on updating the Linux kernel. It is all started when we are trying to migrate an m1 to t3. We are aware that t3 is a Nitro-based instance thus NVMe and ENA module have to be installed. Even after following AWS documentation, the modules don't seem to be installed properly even after reboot. Then the journey begins. First, I ran the following command to check what kernel is actually loaded: uname -r In this particular case, it returns: 3.13.0-45-generic. And I know that it is not the latest. So, as suggested by Amazon support, I ran the following commands one by one to see if the latest linux-aws package are properly installed and at the latest and nvme driver is loaded into the kernel (NVME driver is set to 'Y') sudo apt-cache policy linux-aws\n\nls -al /boot/\n\ncat /boot/config-4.4.0-1044-aws |grep -i \"nvme\" And the result are all as expected. The latest kernel is installed and nvme driver is loaded, but somehow the latest kernel is not used. I ran the following command to confirm. dpkg -l | grep 'linux-image-' On the amazon kernel, it starts with ii so it is indeed properly installed. Searching more online, some people manage to get the latest kernel installed and loaded using a combination of the following commands: sudo apt-get update (update packages)\n\nsudo apt-get install linux-generic (install meta package which was missing from my instance)\n\nsudo apt-get install --reinstall linux-image-4.4.0-1044-aws (replace the last part with the latest kernel to reinstall)\n\nsudo apt-get autoremove (clean up)\n\nsudo apt-get install -f (force install missing packages)\n\nupdate-grub (update grub) None seems to work for me. After several days, I was wondering if somehow it has something to do with grub. So I start checking the result of the update-grub command and found out that it tries to update /boot/grub/menu.lst. That means it is using grub-legacy. So, I ran the command to check for the content menu.lst: cat /boot/grub/menu.lst To my surprise, none of the latest kernels are actually configured in there. In other words, the menu.lst is not updated properly. Few more online search brought me to the following article https://ubuntuforums.org/showthread.php?t=873448. Seems like there is a case which will trigger a bug. Hence menu.lst is not updated. So I make a quick copy and re-run update-grub. cp /boot/grub/menu.lst /boot/grub/menu.lst.bak\nrm /boot/grub/menu.lst\nupdate-grub And checking the menu.lst once again results in the latest kernel being updated in there. Restarting the instance and voilà! The latest kernel is loaded and converting it to t3 was successful.",{"id":337,"title":338,"titles":339,"content":340,"level":9},"/2025/11/04-convert-fat32-to-ntfs-with-no-data-loss-in-windows","04 Convert FAT32 To NTFS With No Data Loss In Windows",[],"Convert FAT32 to NTFS with No Data Loss in Windows This is a repost from my old blog. First posted in 11/14/2019. Filesystem is as usual a pretty complicated thing. And I happened to have a new external hard drive that for somewhat reason was formatted as FAT32. Of course, I didn't notice until I put a bunch of data in it. The time has come when I need to store file larger than the 4GB limit of FAT32. So browsing around the internet, I found out that I can convert to NTFS without data loss and third party software from https://www.tenforums.com/tutorials/85893-convert-fat32-ntfs-without-data-loss-windows.html. The steps that I took are: Make sure data are backed up somewhere else.Close all software/application that has the drive opened. I closed the File Explore too.Run command prompt as administrator.Run the following command in command prompt: convert \u003Cdrive> /fs:ntfs. For example: convert D: /fs:ntfsRestart the computer. That's it!",{"id":342,"title":343,"titles":344,"content":345,"level":9},"/2025/11/05-install-previous-version-of-nuget-package-that-is-not-visible","05 Install Previous Version Of Nuget Package That Is Not Visible",[],"Install Previous Version of Nuget Package that is not Visible This is a repost from my old blog. First posted in 11/27/2019. Sometimes a new software version also introduces a new bug and we need to rollback. And this time is on one of the Nuget package that we use. When troubleshooting MySql Nuget package issue, I noticed that I can't revert back to the previous version using the version drop down under Nuget manager window in Visual Studio. So, a bit of searching reminds me that I can use the Package Manager Console to install a package. Maybe I can specify the version and the server still has it. So I uninstall the latest package and ran the following command: Install-Package \u003Cpackage_name> -Version \u003Cversion> -Source nuget.org The source option is optional. In my case, somehow I had it defaulted to some other source so I have to actually specify it in the command. Hit enter and I got the previous version installed. Problem solved!",{"id":347,"title":348,"titles":349,"content":350,"level":9},"/2025/11/06-moving-asp.net-session-state-server-to-aurora-mysql","06 Moving ASPNET Session State Server To Aurora MySQL",[],"Moving ASP.NET Session State Server to Aurora/MySQL This is a repost from my old blog. First posted in 11/17/2019. Our database was in MS SQL Server and we were in the middle of moving to Aurora with MySQL compatibility.And obviously there are differences to be resolved and one of them is we are not sure on how to move the ASP.NET Session state. After several troubleshooting sessions (pun not intended), I finally managed to move the session state server to Aurora. The following two webpages have been very helpful, albeit the first one is outdated: https://www.codeproject.com/Articles/633199/Using-MySQL-Session-State-Provider-for-ASP-NEThttps://dev.mysql.com/doc/connector-net/en/connector-net-programming-asp-provider.html My steps are as follow: Disable the current state server by commenting/removing the sessionState tag under system.web in web.config.Add MySql.Web Nuget package (As of this post, the working one is version 8.0.17).Add new sessionState tag under system.web \u003CsessionState mode=\"Custom\" customProvider=\"MySqlSessionStateStore\"> \n   \u003Cproviders> \n      \u003Cadd name=\"MySqlSessionStateStore\" type=\"MySql.Web.SessionState.MySqlSessionStateStore, MySql.Web, Version=8.0.17.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d\" connectionStringName=\"LocalMySqlServer\" applicationName=\"/\" autogenerateschema=\"True\" />\n\u003C/providers> \n\u003C/sessionState> Note the necessary attributes: mode=\"Custom\"\ncustomProvider=\"\u003Cprovider_name>\"\nautogenerateschema=\"True\" Add connection string. I would prefer to do this programmatically but I can't find a way to do it as of this post. Also, database has to be specified in the connection string.Create schema/database in Aurora/MySql. I found out that MySql.Web doesn't automatically create the schema/database but it will generate necessary tables. That is all to get it to work for me. Another thing to note is the autogenerateschema attribute was not available through autocomplete/intellisense. However, I can find some other attributes as properties of MySqlSessionStateStore class. https://dev.mysql.com/doc/dev/connector-net/8.0/html/T_MySql_Web_SessionState_MySqlSessionStateStore.htm",{"id":352,"title":353,"titles":354,"content":355,"level":9},"/2025/11/07-specify-one-workspace-deleting-team-foundation-phantom-workspace","07 Specify One Workspace Deleting Team Foundation Phantom Workspace",[],"\"Specify one workspace\" - Deleting Team Foundation Phantom Workspace This is a repost from my old blog. First posted in 12/3/2019. One day, my colleague somehow discovered a duplicate team foundation workspace in his computer after rebooting his PC. The duplicates make him unable to find the projects tied to remote repository that he is working on. The duplicated workspace has exactly the same name, owner and computer name as the other one except no existing mapping. Worse, Visual Studio detected only one workspace and deleting it doesn't seem to work. We started with tf.exe command after we figure out that we can manage workspaces using command line. Using the following command, we manage to get a list of all workspaces: tf workspaces /collection:\u003Cdomain>.visualstudio.com\\\u003Corganization> /owner:* But our attempt to delete the particular workspace using the following command failed with the message \"Specify one workspace\": tf workspace /delete \u003Cworkspace_name>;\u003Cdomain>\\\u003Cowner_name> After browsing more, we found this thread: https://developercommunity.visualstudio.com/content/problem/267507/cant-delete-an-abandoned-vsts-workspace.html Basically, we can get a certain ID to differentiate the two workspaces. But to manage workspaces, we need \"Administer workspaces\" permission. It took us a while to figure out how to give ourselves the permission. To do that we did the following steps: Log in to Azure DevOps console.Select the organization to go to the organization level page.On the bottom left of the console, click on the \"Organization settings\".Under Security > Permissions, select \"Project Collection Administrators\" group.Add ourselves (users) as member of that group.Once permission was setup, we can then run the following command to get a list of all workspaces in xml format: tf workspaces /collection:\u003Cdomain>.visualstudio.com\\\u003Corganization> /owner:* /format:xml However, we bumped into another issue. My colleague's tf.exe somehow doesn't support the /format:xml option. And I found out that mine does. It turns out that his tf.exe was located at: C:\\Program Files (x86)\\Microsoft Visual Studio 15.0\\Common7\\IDE\\ while mine was located at: C:\\Program Files (x86)\\Microsoft Visual Studio\\\u003Cyear>\\\u003Cedition>\\Common7\\IDE\\CommonExtensions\\Microsoft\\TeamFoundation\\Team Explorer\\ So, I managed to retrieved the xml format and the owner alias of both workspaces. I deleted both of them using the following command: tf workspace /delete \u003Cworkspace_name>;\u003Cowner_alias> /collection:\u003Cdomain>.visualstudio.com\\\u003Corganization> We also found out that the difference between both of them are two different email addresses, so we deleted one of the accounts from Visual Studio (on the top right) to make sure only one of them remained. Other thing that didn't work for us initially was trying to rename the visible workspace in Visual Studio. We are hoping by renaming one of them, we can differentiate them and delete one of them. But seems like there is a cache that got in our way that the delete command still didn't work even after we managed to rename it. Other reference links: https://docs.microsoft.com/en-us/azure/devops/repos/tfvc/workspace-command?view=azure-devopshttps://docs.microsoft.com/en-us/azure/devops/repos/tfvc/workspaces-command?view=azure-devopshttps://stackoverflow.com/questions/5503858/how-to-get-tf-exe-tfs-command-line-client",{"id":357,"title":358,"titles":359,"content":360,"level":9},"/2025/11/08-useeffect-is-executed-twice","08 UseEffect Is Executed Twice",[],"useEffect is Executed Twice I had a case in which my react app calls the same api endpoint twice. The call is wrapped inside the useEffect hook. At first, I thought the page was rendered twice, but that was not the case. useEffect(() => {\n  callEndpoint();\n}, []); After further investigation, apparently the useEffect is executed twice even though the trigger is an empty array. I found out later on that it is due to React.StrictMode. In my App.tsx: \u003CReact.StrictMode>\n  \u003CApp />\n\u003C/React.StrictMode> Removing it removed the duplicate execution. //\u003CReact.StrictMode>\n  \u003CApp />\n//\u003C/React.StrictMode>",{"id":362,"title":363,"titles":364,"content":365,"level":9},"/2025/11/09-android-room-database-subsequent-insert-failed-due-to-broken-autoincrement","09 Android Room Database Subsequent Insert Failed Due To Broken AutoIncrement",[],"Android Room Database Subsequent Insert Failed Due to Broken AutoIncrement This is a repost from my old blog. First posted in 12/22/2019. Room DB has managed to abstract away complicated SQL statements which is pretty nice. But as with other new things, it takes a while to get used to. It all starts with an entity such as the following: @Entity\ndata class Item(\n    @PrimaryKey(autoGenerate = true) val id: Int = Int.MIN_VALUE,\n    @ColumnInfo val name: String?\n} and my Dao has the following function: @Insert(onConflict = OnConflictStrategy.IGNORE)\nsuspend fun insert(item: Item) The first insert went well, but I noticed my subsequent insert failed. For somewhat reason, it tried to assign the same value as Id. After few trial and error, I managed to fix it by changing the Int.MIN_VALUE to 0. So the entity class becomes: @Entity\ndata class Item(\n    @PrimaryKey(autoGenerate = true) val id: Int = 0,\n    @ColumnInfo val name: String?\n}",{"id":367,"title":368,"titles":369,"content":370,"level":9},"/2025/11/10-asp.net-web-api-404-the-resource-cannot-be-found","10 ASPNET Web API 404 The Resource Cannot Be Found",[],"ASP.NET Web API 404 The Resource Cannot Be Found This is a repost from my old blog. First posted in 1/20/2020. I have an old ASP.NET Web API 2 which I would like to update with OWIN. As usual, it didn't go smoothly. After updating to OWIN, it somehow threw a 404 error. I spent hours trying various things as stated below but none works. Verified the order of route registrationAttempted to use Route attributesApplied runAllManagedModulesForAllRequests=\"true\" on modules tag in web.configMade sure spelling, Nuget packages and imports are correctChecked with a brand new Web API project to make sure code are correct At the end, I remembered that I accidentally hit \"Create Virtual Directory\" when the Project Url field was set to \"http://localhost:xxxxx/api\" and using IIS Express. I suspect the virtual directory was the issue. After few online searches, I found the virtual directory was set in: \u003Csolution folder>/.vs/config/applicationhost.config. Removing the virtual directory solves my 404 issue.",{"id":372,"title":373,"titles":374,"content":375,"level":9},"/2025/11/11-vscode-code.exe-missing","11 Vscode CodeExe Missing",[],"VS Code Code.exe Missing I had a case where the VS Code shortcut suddenly stopped working. It turns out that it can't find the Code.exe code. I didn't install new version or manually upgraded it. Visiting the directory, Code.exe is just gone. But eventually found couple of suggestions on how to fix the problem in the following post: https://stackoverflow.com/questions/76187272/issues-with-vscode-cannot-open-code-exe-file-missing-and-failed-download Couple of suggestions are: Copy the content of _ folder/directory to parent directory C:\\Users\\\u003CUser>\\AppData\\Local\\Programs\\Microsoft VS CodeCreate a shortcut to the Code.exe in _ folder/directory.What I did is update the current shortcut from C:\\Users\\\u003CUser>\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe to C:\\Users\\\u003CUser>\\AppData\\Local\\Programs\\Microsoft VS Code\\_\\Code.exe",{"id":377,"title":378,"titles":379,"content":380,"level":9},"/2025/11/12-enum-constants-and-somewhere-in-between","12 Enum Constants And Somewhere In Between",[],"Enum, Constants, and Somewhere in Between I was showing a younger developer in my team on some techniques to implement strongly typed constants without using enum. For example, we have a method/function: public async void DoSomething(string activity) And we want to limit the value of activity parameter to let say Run and Bike. One way is to use enum: public enum Activity\n{\n    Run,\n    Bike\n}\n\npublic async void DoSomething(Activity activity)\n\npublic async void DoToday()\n{\n    DoSomething(Activity.Run);\n} Sometimes, we want to get the string value and enum can be tricky, so there's a tendency to loosen the parameter type, let say using static property or string constants. public class Activity\n{\n    public static string Run { get; set; } = \"Run\";\n    public static string Bike { get; set; } = \"Bike\";\n}\n\npublic async void DoSomething(string activity)\n{\n  Debug.WriteLine($\"Activity: {activity}\")\n}\n\npublic async void DoToday()\n{\n    DoSomething(Activity.Run);\n} Which means the following is now valid but not intended: DoSomething(\"Sleep\"); So, how do we find a sweet spot between enum and string? One option is to use class but lock down the constructor so it can't be initialized with unintended value. This way, it is still flexible enough to extract the string value. public class Activity\n{\n    private readonly string _value;\n    private Activity(string value) { _value = value; }\n    public static Activity Run { get; set; } = new Activity(\"Run\");\n    public static Activity Bike { get; set; } = new Activity(\"Bike\");\n    public string Value { get { return _value; } }\n}\n\npublic async void DoSomething(Activity activity)\n{\n    Debug.WriteLine($\"Activity: {activity.Value}\");\n}\n\npublic async void DoToday()\n{\n    DoSomething(Activity.Run);\n} The compiler will flag the following as invalid, thus we can control what are valid values for the activity parameter. DoSomething(new Activity(\"Sleep\"));",{"id":382,"title":383,"titles":384,"content":385,"level":9},"/2025/11/13-visual-studio-2026-and-git-case-sensitivity","13 Visual Studio 2026 And Git Case Sensitivity",[],"Visual Studio 2026 and Git Case Sensitivity So, I'm trying to use Visual Studio Professional 2026 Insiders to work on my project. As I did a git pull, it complained about git case sensitivity. The error is You're on a case-sensitive filesystem, and the remote you are trying to fetch from has references that only differ in casing.. I never had any issue with this repo, so I thought I'll try using Visual Studio Professional 2022 to do git pull. For somewhat reason, VS 2022 git pull didn't complain about case sensitivity. Same case with git through command line. I'm still investigating the difference between the two. But the workaround is using VS 2022 or CLI.",{"id":387,"title":388,"titles":389,"content":390,"level":9},"/2025/11/14-generate-api-call-with-orval-and-axios-from-openapi-schema","14 Generate Api Call With Orval And Axios From Openapi Schema",[],"Generate API Call with Orval and Axios from OpenAPI Schema This is a repost from my old blog. First posted in 1/20/2020. I have a project with .NET Core 9.0 backend and React frontend. With the built-in OpenAPI support via  Microsoft.AspNetCore.OpenApi, it makes it so much easier to generate OpenAPI documents. For more information, visit https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/overview?view=aspnetcore-9.0. To automate the process, I want to generate the document after built. And that's pretty easy as well by following instructions in (Generate OpenAPI documents at build-time)https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/aspnetcore-openapi?view=aspnetcore-9.0&tabs=visual-studio%2Cvisual-studio-code#generate-openapi-documents-at-build-time article. In my csproj file, I put the following entries, so the Open API documents can be exported to a common location outside of the backend project directory with name api.json. \u003CPropertyGroup>\n  \u003COpenApiDocumentsDirectory>../../../openapi\u003C/OpenApiDocumentsDirectory>\n  \u003COpenApiGenerateDocumentsOptions>--file-name api\u003C/OpenApiGenerateDocumentsOptions>\n  ...\n\u003C/PropertyGroup> On the frontend, I would like to automatically ingest that document and automatically generate code to make the api call. That's where Orval (https://orval.dev/) comes in. Since I want to use custom Axios instance, I use the following guide: https://orval.dev/guides/custom-axios. My orval.config.js looks like the following: import { defineConfig } from 'orval';\n\nexport default defineConfig({\n  api: { //custom name, it can be any friendly name.\n    input: '../openapi/api.json',\n    output: {\n      mode: 'single',\n      target: 'src/api/api.ts',\n      schemas: 'src/api/model',\n      mock: false,\n      override: {\n        mutator: {\n          path: './src/services/axios-service.ts',\n          name: 'request'\n        }\n      }\n    }\n  }\n}); The input is the path to the Open API document. Within output, mode: Single tells Orval to generate a single file for all calls (usually one function per endpoint): https://orval.dev/reference/configuration/output#value-single. And target is the output location and name of the generated code. While schemas will hold the generated models/DTOs that represents request and response data. I just turn mock to false since I don't use Faker at this time https://orval.dev/reference/configuration/output#mock. The override is where the interesting thing happen. In my case, it basically says, use the request function in ./src/services/axios-service.ts to make the call. My axios-service.ts contains the following: export const request = \u003CT>(\n    config: AxiosRequestConfig,\n    params?: Params\n  ): Promise\u003CT> => {\n    axiosInstance.defaults.baseURL = import.meta.env.VITE_BASE_URL;\n\n    const source = axios.CancelToken.source();\n    const axiosConfig: AxiosRequestConfig = {\n      ...config,\n      cancelToken: source.token,\n      headers: {\n        Authorization: `Bearer ${params?.accessToken}`\n      }\n    };\n    \n    const promise = axiosInstance(axiosConfig).then(({ data }) => data);\n\n    // @ts-ignore\n    promise.cancel = () => {\n      source.cancel('Query was cancelled');\n    };\n\n    return promise;\n  }; This way, I use the BASE_URL specified in .env file so I can differentiate between local and remote environment. Also, I allow injection of access token, so my call can be authorized by the backend. Orval will then generate something similar to the following calls in api.ts: options?: SecondParameter\u003Ctypeof request\u003CUserResponse>>,) => {\n      return request\u003CUserResponse>(\n      {url: `/users`, method: 'POST'\n    },\n      options);\n    }\n  \nexport const getCustomers = (\n    \n options?: SecondParameter\u003Ctypeof request\u003CCustomersResponse[]>>,) => {\n      return request\u003CCustomersResponse[]>(\n      {url: `/customers`, method: 'GET'\n    },\n      options);\n    }\n  \nexport const postCustomers = (\n    customersRequest: CustomersRequest,\n options?: SecondParameter\u003Ctypeof request\u003Cvoid>>,) => {\n      return request\u003Cvoid>(\n      {url: `/customers`, method: 'POST',\n      headers: {'Content-Type': 'application/json', },\n      data: customersRequest\n    },\n      options);\n    } In package.json, I added command to run orval during npm run dev and npm run build commands: \"scripts\": {\n\"dev\": \"orval && ...\",\n\"build\": \"orval && ...\",\n...\n}::\n\nThat way, when I run the frontend locally, it will generate the code using the latest document. It will also generate when run within CI/CD pipeline. It saves a lot of time by automatically modify the frontend code when the backend api changes.",{"id":392,"title":393,"titles":394,"content":395,"level":9},"/2025/11/15-openapi-and-dotnet-webapi-minimal-api-to-download-file","15 Openapi And Dotnet Webapi Minimal Api To Download File",[],"OpenAPI and .NET Web API Minimal Api to Download File I have an endpoint to download file in my .NET Web API application. When I tried to generate client-side code to download file based on the OpenAPI document, I'm suprised to find that it returns void instead of blob or byte array. So, I checked the OpenAPI document and found out that the response is indeed without type, hence void like the following: \"responses\": {\n  \"200\": {\n    \"description\": \"OK\"\n  }\n} I'm using .NET 9 with built-in OpenAPI support and one of the suggestions is to use TypedResults.File() similar to: TypedResults.File(fileStream, contentType: \"application/octet-stream\", fileDownloadName: \"file.txt\"); However, it didn't pick up the type as well. I remember in .NET 8, I had to use IOperationFilter to generate the expected OpenAPI document response which, at least, should look like: \"responses\": {\n  \"200\": {\n    \"description\": \"OK\",\n    \"content\": {\n      \"application/octet-stream\": {\n        \"schema\": {\n          \"type\": \"string\",\n          \"format\": \"binary\"\n        }\n      }\n    }\n  }\n} Perhaps there's .NET 9 equivalent to IOperationFilter and I found AddOperationTransformer from https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/customize-openapi?view=aspnetcore-9.0#use-operation-transformers. However, it needs to be applied globally and requires more code to filter it if we want it only for a certain endpoint. Fortunately, per endpoint application is addressed in .NET 10: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/customize-openapi?view=aspnetcore-10.0#use-operation-transformers and in .NET 10, I can then apply it for a specific endpoint: app.MapGet(...)\n    .AddOpenApiOperationTransformer((operation, context, cancellationToken) =>\n    {\n        if (operation.Responses?.TryGetValue(StatusCodes.Status200OK.ToString(), out var okResponse) ?? false)\n        {\n            okResponse.Content?.TryAdd(\"application/octet-stream\", \n                new OpenApiMediaType\n                {\n                    Schema = new OpenApiSchema\n                    {\n                        Type = JsonSchemaType.String,\n                        Format = \"binary\"\n                    }\n                });\n        }\n        return Task.CompletedTask;\n    }); Alternatively, we can clear existing generated response: app.MapGet(...)\n    .AddOpenApiOperationTransformer((operation, context, cancellationToken) =>\n    {\n        var binaryOkResponse = new OpenApiResponse\n        {\n            Content = new Dictionary\u003Cstring, OpenApiMediaType>() {\n                {\n                    \"application/octet-stream\",\n                    new OpenApiMediaType\n                    {\n                        Schema = new OpenApiSchema\n                        {\n                            Type = JsonSchemaType.String,\n                            Format = \"binary\"\n                        }\n                    }\n                }\n            }\n        };\n\n        operation.Responses?.Clear();\n        operation.Responses?.Add(StatusCodes.Status200OK.ToString(), binaryOkResponse);\n\n        return Task.CompletedTask;\n    }); Although it produces the expected response in the OpenAPI document, it feels like forced/hardcoded instead of generating it from the actual response type. So another option is to use Produces(). This should work with .NET 9 as well: app.MapGet(...)\n    .Produces\u003Cbyte[]>(StatusCodes.Status200OK, contentType: \"application/octet-stream\"); And the above will produces the following response: \"responses\": {\n  \"200\": {\n    \"description\": \"OK\",\n    \"content\": {\n      \"application/octet-stream\": {\n        \"schema\": {\n          \"type\": \"string\",\n          \"format\": \"byte\"\n        }\n      }\n    }\n  }\n} Notice that the format is byte instead of binary. Basically, byte is used when we want to return json along with the file content. To return only the file itself without json, use binary. To read more on binary vs byte, please check https://swagger.io/docs/specification/v3_0/describing-responses/#response-that-returns-a-file:~:text=The%20user%20name.-,Response%20That%20Returns%20a%20File,-An%20API%20operation. Unfortunately, I can't find a way to generate response with format set to binary using Produces(). .NET 9 type and format: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/include-metadata?view=aspnetcore-9.0&tabs=minimal-apis#type-and-format..NET 10 type and format: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/include-metadata?view=aspnetcore-10.0&tabs=minimal-apis#type-and-format. Since I still return TypedResults.File(), I tried to return the same type with: app.MapGet(...)\n    .Produces\u003CFileStreamHttpResult>(StatusCodes.Status200OK, contentType: \"application/octet-stream\"); Problem with the above is my client-side code generator creates a lot of unnecessary code, so I tried the following: app.MapGet(...)\n    .Produces\u003Cbyte[]>(StatusCodes.Status200OK, contentType: \"application/octet-stream\"); It produces a better client-side code but somehow, the return value on the client-side code is string instead of blob. Apparently, I need the response format to be binary instead of byte. Since there's no way to do that with Produces, I revert to using AddOpenApiOperationTransformer which works for my case where generated code returns blob. Although the server returns FileStreamHttpResult which is a complex object, Scalar correctly return binary in the body and thus the client correctly extracts blob from the call. One final note is the generated OpenAPI document response can be different from the actual working of the endpoint and in this case, it's our responsibility to keep them in sync.",{"id":397,"title":398,"titles":399,"content":400,"level":9},"/2025/11/16-dotnet-10-revert-openapi-3.1-to-openapi-3.0","16 Dotnet 10 Revert Openapi 31 To Openapi 30",[],".NET 10, Revert OpenAPI 3.1 to OpenAPI 3.0 I recently upgraded my web api to .NET 10 and .NET 10 supports OpenAPI version 3.1 schema. When I generate the code based on the new document, I noticed a lot of code change, so I wanted to revert back to OpenAPI version 3.0. The following article helps to get me started: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/aspnetcore-openapi?view=aspnetcore-10.0&tabs=visual-studio%2Cvisual-studio-code In my Program.cs, I modified from: builder.Services.AddOpenApi(); to: builder.Services.AddOpenApi(options =>\n{\n    options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_0;\n}); And for generated document, I need to update from: \u003COpenApiGenerateDocumentsOptions>--file-name api\u003C/OpenApiGenerateDocumentsOptions> to: \u003COpenApiGenerateDocumentsOptions>--file-name api --openapi-version OpenApi3_0\u003C/OpenApiGenerateDocumentsOptions>",{"id":402,"title":403,"titles":404,"content":405,"level":9},"/2025/11/17-managing-package-version-in-dotnet","17 Managing Package Version In Dotnet",[],"Managing Package Version in .NET One of the issues I helped a client troubleshoot was an error related to package versioning. The project has the following dependency: Services project depends on package A (v2)\nAPI project depends on package A (v1)\nServices project depends on API project So, package A on Services project has been upgraded to v2, but it was still in the previous version in API project. Code is in Services project calls a method of package A but implemented in API project. Let say, in package A: public class SomePackageClass()\n{\n  public void DoWorkInPackage()\n  {\n    ...\n  }\n}\nThen in API:public class SomeApiClass()\n{\n  public void DoWorkInApi()\n  {\n    instanceOfSomePackageClass.DoWorkInPackage();\n  }\n}\n\npublic interface ISomeApiClass\n{\n  public void DoWorkInApi()\n}\nAnd in Services:public class SomeClassInServices()\n{\n  public void DoWorkInServices()\n  {\n    instanceOfSomeApiClass.DoWorkInApi();\n  }\n}\nAs far as Services project is concern, instanceOfSomePackageClass.DoWorkInPackage() is based on v2 of package A, but since the actual call is in API, only v1 package is accessible and thus, it throws an error. As we tried to fix the package version conflict, I learned a few applicable dependency resolution rules from https://learn.microsoft.com/en-us/nuget/concepts/dependency-resolutionThe first one is (Lowest applicable version)https://learn.microsoft.com/en-us/nuget/concepts/dependency-resolution#lowest-applicable-version. In our case, since API requires v1 of package A, even if feed has v2, it will still use v1 of package A. In this case, even if API project specifies >= v1, it will not use v2.Another one is Direct dependency wins. With this rule, Services project has v2 and it initiates the call, so it tried to use v2 of package A. But since the actual method call is implemented in API and API depends on v1, API can't access v2 of package A.So, our solution is removing dependency on package A in Services and upgrade the package A in API to v2. That way, Services which depends on API will transitively depends on package A. This will provide single place to update and reduce future package version conflict.Services project depends on API project\nAPI project depends on package A (v2)\nServices transitively depends on package A in API project (v2)",{"id":407,"title":408,"titles":409,"content":410,"level":9},"/2025/11/18-jsonserializeroptions-numberhandling-allowreadingfromstring-and-strict","18 JsonSerializerOptions NumberHandling AllowReadingFromString And Strict",[],"JsonSerializerOptions NumberHandling AllowReadingFromString and Strict After all the attempts to fix OpenAPI document, I noticed that Orval intepreted one of the property as unknown type which is supposed to be integer, thus number type. I checked the OpenAPI document and it has the following type and format: type: \"^-?(?:0|[1-9]\\d*)$\",\nformat: \"int32\" For Orval to intepret it properly as number, I need it to be: type: \"integer\",\nformat: \"int32\" So, I check the backend and found out that it is due to JsonSerializeOptions.NumberHandling is set to AllowReadingFromString by default. https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/configure-options#web-defaults-for-jsonserializeroptions I want to set NumberHandling to Strict globally. Since I use minimal api, this article helps https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/responses?view=aspnetcore-10.0#configure-json-serialization-options-globally. I just need to add the following on my backend code: builder.Services.ConfigureHttpJsonOptions(options =>\n{\n    options.SerializerOptions.TypeInfoResolverChain.Insert(0, HttpApiJsonSerializerContext.Default);\n});",{"id":412,"title":413,"titles":414,"content":415,"level":9},"/2025/11/19-aws-cloudformation-starting-ec2-instance-requires-ec2-runinstances-permission","19 AWS CloudFormation Starting EC2 Instance Requires Ec2 RunInstances Permission",[],"AWS CloudFormation Starting EC2 Instance Requires ec2:RunInstances Permission This is a repost from my old blog. First posted in 1/20/2020. Another weird case with AWS CloudFormation. I attempted to start an EC2 instance and for somewhat reason it failed and said it doesn't have ec2:RunInstances permission, but it does. After few checks, I found out that the cause is the IamInstanceProfile. If it is set, the error happens. With clue from some online forum, I tried adding iam:PassRole permission for CloudFormation instead of the required ec2:RunInstances and it works!",{"id":417,"title":418,"titles":419,"content":420,"level":9},"/2025/11/20-a2-hosting-let's-encrypt-can't-install-certificate-on-asp.net-core-application","20 A2 Hosting Let's Encrypt Can't Install Certificate On ASPNET Core Application",[],"A2 Hosting Let's Encrypt Can't Install Certificate on ASP.NET Core Application This is a repost from my old blog. First posted in 3/11/2020. I have an ASP.NET Core app hosted by A2 Hosting. A2 Hosting provides free SSL certificate through Let's Encrypt, so I decided to install it for my application. Since the portal is by Plesk, I follow the guide in https://support.plesk.com/hc/en-us/articles/115000165013 However, it didn't work as expected. My application still has a web.config file. After trying different ways, I commented out aspNetCore module in the web.config and then the certificate was installed successfully. By commenting the module, ASP.NET Core processing by IIS is disabled, so the validation request by Let's Encrypt is treated like a regular request towards a static file.",{"id":422,"title":423,"titles":424,"content":425,"level":9},"/2025/11/21-ef6-strange-pending-changes-error","21 EF6 Strange Pending Changes Error",[],"EF6 Strange Pending Changes Error This is a repost from my old blog. First posted in 3/16/2020. One of the complicated errors on EF6 that I often troubleshoot is the following: Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration. Usually, I will just run Add-Migration on Package Manager Console to see what changes in the schema. But this time it is strange, the Add-Migration includes the code to create existing tables. I searched for the migration files between the time those tables were created and the latest migration, I can't find anywhere that those tables were dropped. When trying to find some clue online, I bumped into the following amazing article: https://tech.trailmax.info/2014/03/inside_of_ef_migrations/. So, I went into the database and decompress a few blob/binary files from Model column. The files contain schema snapshots in the form of XML. And in my case, somewhere along the migrations, the tables were suddenly missing from the snapshots. However, the actual tables were still in the database. I also found out that my coworker at one time commented those tables out. But it is weird because if they were commented out and Add-Migration was triggered, the generated file would have DropTable code. When I asked my coworker, the migration file was not changed manually, so the DropTable code was not generated in the first place. But the latest snapshot doesn't have those tables in it. So, no DropTable, no manual migration file modification and no tables in the snapshot. It took me a few hours to understand how to recreate the issue. With everything as is, I run Add-Migration once. EF then generates a new migration file and shows the following message in the console: The Designer Code for this migration file includes a snapshot of your current Code First model. This snapshot is used to calculate the changes to your model when you scaffold the next migration. If you make additional changes to your model that you want to include in this migration, then you can re-scaffold it by running 'Add-Migration TestMigration' again. Then I commented out the table that I want to go missing and rerun the Add-Migration. Usually, when you need to rescaffold a migration, you use the -Force option, in this case I did not. I simply re-ran the same Add-Migration command. This time EF shows the following message in the console: Only the Designer Code for migration 'TestMigration' was re-scaffolded. To re-scaffold the entire migration, use the -Force parameter. Nothing changed on the generated file, but notice that the Designer Code which has the model snapshot has been changed. That means the table that I commented has been removed from the snapshot, but no DropTable code. And when I run Update-Database, EF inserted the model snapshot along with the latest migration file name into the database. Since no table was dropped, when I uncommented the table and ran the application, EF throws the pending changes error. Eventually to summarize the steps: Run Add-MigrationComment a tableRun the same Add-Migration (without -Force option)Update-DatabaseUncomment the tableTo fix it, I simply reverted the migrations and re-did them properly. Also, not sure if the following code plays a part in the issue, but we have them in our code: Database.SetInitializer\u003CDbContext>(null);",{"id":427,"title":428,"titles":429,"content":430,"level":9},"/2025/11/22-ef6-mysql-remove-default-dbo-schema","22 EF6 MySQL Remove Default Dbo Schema",[],"EF6 MySQL Remove Default dbo Schema This is a repost from my old blog. First posted in 3/18/2020. As we all know, Entity Framework has default schema of \"dbo\", but MySQL will ignore it when performing migrations. But it gets troublesome when we try to rollback, because the dbo doesn't get ignored in that case. Due to the fact that dbo doesn't get ignored, rolling back the migrations often caused error in my case. And removing the schema manually every time a new migration file is generated is tiring. That prompted me to find a way to remove the schema when new migration file is generated. My first attempt is by looking inside the Configuration file. In my case, I have a custom HistoryContext because some MigrationHistory keys are just too long. And the custom HistoryContext is set in the Configuration file constructor: SetHistoryContextFactory(MySqlProviderInvariantName.ProviderName, Function(connection, schema) New MySqlHistoryContext(connection, schema)) After some online search, it seems like for some databases, setting the schema to something else alters the generated file, so I give it a try. My code thus becomes: SetHistoryContextFactory(MySqlProviderInvariantName.ProviderName, Function(connection, schema) New MySqlHistoryContext(connection, \"\")) However, it doesn't work at all. Then I think there maybe a way to set it on the DbContext level and I found the following code which I apply to the OnModelCreating method: modelBuilder.HasDefaultSchema(String.Empty) And this time it works! No more dbo. But on the newly generated migration file, it has MoveTable() code for existing tables. In my case, I just comment them out since schema was ignored anyway. Finally, out of curiosity, I just tried changing the schema to null instead of empty string. However, that one doesn't work in my case as it tries to set the schema back to dbo for my database. So the final solution is to set the default schema to empty string.",{"id":432,"title":433,"titles":434,"content":435,"level":9},"/2025/11/23-ef6-mysql-migrations-error-specified-key-was-too-long-max-key-length-is-767-bytes","23 EF6 MySql Migrations Error Specified Key Was Too Long Max Key Length Is 767 Bytes",[],"EF6 MySql Migrations Error \"Specified key was too long; max key length is 767 bytes\" This is a repost from my old blog. First posted in 3/18/2020. We were in the middle of moving to MySQL and would like to use EF Migrations against MySQL. But the error held us back a little. When trying to apply EF Migrations, it failed with \"Specified key was too long; max key length is 767 bytes\" error. The following article helped solve my problem. https://docs.microsoft.com/en-us/aspnet/identity/overview/getting-started/aspnet-identity-using-mysql-storage-with-an-entityframework-mysql-provider#adding-custom-migrationhistory-context Under \"Adding custom MigrationHistory context\" section, it talks about creating a custom HistoryContext class. In my case: Public Class MySqlHistoryContext\n        Inherits HistoryContext\n\n    Sub New(existingConnection As DbConnection, defaultSchema As String)\n        MyBase.New(existingConnection, defaultSchema)\n    End Sub\n\n    Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)\n        MyBase.OnModelCreating(modelBuilder)\n        modelBuilder.Entity(Of HistoryRow)().Property(Function(h) h.MigrationId).HasMaxLength(100).IsRequired()\n        modelBuilder.Entity(Of HistoryRow)().Property(Function(h) h.ContextKey).HasMaxLength(200).IsRequired()\n    End Sub\nEnd Class Then use it on the generated Configuration file. My problem is fixed afterwards. Friend NotInheritable Class Configuration\n        Inherits DbMigrationsConfiguration(Of MyDbContext)\n\n    Public Sub New()\n        AutomaticMigrationsEnabled = False\n\n        SetHistoryContextFactory(MySqlProviderInvariantName.ProviderName, Function(connection, schema) New MySqlHistoryContext(connection, schema))\n    End Sub\n\n    Protected Overrides Sub Seed(context As MyDbContext)\n    End Sub\n\nEnd Class",{"id":437,"title":438,"titles":439,"content":440,"level":9},"/2025/11/24-identityserver4-custom-claims-and-services","24 IdentityServer4 Custom Claims And Services",[],"IdentityServer4 Custom Claims and Services This is a repost from my old blog. First posted in 3/28/2020. It is all started from my intention to add \"iat\" claim to access token. IssuedAt (iat) claim is optional so it takes a bit of searching to figure out how to do that. Add that to my unfamiliarity with IdentityServer4, it becomes quite a task. At this point, I am using IdentityServer4 version 3.0.2.0. First, I found out that you might be able to add custom claim by extending IProfileService. It works well for some random claim, but not \"iat\". Strange, it must be filtered somewhere then. Then browsing the source code in github, I found out that it was indeed filtered by FilterProtocolClaims method in DefaultClaimService: https://github.com/IdentityServer/IdentityServer4/blob/master/src/IdentityServer4/src/Services/Default/DefaultClaimsService.cs Ok, so I think I can extend DefaultClaimsService. I tried by adding a custom class in the StartUp using the following code: services.AddTransient\u003CIClaimsService,CustomClaimsService>(); Sadly, it didn't work. I then learn that you can add the service under builder.Services, so I tried the following: services.AddIdentityServer()\n      .... (removed for brevity)\n      .Services.AddTransient\u003CIClaimsService, CustomClaimsService>(); That works! My \"iat\" claim is included in the access token. In my case, I choose to overwrite GetStandardSubjectClaims method because that is where \"auth_time\" claim is set and \"iat\" claim has the same value as \"auth_time\" claim using code like the following: var authTime = claims.FirstOrDefault(c => c.Type == JwtClaimTypes.AuthenticationTime);\nif (authTime != null)\n{\n   outputClaims.Add(new Claim(JwtClaimTypes.IssuedAt, authTime.Value, ClaimValueTypes.Integer));\n}",{"id":442,"title":443,"titles":444,"content":445,"level":9},"/2025/11/25-samsung-smart-switch-stuck-when-updating-firmware-on-s20-plus","25 Samsung Smart Switch Stuck When Updating Firmware On S20 Plus",[],"Samsung Smart Switch Stuck When Updating Firmware on S20+ This is a repost from my old blog. First posted in 4/6/2020. My old phone is dying so I got an S20+. The data transfer from old phone is easy, thanks to Samsung Smart Switch. However, even though the phone notified there was an OTA update, it can't download the update. While searching online for solution, I found out that Smart Switch PC can apply the update, so I give that a try. Smart Switch recommends using Samsung original cable, so I use the USB-C to USB-C cable that comes with the S20+. It works well to a point, phone was detected, firmware downloaded, but in my case, it is stuck at 86% for hours. Some people in the forum said, it can take up to 30 minutes. So, this is not normal. During the update, there is an option to cancel by pressing Volume down and Power key. However, that soft-brick the phone and I have to do Emergency Recovery. If you are also at this point, do jot down the \"recovery code\". I try the Emergency Recovery only to find out, it is also stuck at 86%. I tried two more times with the same result. Not good. One option in the online forum is using Odin to flash. So, just in case I need it, I downloaded the latest version suggested in SamMobile. It is the 3.14.4. However, some people say that is not a clean version. And some people reported flashing S20s successfully with 3.13.1 patched version. I also downloaded the firmware which happened to be 5GB just in case I really need Odin. Needless to say, I'm not very fond of using non-recommended tools as my phone was just a day old. At this point, Smart Switch can still detect the phone, so there is hope. I happened to read that one person in the online forum says he doesn't trust USB-C to USB-C cable due to its driver. That made me think of another option, how about if I switch the cable to USB-C to USB-A? Since USB-A has been around longer, the driver is more mature/time-tested. So, I ran Smart Switch again, not hoping much, but to my surprise, it passed the 86% mark and ended up flashing the firmware successfully. My phone is back! Praise God! Hallelujah! So, try using USB-C to USB-A cable.",{"id":447,"title":448,"titles":449,"content":450,"level":9},"/2025/11/26-if-debug-preprocessor-directive-on-asp.net-web-forms-markup","26 If DEBUG Preprocessor Directive On ASPNET Web Forms Markup",[],"#if DEBUG Preprocessor Directive on ASP.NET Web Forms Markup This is a repost from my old blog. First posted in 4/21/2020. I have a JavaScript that I want to include only on Release mode of my ASP.NET Web Forms app. The script will reside in the markup. To do that I will need to use #if DEBUG. But to have it working in the markup takes me a while to figure out. First, I tried wrapping my script with the following code on the markup under  tag and it doesn't work. \u003C% #if !DEBUG %>\n    \u003Cscript>\n         alert('Hello World!');\n    \u003C/script>\n\u003C% #endif %> Next, after reading some articles online, I tried to wrap my code using the following code and it still doesn't work. \u003C% if (!Debugger.IsAttached) { %>\n    \u003Cscript>\n        alert('Hello World!');\n    \u003C/script>\n\u003C% } %> Finally, the one that works for me is when I wrap the whole thing with \u003Casp:PlaceHolder> tag: \u003Casp:PlaceHolder runat=\"server\"> \n    \u003C% #if !DEBUG %>\n        \u003Cscript>\n            alert('Hello World!');\n        \u003C/script>\n    \u003C% #endif %>\n\u003C/asp:PlaceHolder>",{"id":452,"title":453,"titles":454,"content":455,"level":9},"/2025/11/27-forms-authentication-auto-redirects-to-account-login","27 Forms Authentication Auto Redirects To Account Login",[],"Forms Authentication Auto Redirects to /Account/Login This is a repost from my old blog. First posted in 5/7/2020. We are required to add a different authentication method on our ASP.NET Web Forms app. It is currently configured to use OWIN, so I thought I can just disable the current authentication method and revert to the old web.config forms authentication for testing purposes. Turns out it is harder than I thought. After disabling the current authentication method, I add the common Forms Authentication web.config entry: \u003Cauthorization>\n   \u003Cdeny users =\"?\" />\n   \u003Callow users = \"*\" />\n\u003C/authorization>\n\u003Cauthentication mode=\"Forms\">\n   \u003Cforms name=\".ASPXFORMSAUTH\" loginUrl=\"~/login.aspx\" protection=\"All\" path=\"/\" timeout=\"30\" />\n\u003C/authentication> Then I try to access the protected page and to my surprise I got redirected to /Account/Login?ReturnUrl=. That is weird and I verified other settings and none seems to be out of place. Searching online, I happened to find the following thread: https://forums.asp.net/t/1847413.aspx?How+is+authentication+mapped+to+Account+Login Following the instruction, I added the following under \u003CappSettings> tag in web.config and it redirects properly. \u003Cadd key=\"loginUrl\" value=\"~/login.aspx\" /> Update\n5/8/2020\nAccording to the following article, there is a way to disable the redirect instead of changing the destination. https://docs.microsoft.com/en-us/aspnet/whitepapers/mvc3-release-notes#0.1__Toc274034230 To disable the auto redirect, add the following under  tag in web.config: \u003Cadd key=\"enableSimpleMembership\" value=\"false\" />\n\u003Cadd key=\"autoFormsAuthentication\" value=\"false\" />",{"id":457,"title":458,"titles":459,"content":460,"level":9},"/2025/11/28-temporary-aws-credentials-with-third-party-identity-provider-via-sts-and-android-sdk","28 Temporary AWS Credentials With Third Party Identity Provider Via STS And Android SDK",[],"Temporary AWS Credentials with Third Party Identity Provider via STS and Android SDK This is a repost from my old blog. First posted in 5/25/2020. Role has been the preferred way to gain access to AWS for mobile apps instead of hard coded credentials. A mobile app can assume a specific role via AWS STS (Security Token Service) in which a temporary AWS credentials will be returned. However, the implementation is not as easy as I thought it would be. During my implementation time, I found that the documentation was not as clear and ended up spending a lot of time doing trial and error and re-reading articles. One of my requirements is I don't want to rely on AWS Cognito for identity at all since I already use a third party identity provider. It is, however, possible to use AWS Cognito as a bridge between the mobile app and the third party identity provider. My next requirement is I don't want to use AWS Amplify. AWS pushes Amplify usage very hard and it is indeed very easy to use, but I'm not too fond of the level of abstraction for my application. Another requirement is if possible, I want to use SDK instead of manually making a REST call. With those requirements in mind, I went to look for the documentation. My first meaningful documentation is the following article about AssumeRoleWithWebIdentity: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_assumerolewithwebidentity In that section, AWS recommends AWS Cognito and nowhere obvious can I find what to do if I don't want to use it. After missing it a few times, the link that says AmazonSTSCredentialsProvider at the end of the section gives a clue and it leads to the following blog post: https://aws.amazon.com/blogs/mobile/using-the-amazoncredentialsprovider-protocol-in-the-aws-sdk-for-ios/ Although the blog says for iOS, it is also applicable to Android. After rummaging through the API reference, AmazonSTSCredentialsProvider has many implementations, in which the one applicable to my case is the WebIdentityFederationSessionCredentialsProvider since it takes a token from third party identity provider and roleArn. https://aws-amplify.github.io/aws-sdk-android/docs/reference/com/amazonaws/auth/WebIdentityFederationSessionCredentialsProvider.html At this point, it is still not clear on what I need to do to be able to use the class above. After few more online searches, I found the articles below to be helpful: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc.html Eventually, the articles above lead to the article that helps me setup the whole thing: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc_manual.html To make it work, few things I need to do: Create a role and note the ARNCreate an IAM Identity Provider entity. The link can be found in the IAM console page.Set the role's Trust relationship with the Identity Provider as the trusted entityOn the mobile app, I use the following code:At first, I made a mistake by providing an access token. It threw an error that it can't find iat property. When I switched to use id token, it managed to retrieve the temporary credentials which I then used to successfully to make an API call. For example, DynamoDB API call. In conclusion, my code in Kotlin that works is: val wif = WebIdentityFederationSessionCredentialsProvider(\n                idToken,\n                null,\n                roleArn)\nval dynamoDBClient = AmazonDynamoDBClient(wif)\ndynamoDBClient.setRegion(Region.getRegion(region))\nval scanRequest = ScanRequest(tableName)",{"id":462,"title":463,"titles":464,"content":465,"level":9},"/2025/11/29-azure-devops-build-failed-for-project-without-solution-file","29 Azure DevOps Build Failed For Project Without Solution File",[],"Azure DevOps Build Failed for Project without Solution File This is a repost from my old blog. First posted in 1/20/2020. Our company has been using Azure DevOps as a source control server. Only lately, I have been expanding our usage to take advantage of its CI/CD offerings. It went smoothly until I bumped into a project that has no solution file. The project without solution file failed the Visual Studio Build task even when it has the same settings as other projects with solution file. I started by verifying settings from the Solution field. It does says that it can use MSBuild project. Since I was using VB.NET, I point it to .vbproj file. Next is the Platform field, which according to the info bubble, I can specify \"any cpu\". Last is the Configuration field. Since I want a Release build, I can specify \"release\" according to the info bubble. The same values, with the exception of the Solution field, work well if I point the task to a solution file but break when I point it to a project file. Part of the error message is: Please check to make sure that you have specified a valid combination of Configuration and Platform for this project.  Configuration='release'  Platform='any cpu'.  You may be seeing this message because you are trying to build a project without a solution file, and have specified a non-default Configuration or Platform that doesn't exist for this project. The error message indeed stated that the Configuration and Platform values are invalid. But it builds just fine locally without a solution file. Granted, Visual Studio will create a temporary solution file when opening a project file. Since it built fine locally, I decided to check inside the project file to find the values used. The project file does use \"Release\" instead of \"release\" and \"AnyCPU\" instead of \"any cpu\". So, I gave it a try and the build was successful. Opening the solution file reveals the use of \"Release\" and \"Any CPU\", so the values might be case insensitive, but I didn't give it a try. And my solution is: If pointing to solution file, use \"release\" as Configuration and \"any cpu\" as PlatformIf pointing to project file, use \"Release\" as Configuration and \"AnyCPU\" as Platform",{"id":467,"title":468,"titles":469,"content":470,"level":9},"/2025/11/30-error-installing-aws-codedeploy-agent-in-windows-server-2016","30 Error Installing AWS CodeDeploy Agent In Windows Server 2016",[],"Error Installing AWS CodeDeploy Agent in Windows Server 2016 This is a repost from my old blog. First posted in 6/8/2020. It has been a while since I added an EC2 instance to our CI/CD pipeline. And this time, I need to allow a Windows Server 2016 to receive artifacts from AWS CodeDeploy by installing the agent. And installing the CodeDeploy agent is not straight forward. I followed the instructions to install using Windows PowerShell: https://docs.aws.amazon.com/codedeploy/latest/userguide/codedeploy-agent-operations-install-windows.html#codedeploy-agent-operations-install-windows-powershell It went smoothly until it tried to start the windows service which failed with the following error message: Service 'CodeDeploy Host Agent Service' (codedeployagent) failed to start. \nVerify that you have sufficient privileges to start system services The error message can be found in the log file which is located at:\nC:\\temp\\host-agent-install-log. The following article helps me solving the installation issue: https://github.com/aws/aws-codedeploy-agent/issues/189 Basically, we need to add Windows Defender exclusions for the installation and execution folders. In my case, it will be: Add-MpPreference -ExclusionPath (\"C:\\ProgramData\\Amazon\\CodeDeploy\",\"$env:windir\\Temp\") The following worked in Windows Server 2016 but somehow didn't work in 2019: Add-MpPreference -ExclusionPath (\"C:\\temp\", \"C:\\ProgramData\\Amazon\\CodeDeploy\") Updates\nJune 18, 2020\nThe last time I checked, it is no longer an issue in the following AMI:\nWindows_Server-2016-English-Full-Base-2020.06.10 November 25, 2020\nIt happened to me again on Windows Server 2019. This time the EC2 is in private subnet, so I also checked the following: Permission attached to EC2 instance profileAccess to endpoints:\nhttps://stackoverflow.com/questions/48023692/aws-codedeploy-not-working-in-private-vpcEvent Viewer > ApplicationEvent Viewer > System. I noticed the following error message:\nA timeout was reached (30000 milliseconds) while waiting for the CodeDeploy Host Agent Service service to connect.\nThe command above still worked, but need a slight change. Along with that, extending the timeout in the following article might help.\nhttps://kevsoft.net/2017/10/02/codedeploy-agent-failing-to-start.html",{"id":472,"title":473,"titles":474,"content":475,"level":9},"/2025/12/01-configure-port-on-aspnet-webapi","01 Configure Port On Aspnet Webapi",[],"Configure Port on ASP.NET Web API I have a ASP.NET Web API using Minimal that's integrated with ASP.NET Aspire. It's great that a single command will start the application along with the supporting resources, but when I need to modify the code, I have to first stop it in Aspire, build, and then restart it in Aspire. It is a hassle compare to just click \"Start Debugging\" in Visual Studio. So, I did just that, stop it in ASP.NET Aspire and start it through Visual Studio. But I noticed that the port launched through ASP.NET Aspire and Visual Studio are different although both are supposed to use launchSettings.json. Through Visual Studio, it defaults to http://localhost:5000 no matter http or https profiles used to launch it, while ASP.NET Aspire use ports specified in launchSettings.json. That prompts me to find a way to match the port so it doesn't change when I launch from either Aspire or Visual Studio. Further investigation, launchSettings.json is meant to be used by Visual Studio. So the profiles are visible in Visual Studio, but apparently the applicationUrl field is not picked up in my case although it is running using Kestrel indicated by \"commandName\": \"Project\". In this case, my application is running .NET 10 and I use Visual Studio 2026 community. Visual Studio has a built-in Debug UI under \u003Cyour-project> > Right click > Properties > Debug > General > Open debug launch profiles UI. If I provide the following command line arguments, then it will use the specified port and add that argument to launchSettings.json. --urls http://localhost:5123 As of this point, I can't find a way to get Visual Studio to use the applicationUrl in the launchSettings.json, so I temporarily use the command line arguments. Other things that I learned is WebApplication.CreateSlimBuilder() will only support http as https termination is usually done on the ingress which I can relate since I built a whole environment from scratch in AWS before. For more information: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/native-aot?view=aspnetcore-10.0#the-web-api-native-aot-template Other things to mention is since we are planning to use the same port, we need to remove the code to launch the application in Aspire to prevent port conflict. In my case, my Aspire solution also include the application projects, so Aspire needs to run first so it can copy the project files before running the application through different instance of Visual Studio.",{"id":477,"title":478,"titles":479,"content":480,"level":9},"/2025/12/02-strongly-typed-left-outer-join-on-mongodb","02 Strongly Typed Left Outer Join On Mongodb",[],"Strongly Typed Left Outer Join on MongoDB Only on the road that you'll see potholes, not on the map. So, I want to perform left outer join on two collections in MongoDB. Lookup has been great (https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/), but I want it strongly typed in C#. Let's take the Movies and Reviews example where: public class Movie\n{\n    public ObjectId Id { get; set; }\n    public string Title { get; set; }\n    public IEnumerable\u003CReview> Reviews { get; set; } = [];\n}\n\npublic class Review\n{\n    public ObjectId Id { get; set; }\n   \n    [BsonElement(\"movie_id\")]\n    public ObjectId MovieId { get; set; }\n\n    public int Rating { get; set; }\n} To simply join all movies to reviews, we can do using Aggregate().Lookup() IMongoCollection\u003CMovie> movieCollection = ...;\nIMongoCollection\u003CReview> reviewCollection = ...;\n\nvar moviesWithReviews = await movieCollection.Aggregate()\n  .Lookup\u003CMovie, Review, Movie>(\n    foreignCollection: reviewCollection,\n    localField: movie => movie.Id,\n    foreignField: review => review.MovieId,\n    @as: movie => movie.Reviews).ToListAsync(); But if we need additional condition, for example Movie.Title == \"Beauty and the Beast\", we need to use pipeline. https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/#std-label-lookup-multiple-joins. So, the query to MongoDB is similar to: db.movie.aggregate( [\n   {\n      $lookup:\n         {\n           from : \"reviews\",\n           localField : \"_id\",\n           foreignField : \"movie_id\",\n           let : { pipeline_title: \"$title\" },\n           pipeline : [\n              { $match :\n                 { $expr :\n                      { $eq: [ \"$$pipeline_title\", \"Beauty and the Beast\" ] }\n                 }\n              }\n           ],\n           as : \"Reviews\"\n         }\n    }\n] ) Notes the use of let. It is because the pipeline has no access to the input. And to access the pipeline variable, we need double dollar sign ($$). From the documentation: The pipeline cannot access fields from input documents. Instead, define variables for the document fields using the let option and then reference the variables in the pipeline stages. To convert to C#, there's no Lookup overload that's similar to the query above. But we can do the following query and utilize one of the overloads: db.movie.aggregate( [\n   {\n      $lookup:\n         {\n           from : \"reviews\",\n           let : { pipeline_title: \"$title\", pipeline_id: \"$_id\" },\n           pipeline : [\n              { $match :\n                 { $expr :\n                      { $and: [\n                        { $eq: [ \"$movie_id\", \"$$pipeline_id\" ]},\n                        { $eq: [ \"$$pipeline_title\", \"Beauty and the Beast\" ] }\n                      ]}\n                      \n                 }\n              }\n           ],\n           as : \"Reviews\"\n         }\n    }\n] ) In C#, it becomes: var lookupPipeline = new EmptyPipelineDefinition\u003CReview>()\n  .Match(new BsonDocument(\"$expr\",\n          new BsonDocument(\"$and\", new BsonArray\n          {\n            new BsonDocument(\"$eq\", new BsonArray { \"$movie_id\", \"$$pipeline_id\" }),\n            new BsonDocument(\"$eq\", new BsonArray { \"$$pipeline_title\", \"Beauty and the Beast\" \n          })\n  })));\n\nvar moviesWithReviews = await movieCollection.Aggregate()\n  .Lookup\u003CMovie, Review, IEnumerable\u003CReview>, Movie>(\n      foreignCollection: reviewCollection,\n      let: new BsonDocument { { \"pipeline_title\": \"$title\" }, { \"pipeline_id\", \"$_id\" } },\n      lookupPipeline: lookupPipeline,\n      @as: new ExpressionFieldDefinition\u003CMovie, IEnumerable\u003CReview>>(movie => movie.Reviews))\n  .ToListAsync(); If we want the lookupPipeline to be strongly typed, especially on the Review.MovieId field we are can't do the following since pipeline variable is only accessible with $expr operator. As far as I experienced, I don't see any C# equivalent for the operator. var lookupPipeline = new EmptyPipelineDefinition\u003CReview>()\n  .Match(review => review.MovieId == \"$$pipeline_id\" && \"$$pipeline_title\" == \"Beauty and the Beast\"); And the following doesn't work either: var filterBuilder = Builders\u003CReview>.Filter;\n\nvar filter = filterBuilder.And(\n    filterBuilder.Eq(review => review.MovieId, \"$$pipeline_id\"),\n    filterBuilder.Eq(\"$$pipeline_title\", \"Beauty and the Beast\")); After more trials and errors, I found MongoDB LINQ Syntax for Aggregation. https://www.mongodb.com/docs/drivers/csharp/current/aggregation/linq/#lookup--. The one that finally works look like: var movieCollectionQuery = movieCollection.AsQueryable();\n\nvar lookupResults = await movieCollectionQuery.Lookup\u003CMovie, Review, Review>(\n            reviewCollection,\n            (movie, reviews) => reviews.Where(review => review.MovieId == movie.Id && movie.Title == \"Beauty and the Beast\")).ToListAsync();\n\nvar moviesWithReviews = [..lookupResults.Select(result =>\n{\n    var movie = result.Local;\n    movie.Reviews = result.Results;\n    return movie;\n})];",{"id":482,"title":483,"titles":484,"content":485,"level":9},"/2025/12/03-asp.net-web-forms-external-component-has-thrown-an-exception-error","03 ASPNET Web Forms External Component Has Thrown An Exception Error",[],"ASP.NET Web Forms \"External component has thrown an exception\" Error This is a repost from my old blog. First posted in 6/22/2020. Every once in a while, I will get a random error for reasons too time consuming to dig. I have been using Azure DevOps to create CI/CD pipeline to deploy our web application and it has been going well so far. And today, I suddenly got a weird error but it was easily solved. I had no trouble logging in and going to the main page of our web application. But when visiting a particular page, suddenly throws \"External component has thrown an exception\". I tested it locally and had no problem. And nothing changed on the code of that particular page. Sometimes it can be due to the server runs out of memory and that doesn't appear to be the case this time. This is probably another hiccup I thought. So, I went inside the server and recycle the application pool in IIS. Then, I went back to the browser and reload the page that caused an error and this time it loads without any issue. And the solution this time is simply recycling the application pool.",{"id":487,"title":488,"titles":489,"content":490,"level":9},"/2025/12/04-windows-server-2016-update-error-0x8007000e","04 Windows Server 2016 Update Error 0x8007000e",[],"Windows Server 2016 Update Error 0x8007000e This is a repost from my old blog. First posted in 6/24/2020. This one server that I managed has not been updated for a while and I happened to need to create a new image out of it, so I thought I might as well update it to the latest via Windows Update. And I ended up spending hours troubleshooting how to update. Windows Update ran into 0x8007000e error when checking for updates. Searching online, some suggested installing Windows Update Troubleshooter or similar tools or update the Windows Update agent. And some people suggested that the OS actually runs out of memory or storage. My server has 10+ GB of free space and 2GB memory. I thought it shouldn't run out of resources until I read the following articles: https://feedback.azure.com/forums/216843-virtual-machines/suggestions/31407055-low-on-memory-error-server-2016-b-series I follow the suggestion in there to increase the memory to 4GB and it finally updates without issue. I also noticed while the check is running, it consumes about 45% of memory. And the download finally runs, it takes around 55-65% of memory. That definitely won't work on my previous configuration. So the solution in my case is to use 4GB or more memory.",{"id":492,"title":493,"titles":494,"content":495,"level":9},"/2025/12/05-exploring-mongodb-atlas","05 Exploring Mongodb Atlas",[],"Exploring MongoDB Atlas I'm planning to host my app in AWS. My app is built to integrate with MongoDB and AWS does have a MongoDB compatible service called DocumentDB. One thing I like about DocumentDB is AWS separate the compute from the storage. Which means, the compute can be removed without losing data and we will incur only the storage charge when we don't need it running. This is especially helpful especially during development. However, there are compatibility issue between MongoDB and DocumentDB. Not all MongoDB features are supported by DocumentDB. At the same time, I just used basic features, so it shouldn't be a problem. For more information: https://docs.aws.amazon.com/documentdb/latest/developerguide/compatibility.html When I used DocumentDB before this, I utilized AWS EventBridge to add/remove DocumentDB on schedule to save significant cost. However, if I need it outside of the scheduled time, I need to remember to add the compute part back or I will end up spending a lot of time wondering why connection to DB is broken. As I was looking for alternative, I read on MongoDB Atlas. Basically it cloud ready MongoDB. Setup is easy and it has free tier which is great for my use case. By default, it has basic security in which it will only allow ingress from your local public IP. And small thing to watch out for is when I tried to retrieve the connection string, I need to find the username and password which is not very obvious on where to find them. We actually need to create a user and it is accessible from the side menu Security > Database & Network Access. Once I'm ready to deploy my application to AWS, I need to find out how to enable access through private network, so the data doesn't go through the internet which will greatly improve security and performance. I will update this post once I cross that bridge.",{"id":497,"title":498,"titles":499,"content":500,"level":9},"/2025/12/06-aspnet-dockerfile-for-local-and-cicd","06 Aspnet Dockerfile For Local And Cicd",[],"ASP.NET Dockerfile for Local and CI/CD Finally my application is ready to be deployed. To make it portable, it needs to be containerized, so I'm working on Dockerfile. To get a jumpstart, I copied the Dockerfile from https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/docker/building-net-docker-images?view=aspnetcore-10.0#the-dockerfile. Then I'm thinking to test it locally with the following command: docker build -t app:latest . However, it throws few error messages: error MSB4018: The \"ResolvePackageAssets\" task failed unexpectedly.\n\nerror MSB4018: NuGet.Packaging.Core.PackagingException: Unable to find fallback package folder 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages' Ok, it's weird that it's looking for windows path when the image is linux based. I quickly found out that since the COPY step runs locally, it copies the bin and obj directories as well which was generated from my local Windows machine and thus incompatible with the Linux based image. To prevent that, I tried using .dockerignore file and place it on the same directory as the Dockerfile. Since in dockerignore file, leading and trailing slashes are disregarded, I just need the following content. For more information: https://docs.docker.com/build/concepts/context/#syntax */bin\n*/obj Re-building it locally throws yet another error: error NETSDK1047: Assets file '/source/path/to/app/obj/project.assets.json' doesn't have a target for 'net10.0/linux-x64'. Ensure that restore has run and that you have included 'net10.0' in the TargetFrameworks for your project. You may also need to include 'linux-x64' in your project's RuntimeIdentifiers. I checked the .csproj file of my application and it doesn't have \u003CRuntimeIdentifier>linux-x64\u003C/RuntimeIdentifier>. Probably because my local development machine is Windows. Since I need it to be able to run in both Windows (local) and Linux (remote), I tried the following: \u003CRuntimeIdentifier>linux-x64;win-x64\u003C/RuntimeIdentifier> Which is supposed to be valid, but the build failed again. This time the message is: The \"HasTrailingSlash\" function only accepts a scalar value, but its argument \"$(OutputPath)\" evaluates to \"bin\\Debug/net10.0/linux-x64;win-x64/\" which is not a scalar value. Alright, removed \u003CRuntimeIdentifier> tag. On CI/CD pipeline, I'll use the Dockerfile, for local development, I'll just use Visual Studio or dotnet CLI, so I can add --os linux option to dotnet restore step. In the Dockerfile, it becomes: ...\nRUN dotnet restore --os linux\n... Then it builds successfully on my local machine. Since bin and obj directories are not tracked by the version control, the CI/CD pipeline won't have to worry about them.",{"id":502,"title":503,"titles":504,"content":505,"level":9},"/2025/12/07-asp.net-owin-usecookieauthentication-logs-user-out-after-sign-in","07 ASPNET OWIN UseCookieAuthentication Logs User Out After Sign In",[],"ASP.NET OWIN UseCookieAuthentication Logs User Out After Sign In This is a repost from my old blog. First posted in 6/29/2020. I have a need to do manual cookie authentication. As I use OWIN with UseCookieAuthentication middleware, it is not that hard except when I had no idea what is actually required. I know I had to create a ClaimsIdentity and I will need AuthenticationProperties object. Supplying both of them successfully created the cookie, but when I went to a different page, the authentication failed and the application kicked me out to the login page. The following is my initial problematic code in the authentication handler: Dim claims As New List(Of Claim)\nclaims.Add(New Claim(ClaimTypes.NameIdentifier, user.Username))\nDim claimsIdentity As New ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationType)\ncontext.GetOwinContext().Authentication.SignIn(New AuthenticationProperties With {\n    .ExpiresUtc = expiration\n}, claimsIdentity) For my basic requirement, apparently there are required claims. In my case, I'm missing the Name claim. Adding the following claim solves my issue: claims.Add(New Claim(ClaimTypes.Name, user.Name)) As of now, I'm still not sure why it is necessary and haven't had time to look it up. But a quick read on ClaimsIdentity reveal that NameClaimType is necessary. https://docs.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity?view=netframework-4.8 My final code thus becomes: Dim claims As New List(Of Claim)\nclaims.Add(New Claim(ClaimTypes.NameIdentifier, user.Username))\nclaims.Add(New Claim(ClaimTypes.Name, user.Name))\nDim claimsIdentity As New ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationType)\ncontext.GetOwinContext().Authentication.SignIn(New AuthenticationProperties With {\n    .ExpiresUtc = expiration\n}, claimsIdentity)",{"id":507,"title":508,"titles":509,"content":510,"level":9},"/2025/12/08-aws-codedeploy-failed-deployment-in-windows-server","08 AWS CodeDeploy Failed Deployment In Windows Server",[],"AWS CodeDeploy Failed Deployment in Windows Server This is a repost from my old blog. First posted in 7/12/2020. Our CI/CD pipeline has been going smoothly for a long time. Today, I happened to need to deploy something and it failed. First, I looked in the console and viewing the events, it failed at the first step which is ApplicationStop. So I thought the application is still running which is usually the case when the deployment failed but this time no instance of my application is being run at that moment. Next, I check the log file which can be found in: https://docs.aws.amazon.com/codedeploy/latest/userguide/deployments-view-logs.html The log file indicated the agent can't connect to the host. One of the error message in the log is \"certificate verify failed\". I restarted the CodeDeploy agent but the issue persisted. Eventually, by uninstalling and updating the CodeDeploy agent solves my issue. In my case, which is in Windows Server, I had to stop the agent service and uninstall to enable the update to success. https://docs.aws.amazon.com/codedeploy/latest/userguide/codedeploy-agent-operations-update-windows.html",{"id":512,"title":513,"titles":514,"content":515,"level":9},"/2025/12/09-iis-401-error-on-new-website","09 IIS 401 Error On New Website",[],"IIS 401 Error on New Website This is a repost from my old blog. First posted in 7/13/2020. I had a new site setup on IIS and thought I got everything setup fine. Everything seems ok from: BindingSNICertificateEnable Allow AnonymousDirectory permissionRedirectetc Guess what? Can't even access my home page. The server throws the following error: 401 - Unauthorized: Access is denied due to invalid credentials.\nYou do not have permission to view this directory or page using the credentials that you supplied. Usually it is because of permission on the directory. But this time it looks fine. Weird thing is I can visit aspx page, but some of the static files are blocked. After some browsing, I noticed the value under Site > Authentication > Anonymous Authentication > Edit... (right-click) of the other site that works fine was set to Application pool identity. Meanwhile, my new site was set to Specific user: IUSR and my directory only allow access to IIS_IUSRS. In my case, setting the above to Application pool identity solves my issue.",{"id":517,"title":518,"titles":519,"content":520,"level":9},"/2025/12/10-azure-devops-output-variable","10 Azure Devops Output Variable",[],"Azure DevOps Output Variable It is supposed to be a simple task. I need the image uri that was pushed by ECRPushImage task in Azure DevOps on the next task. ECRPushImage task has outputVariable variable, so let say I set that to ImageUri on my azure-pipelines.yml - task: ECRPushImage@1\n  inputs:\n    ...\n    outputVariable: 'ImageUri' According to this article https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#use-output-variables-from-tasks, I also need to set name on the task: - task: ECRPushImage@1\n  name: ECR\n  inputs:\n    ...\n    outputVariable: 'ImageUri' So, I can use the variable like following: - script: echo $(ECR.ImageUri) But it doesn't work, the variable was not replaced. I also tried other runtime syntax in https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#understand-variable-syntax. So, I went to the GitHub https://github.com/aws/aws-toolkit-azure-devops/blob/master/src/tasks/ECRPushImage/TaskOperations.ts#L81 and it does a simple task.setVariable(). According to the setVariable documentation https://learn.microsoft.com/en-us/azure/devops/pipelines/process/set-variables-scripts?view=azure-devops&tabs=bash#about-tasksetvariable, we can access the variable without the name, so it becomes: - task: ECRPushImage@1\n  inputs:\n    ...\n    outputVariable: 'ImageUri'\n- script: echo $(ImageUri) And it works! That's after 10 iterations of trials and errors.",{"id":522,"title":523,"titles":524,"content":525,"level":9},"/2025/12/10-docker-build-copy-directory-not-found","10 Docker Build Copy Directory Not Found",[],"Docker Build Copy Directory Not Found So, I tried to provide parameter to Dockerfile since my CI/CD pipeline runs in Azure DevOps and the artifact staging directory is provided as variable and I don't want to hard code the value inside Dockerfile. Enter Build variables https://docs.docker.com/build/building/variables/. It seems simple. All I need in my dockerfile is: FROM ...\nARG SRC=\"./app\"\nCOPY ${SRC} . Then I can pass the value: docker build --build-arg SRC=$(Build.ArtifactStagingDirectory) . Well, it throws an error: ERROR: failed to build: failed to solve: failed to compute cache key: failed to calculate checksum of ref 4ce6fa60-2f23-4ac2-b56a-0440c85af90a::qzmaj2vppe2uy3akiebhn7od1: \"/home/vsts/work/1/a\": not found The path is correct, but somehow Docker can't find the directory. Apparently, it has something to do with build context https://docs.docker.com/build/concepts/context/ because the following works: cd $(Build.ArtifactStagingDirectory)\ndocker build --build-arg SRC=. . Which means only the directory on which the Dockerfile is being executed from and its subdirectories are accessible inside Dockerfile.",{"id":527,"title":528,"titles":529,"content":530,"level":9},"/2025/12/10-miro-recap-2025","10 Miro Recap 2025",[],"Miro Recap 2025 So, some of my coworkers are viewing their Miro recap today. We have been using Miro extensively which really helps when our team is big and we have sub-teams/pairing, etc. Here's my result: Thanks Miro for doing this fun summary. Visit Miro at https://miro.com/.",{"id":532,"title":533,"titles":534,"content":535,"level":9},"/2025/12/11-checking-anonymous-authentication-allowed-on-asp.net-owin-middleware-and-web-forms","11 Checking Anonymous Authentication Allowed On ASPNET OWIN Middleware And Web Forms",[],"Checking Anonymous Authentication Allowed on ASP.NET OWIN Middleware and Web Forms This is a repost from my old blog. First posted in 7/13/2020. Some business logic on our web application apparently caused issue when hitting a page that allow anonymous authentication. And it seems there is no simple flag that indicates whether a page requires authorization or not. I need to check for allow anonymous in ASP.NET Web Forms page and on OWIN middleware. For ASP.NET Web Forms page, I found the following thread in StackOverflow which works great: https://stackoverflow.com/questions/8662922/programmatically-check-if-page-requires-authentication-based-on-web-config-setti In my case, I need to convert the code to VB.NET, so it becomes: Dim principal = New GenericPrincipal(New GenericIdentity(String.Empty, String.Empty), New String() {})\nDim isAllowAnonymous = UrlAuthorizationModule.CheckUrlAccessForPrincipal(Page.AppRelativeVirtualPath, principal, Context.Request.HttpMethod).ToString() And on OWIN middleware, I need to tweak the above a little bit, so it becomes: Dim principal = New GenericPrincipal(New GenericIdentity(String.Empty, String.Empty), New String() {})\nDim isAllowAnonymous = UrlAuthorizationModule.CheckUrlAccessForPrincipal(context.Request.Uri.AbsolutePath, principal, context.Request.Method)",{"id":537,"title":538,"titles":539,"content":540,"level":9},"/2025/12/12-frustrating-please-wait-for-an-editor-command-to-finish-pop-up-when-editing-javascript","12 Frustrating Please Wait For An Editor Command To Finish Pop Up When Editing JavaScript",[],"Frustrating \"Please wait for an editor command to finish\" Pop-up When Editing JavaScript This is a repost from my old blog. First posted in 7/22/2020. It happens to be I need to edit a massive JavaScript file and I tried to speed through it, however, my instance of Visual Studio 2017 is not helpful by trying to be helpful. Every single key stroke triggers a 1-5 seconds pause which sometimes caused a pop-up with \"Please wait for an editor command to finish\" message to show. Worse, that pop-up is not cancelable. Additionally, my CPU usage was hovering at 80-90% just editing JavaScript! As of this time, my Visual Studio 2017 version is 15.9.25. Seems like it is triggered by some auto-suggestion tools which in Visual Studio, Intellisense seems to be the culprit. I ended up going to Tools > Options > JavaScript/TypeScript > Formatting > General and uncheck everything under Automatic Formatting. Even after that I still noticed a half-a-second delay on some keystrokes, so I also uncheck Tools > Options > JavaScript/TypeScript > Linting > General > Enable ESLint. That made my life a whole lot easier. It also drops my CPU usage to 10-20%.",{"id":542,"title":543,"titles":544,"content":545,"level":9},"/2025/12/13-ef-sum-error-due-to-empty-rows-after-filtering-on-mysql","13 EF Sum Error Due To Empty Rows After Filtering On MySQL",[],"EF Sum Error Due to Empty Rows After Filtering on MySQL This is a repost from my old blog. First posted in 7/23/2020. I actually have been waiting when I will encounter this kind of error. This time the error happens when performing EF query on MySQL database. After filtering, the query returns empty rows thus sum can't work. The error message in my case is: \"The cast to value type 'System.Decimal' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.\" The following is an example code: Dim totalPrice = dbContext.Items.Where(Function(i) i.Color = \"Blue\").Sum(Function(i) i.Price) However it works fine if we execute the query first before Sum, but it requires the rows to be pulled to memory which can be resource intensive. Dim totalPrice = dbContext.Items.Where(Function(i) .Color = \"Blue\").ToList().Sum(Function(i) i.Price) One helpful article: https://coding.abel.nu/2012/08/null-sematics-in-linqs-sum/ The solution in my case is to perform projection, followed by DefaultIfEmpty and call Sum() afterwards. The code becomes: Dim totalPrice = dbContext.Items.Where(Function(i) i.Color = \"Blue\").Select(Function(i) i.Price).DefaultIfEmpty(Decimal.Zero).Sum()",{"id":547,"title":548,"titles":549,"content":550,"level":9},"/2025/12/14-vb.net-variable-value-in-loop","14 VBNET Variable Value In Loop",[],"VB.NET Variable Value in Loop This is a repost from my old blog. First posted in 8/17/2020. While troubleshooting other things, I found out that I got trapped in the beginner's mistake. Essentially, I'm expecting when I declare a variable inside a loop, it is automatically set to its default value for each loop, but it is not the case. For example, I have the following loop: For i = 0 to Count - 1\n   Dim x As Integer\n   x += 1\nNext I'm expecting the value of x to stay at 1 for each loop because I declare it inside the loop, but by the end of the second loop, the value of x is 2 and so on. Apparently, the variable is getting reused and the existing value is carried over to the next iteration. Remember to initialize the variable when it is inside a loop, thus the above loop becomes: For i = 0 to Count - 1\n   Dim x As Integer = 0\n   x += 1\nNext",{"id":552,"title":553,"titles":554,"content":555,"level":9},"/2025/12/15-amazon-cloudwatch-getmetricdata-api-samplecount-returns-0","15 Amazon CloudWatch GetMetricData API SampleCount Returns 0",[],"Amazon CloudWatch GetMetricData API SampleCount Returns 0 This is a repost from my old blog. First posted in 8/17/2020. One of our code is to keep track on how many data points are there for each CloudWatch metric. So, I usually use the GetMetricData API with statistic set to SampleCount. But since we only care about the total, I don't use short period (high resolution). Partly, it is to reduce the amount of data returned. However, in one case, it returns 0 for a particular month. According to the following documentation, period has to be a multiply of 60: https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDataQuery.html No problem, since my start time and end time is exactly one month apart, I will just set the period to the number of seconds between start time and end time to get highest number of period. It works for some months, it returns 0 in this particular case. Strange until I found out in a different documentation that there's a max period of 86,400 seconds (one day). https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Statistic I change my period to 86400 and it no longer returns 0.",{"id":557,"title":558,"titles":559,"content":560,"level":9},"/2025/12/16-xcode-codesign-incorrectly-states-password-is-incorrect","16 Xcode CodeSign Incorrectly States Password Is Incorrect",[],"Xcode CodeSign Incorrectly States Password is Incorrect This is a repost from my old blog. First posted in 9/11/2020. I was trying to create an archive in Xcode to prepare the app for testing. It requires a code signing certificate and Xcode tried to reach out to Keychain to obtain it, so it prompted me for a password to my Keychain. My first thought is since the Keychain lives in my Mac, it has to be my Mac's password, so I entered it and it failed. I re-checked the characters, re-entered and it still failed. That is odd considering I did that before without issue. I found out that my Keychain Access app was still active. I have to quit the app and then it proceeds properly. So, the solution is quit the Keychain Access app before entering password for signing.",{"id":562,"title":563,"titles":564,"content":565,"level":9},"/2025/12/17-mermaid-on-miro","17 Mermaid On Miro",[],"Mermaid on Miro I tried to put my Mermaid code on Miro. Copy paste didn't go so well, but it eventually work with some limitations. It doesn't like colon. My mermaid code is for Entity Relation diagram. There's a way to easy apply style using classDef and triple colon shorthand :::. For example: Entity:::primary {\n  int ID PK\n}\n\nclassDef primary stroke:#0000FF,stroke-width:2px The above throws Parse error... I found out that at that time, the Mermaid version installed in Miro is 10.9 while the latest is 11.12, so maybe a lot has changed. Removing all the colons work. And I can't find styling documentation for Mermaid 10.9, so I can't apply any style. Another limitation is Mermaid diagram will be rendered in Miro as an image. It is supposedly editable and it works for the template diagrams, but for my custom diagram, it lost the code somehow when I attempted to edit existing image/diagram.",{"id":567,"title":568,"titles":569,"content":570,"level":9},"/2025/12/18-null-safe-nullable-variable","18 Null Safe Nullable Variable",[],"Null Safe Nullable Variable Please don't do this unless there's a solid reason. So, I happened to see Javascript code similar to the following on a production app which I can't see the reason. Assuming redirectUrl is never null. const url = isRedirect ? redirectUrl : \"null\"; The above renders the check further down useless: if (url) {\n  // Do something\n}",{"id":572,"title":573,"titles":574,"content":575,"level":9},"/2025/12/19-exploring-react-router-v7","19 Exploring React Router V7",[],"Exploring React Router v7 Coming from React Router v6, the new version brings a lot of change. One of them is the various modes that we can use: FrameworkDataDeclarative From all of them, seems like Framework mode is the recommended and most comprehensive, so I start with that. However, the documentation is a little confusing for me. To start with, the installation instruction begins with a template. In my case, I want to start from scratch and I found it under upgrading: https://reactrouter.com/upgrading/component-routes. It is also to good to check the following page: https://reactrouter.com/how-to/route-module-type-safety. In my case, I want to use layout and the following page is a great help: https://reactrouter.com/start/framework/routing. When it finally works, I need to build the app. In my case, I want to use SSG, so I need to disable the SSR (Server Side Rendering) which is covered under: https://reactrouter.com/how-to/spa.",{"id":577,"title":578,"titles":579,"content":580,"level":9},"/2025/12/20-react-router-conditional-protected-route","20 React Router Conditional Protected Route",[],"React Router Conditional Protected Route I'm using react-oidc-context package for my app. And so far, all routes on my app is protected. However, I need to let some routes to not require authentication. I can't find much documentation on how to do that on React Router v7 Framework mode. So, I start with gathering all relevant information. To protect a route using react-oidc-context is by providing the component that we want to protect (https://github.com/authts/react-oidc-context?tab=readme-ov-file#protect-a-route). However, the Framework mode of React Router v7 route config is made up of strings, so I can't just do something like: route('/some-route', withAuthenticationRequired('path-to-file')) Back in React Router v6, since I was using either Data or Declarative mode, I can just create AuthenticationGuard component and apply it on the route itself similar to this Auth0 guide. But obviously can't be applied to React Router v7 Framework mode. In my case, I want to protect a parent Layout component, so all the underlying routes will be protected as well. And I will put unprotected route outside of the protected Layout component. So, I went from: export default withAuthenticationRequired(Outlet, {\n  OnRedirecting: () => (\u003Cdiv>Redirecting to the login page...\u003C/div>)\n}) to export default withAuthenticationRequired(Layout, {\n  OnRedirecting: () => (\u003Cdiv>Redirecting to the login page...\u003C/div>)\n}) The code above was in root.tsx and it didn't work for me. And as a good keeping-up-with-the-tech engineer, I check with AI. The recommended way was to use middleware. I'm familar with middleware concept on .NET OWIN era, so it makes sense to me. As I explore it at this time, the middleware is still under testing for Framework mode and it is an opt-in only. In other words, it probably will change in the future, so I'd rather wait until it stabilize a bit more. Eventually, after more trials and errors, I got it working by moving the withAuthenticationRequired method from root.tsx file to Layout.tsx file. My route looks like the following: export default [\n  layout('./routes/layout.tsx', [\n    route(\"protected\", \"./routes/protected.tsx\")\n  ]),\n  route(\"unprotected\", \"./routes/unprotected.tsx\")  \n] satisfies RouteConfig; And my Layout.tsx: const Layout = () => {\n...\n}\n\nexport default withAuthenticationRequired(Layout, {\n  OnRedirecting: () => (\u003Cdiv>Redirecting to the login page...\u003C/div>)\n})",{"id":582,"title":583,"titles":584,"content":585,"level":9},"/2025/12/21-signing-certificate-is-none-in-xcode","21 Signing Certificate Is None In Xcode",[],"Signing Certificate is None in Xcode This is a repost from my old blog. First posted in 9/11/2020. Xcode has this capability to manage certificates, app ID and provisioning profile which makes is very convenient. However, this time, I would like to manage my own. I manage to get Xcode to recognize the provisioning profile that I have created in developer.apple.com. However, under .xcodeproj (project file) > Signing & Capabilities > Signing Certificate, the value is none. It also comes with an error that it the provisioning profile is not associated with its own developer certificate. I have made sure that the certificate associated with the provisioning profile is stored in my Keychain, but it seems like Xcode is still trying to use a different certificate for signing. My guess was right, I went to .xcodeproj (project file) > Build Settings > Code Signing Identity and found out that it is set to iOS Developer under \"Automatic\" section. Switching it to the right (associated with provisioning profile) certificate on the Keychain solves the issue.",{"id":587,"title":588,"titles":589,"content":590,"level":9},"/2025/12/22-mermaid-zoomable-previewer-in-vs-code","22 Mermaid Zoomable Previewer In Vs Code",[],"Mermaid Zoomable Previewer in VS Code Up to this point, I had my diagram in a regular markdown file. The problem is when the diagram got bigger, the previewer can't zoom in. Reading the extension doc, it does support pan and zoom. However, I wasn't able to access that feature. After playing around a little, I figured out the way to do it. The previewer supports only .mmd file. So, here are the steps I did: Move mermaid diagram to mmd file.Open the mmd file in VS code.Click CTRL + Shift + P and search for MermaidChart: PreviewDiagram By default, it has no key binding, so I bind mine to ALT + SHIFT + M for quick access.",{"id":592,"title":593,"titles":594,"content":595,"level":9},"/2025/12/23-searching-files-by-datemodified-in-file-explorer-in-windows","23 Searching Files By DateModified In File Explorer In Windows",[],"Searching Files by DateModified in File Explorer in Windows This is a repost from my old blog. First posted in 9/15/2020. I was in the middle of some project files restructuring and part of the process is making a back up of my files. When all is done, I went back to my back up folder to find files that I modified a day before. I know there has to be a way to do that, but it is not immediately obvious. But the following article was helpful to me. https://www.howtogeek.com/243511/how-to-search-for-files-from-a-certain-date-range-in-windows-8-and-10 I opted for the UI solution, that is to use the Search tab. However, I can't find the search tab in File explorer, so I decided to go the harder route, to type into the search box. I managed to file my files by typing the following in the search box: datemodified:\u003Cstart_date>..\u003Cend_date> For example: datemodified:9/14/2020..9/15/2020 modified: instead of datemodified: works too. Also, the search tab finally shows after I got my search result.",{"id":597,"title":598,"titles":599,"content":600,"level":9},"/2025/12/24-unwanted-dollar-sign-in-bash-script","24 Unwanted Dollar Sign In Bash Script",[],"Unwanted Dollar Sign in Bash Script This is a repost from my old blog. First posted in 9/18/2020. The script that I used ran fine for various flavors of Linux for a long time. But somehow, it produced unwanted dollar sign on Ubuntu 18.04, so my hours of troubleshooting starts. The simplest one I can say is I use echo with tab and variables and piped that to awk through AWS Systems Manager. It is similar to the following: v='variable'\nTAB=$'\\t'\necho \"${v}${TAB}\" | awk '{print $0}' In many flavors of Linux other than Ubuntu 18.04, even in Ubuntu 16.04, it produced the expected result: variable However, in Ubuntu 18.04, it ends the result with an extra dollar sign: variable$ At first, I thought it marks end of line or the typical \\0 (NUL character) that marks end of string, so I tried various ways to remove it such as using tr, gsub, etc. But none of them works. Eventually, I found out that the dollar sign comes from the TAB variable. To solve it, I have to replace the above with: echo -e \"${v}\\t\"",{"id":602,"title":603,"titles":604,"content":605,"level":9},"/2025/12/25-sns-https-fanout-to-api-gateway-error","25 SNS HTTPS Fanout To API Gateway Error",[],"SNS HTTPS Fanout to API Gateway Error This is a repost from my old blog. First posted in 11/11/2020. In one of my projects, I have an Amazon SNS subscription set up to fan out to HTTPS endpoint that is backed by Amazon API Gateway. The API Gateway has mapping template applied. It went smoothly during test with Postman and the API Gateway test, but when SNS sends the Notification message, it threw an error. On CloudWatch log, the error message is: Execution failed: null Apparently SNS sends request with Content-Type of text/plain although the request body contains json while I only had mapping set for application/json. So adding mapping template for text/plain solves my problem.",{"id":607,"title":608,"titles":609,"content":610,"level":9},"/2025/12/26-nuget-package-reference-nu6105-publish-error","26 NuGet Package Reference NU6105 Publish Error",[],"NuGet Package Reference NU6105 Publish Error This is a repost from my old blog. First posted in 11/11/2020. Some of my .NET Core applications are already using PackageReference which is a very nice idea. However, through a combination of packages, Visual Studio did not allow me to publish my project although it built fine. During publish, it threw error on NU6105 warning. Along with that most of it comes with the following message: Detected package downgrade Some developers solve it by finding which package caused the issue and manually added them through NuGet, but I find them troublesome until I found the following article: https://docs.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu1605 In my case, all I need to do to solve it is to install the following NuGet package: Microsoft.NETCore.Targets",{"id":612,"title":613,"titles":614,"content":615,"level":9},"/2025/12/27-msbuild-copy-task-afterbuild-vs2019","27 MSBuild Copy Task AfterBuild VS2019",[],"MSBuild Copy Task AfterBuild VS2019 This is a repost from my old blog. First posted in 11/11/2020. This time the issue is with MSBuild task that I set up in one of my project (in the project file). The task is to copy the dll to a different location after build is done. I copied the configuration over to a different project and guess what, it didn't work. It worked flawlessly for a very long time with the following configuration: \u003CTarget Name=\"AfterBuild\">\n  \u003CCopy SourceFiles=\"...\" DestinationFolder=\"...\" />\n\u003C/Target> Two main differences between the two projects are the working on is a .NET Framework project and built in VS2017. The new one is a .NET Standard and built in VS2019. Apparently, there is a change for VS2019 that comes with updated MSBuild. It is no longer depends on the target name (it is a bad idea anyway) to determine when to execute the task. I update it to the following and then it works great. \u003CTarget Name=\"AnyNameIsFine\" AfterTargets=\"Build\">\n  \u003CCopy SourceFiles=\"...\" DestinationFolder=\"...\" />\n\u003C/Target> For reference: https://docs.microsoft.com/en-us/visualstudio/msbuild/copy-task?view=vs-2019",{"id":617,"title":618,"titles":619,"content":620,"level":9},"/2025/12/28-react-navigation-handle-header-button-click-on-child-screen-or-component","28 React Navigation Handle Header Button Click On Child Screen Or Component",[],"React Navigation Handle Header Button Click on Child Screen or Component This is a repost from my old blog. First posted in 11/11/2020. I have a react native application which I need to handle header button / action button click on the detail screen. And the journey to solve it was not a short one. On the parent screen, I have defined a stack navigation and set the header button. Then I need to handle the header button click on the child screen. I read about passing the function as parameter but it's not easy. There are also options to useEffect or ref, but none of them are working for me. In the end, the one that works for me and pretty clean too is by using React.useLayoutEffect and navigation.setOptions: const ChildScreen = ({navigation, route}) => {\n  React.useLayoutEffect(() => {\n    navigation.setOptions({\n      headerRight: () => (\n        \u003CButton onPress={() => ...} title=\"Right\" />\n      ),\n    });\n  }, [navigation]);\n  \n  return (...)\n}; Reference: https://reactnavigation.org/docs/header-buttons/#header-interaction-with-its-screen-component",{"id":622,"title":623,"titles":624,"content":625,"level":9},"/2025/12/29-ftp-access-denied-when-attempting-to-transfer-files","29 FTP Access Denied When Attempting To Transfer Files",[],"FTP Access Denied When Attempting to Transfer Files This is a repost from my old blog. First posted in 12/8/2020. Permission is, as usual, a double-edged sword. It happened when I tried to transfer files to a remote Linux server. I created a directory on the remote server and attempting to transfer files via FTP client but got an access denied error. It is weird because I do login using the same account and thus as the owner of the directory. The one that solves the problem in my case is by changing ownership of the folder recursively (-R option) and use name of the user as group name such as: sudo chown -R \u003Cuser>:\u003Cuser> \u003Cdirectory>",{"id":627,"title":628,"titles":629,"content":630,"level":9},"/2025/12/30-amazon-ecr-accessing-private-repository-through-aws-cli","30 Amazon ECR Accessing Private Repository Through AWS CLI",[],"Amazon ECR Accessing Private Repository through AWS CLI This is a repost from my old blog. First posted in 12/8/2020. Remote repository is always an easy way to share code. However, I can't seem to find an easy way to access my private repository in ECR. In order to push or pull from ECR, we have to first login via AWS CLI and pass the credentials to docker. The script is pretty straightforward and will work in most cases except mine: aws ecr get-login-password --region \u003Cregion> | sudo docker login --username AWS --password-stdin \u003Cregistry_url> The problem is I save my credentials for the registry in a different AWS CLI profile, thus I need to change my script to the following so I can push to and pull from the private repository: aws ecr get-login-password --region \u003Cregion> --profile \u003Ccustom_profile> | sudo docker login --username AWS --password-stdin \u003Cregistry_url>",{"id":632,"title":633,"titles":634,"content":635,"level":9},"/2025/12/31-recap-2025","31 Recap 2025",[],"Recap 2025 Looking back at 2025. Here are some stuffs that I go involved in: Join Integrity Inspired. I started a new job as a consultant. Before this, I was looking to have either one of these three things: opportunity to talk directly with customer, experience working for big companies as I never had one before, and working in a team. With Integrity, I got all three plus I'm not directly involved in big company bureaucracy and I got to learn TDD.Create CLI using Commander.js and Chalk.js and Puppeteer. So, just to work on project/repo that our team own locally, we need 5-6 projects running, each with its own quirks. To automate all of that, I created a CLI, so I can just use a single command to run all projects and do customization. That saved a lot of time rather than manual work that our client recommended.Play with Cypress and Playwright. I have been wanting to get some experience in this. I have the opportunity this year and they are awesome. Cypress has a quirk, but simpler. Playwright is powerful but more complicated.KCDC. This year is my first time in KCDC. And since it is my first time, I had to go round the big convention center to find entrance to the building. I made some new friends and learned a lot of stuffs. One new friend is a Turkish that came all the way from Japan. I also met a former coworker from DCI in Hutchinson, KS.Hack Midwest. 4 of us decided to participate in Hack Midwest this year and we build online carnival backed by Stablecoin. There are some crazy stuffs going in the event, but we had fun. And we won Best Design.Miro recap. We have been using Miro. And Miro made a nice recap page. Most of us are in top 10% spending time in Miro, but I was the only within the top 5% which seems to jumpstart next year Miro competition within my team.Talk at FaithTech. I gave a talk on how to host very cheap website in the cloud. It can be better, but Patrick, a friend of mine, gave me his full support. Even my wife came. A new friend, George, said he finally see that cloud is real. Another friend told me, I'm probably the most frugal guy he knows. Lots of fun.T-shirt design. Integrity is going to make a new T-shirt and asking if any of us want to submit a design. I wish there are more participant, but I submit a dictionary-entry like design and my boss used part of it as the new T-shirt.Read pragmatic programmer. After a long time, I finally read and finish programatic programmer. I learned a ton, especially how to handle ridiculous deadline, how to make code easily changed and managed, and how to negotiate and set priorities.Patrick's AI talk in .NET User Group. Patrick just joined a new company and gave a talk on end-to-end development using AI. It was amazing, he managed to get a project 40% done in a weekend.Phil's AI talk in Next5. Another great AI talk from my boss in Next5. I always love the clarity and honesty that Phil shows in his talk. Rather than succumb to hype, we are encouraged to start exploring AI and see for ourselves on what this new tool can do.",{"id":637,"title":638,"titles":639,"content":640,"level":9},"/2026/01/01-elasticsearch-mapping-visitor-pattern-not-applied-on-dynamic-object","01 ElasticSearch Mapping Visitor Pattern Not Applied On Dynamic Object",[],"ElasticSearch Mapping Visitor Pattern Not Applied on Dynamic Object This is a repost from my old blog. First posted in 12/21/2020. The joy of learning new technology is learning new constraints. There is never enough documentation. I need to insert dynamic objects into ElasticSearch. For the sake of consistency, I need some properties mapped to specify types and the rest will be mapped text. One amazing thing is the ElasticSearch automagical conversion called AutoMap. Seems like AutoMap with visitor pattern and properties override will meet my requirements, so I have something like this in my code: public class MapToTextPropertyVisitor : NoopPropertyVisitor\n{\n    public override IProperty Visit(PropertyInfo propertyInfo,\n            ElasticsearchPropertyAttributeBase attribute) => new TextProperty();\n}\n\nvar createIndexResponse = _client.Indices.Create(\"\u003Cindex_name>\", c => c\n    .Map\u003Cdynamic>(m => m\n        .AutoMap(new MapToTextPropertyVisitor())\n        .Properties(p => p.Date(d => d.Name(\"\u003Coverrides_date_field>\")); AutoMap with manual overrides using fluent mapping:\nhttps://www.elastic.co/guide/en/elasticsearch/client/net-api/current/fluent-mapping.html#_auto_mapping_overrides_down_the_object_graph Visitor pattern:\nhttps://www.elastic.co/guide/en/elasticsearch/client/net-api/current/visitor-pattern-mapping.html But for somewhat reason, some of my dynamic object's properties that are not overridden are still mapped to date type when it is supposed to be mapped to text. I found out later that the visitor pattern doesn't apply to dynamic mapping in which my dynamic objects are subjected to. It only applies to POCO with clear types. Another thing is in my case, the properties in my dynamic object are all of type string. String in ElasticSearch for dynamic mapping has two different kind of detections applied to it: Date detectionNumber detection https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-field-mapping.html So, my problem were solved by disabling the two detections. That makes the string properties stay as string.",{"id":642,"title":643,"titles":644,"content":645,"level":9},"/2026/01/02-running-express-js-application-via-plesk-in-mocha-host-windows-hosting","02 Running Express JS Application Via Plesk In Mocha Host Windows Hosting",[],"Running Express JS Application via Plesk in Mocha Host Windows Hosting This is a repost from my old blog. First posted in 1/10/2021. Nowadays, to run an application balancing best practices and ease of use need tons number of different technology. That means documentations are scattered too. I have an Express JS application that I need to be hosted and since I have active plan under Mocha Host, I decided to host it there. My hosting server is Windows and it supports Node.JS. Looking into the settings, it is as simple as enabling Node.JS. However, after managing to deploy the application, it doesn't run as expected as it returns 404 for known url. When I finally managed to solve the running issue, there are many steps that I need to configure to get my application working. Step 1 I'm using Express JS version 4 generated via express-generator, so the starting script is not app.js, but /bin/www. So following the instruction in the article below: https://www.plesk.com/blog/product-technology/node-js-plesk-onyx/ I created a new entry file called service.js. The content is simple as follow: const app = require('./app');\nconst http = require('http');\n\nhttp.createServer(app).listen(process.env.PORT); Step 2 In Plesk under Websites & Domains > YOUR_WEBSITE > Node.js > Application StartUp File, change it from app.js to server.js. Step 3 Ensure that Document Root and Application Root are the same. Unlike other hosting in which Document Root path = Application Root path + /public. Step 4 Add the following into the web.config under \u003Csystem.webserver> tag, so the Express routing works. The above is enough in my case. I don't have to add  and/or other suggested tags. Step 5 (Optional) In my case, I have to click the NPM install button in step 2 to install dependencies. Also, you might need to restart the dedicated application pool or disable/enable Node.js. In my case, I didn't have to do that. Other links that helped me figured this thing out:\nhttps://www.a2hosting.co.id/kb/developer-corner/making-a-simple-node.js-application-in-plesk-for-windowshttps://support.plesk.com/hc/en-us/articles/360010589619-Node-js-application-subpath-shows-error-404-after-being-deployed-in-Pleskhttps://talk.plesk.com/threads/use-nodejs-and-problem-with-express-routing.343510/",{"id":647,"title":648,"titles":649,"content":650,"level":9},"/2026/01/03-error-with-no-exception-thrown-when-transferring-data-from-amazon-elasticsearch-service-to-amazon-documentdb","03 Error With No Exception Thrown When Transferring Data From Amazon Elasticsearch Service To Amazon DocumentDB",[],"Error with No Exception Thrown When Transferring Data from Amazon Elasticsearch Service to Amazon DocumentDB This is a repost from my old blog. First posted in 1/10/2021. We all wish our application performs as fast as possible and to do that sometimes we need to slow down. I have a project in which I have to get data from Amazon Elasticsearch, process the data and save the result into Amazon DocumentDB. I processed the data asynchronously so my processing application performed really fast. Since the result accuracy is important, I deleted the result and rerun the process just to make sure the same input will produce the same result. However, the results are different and no error nor any exception is thrown. After few hours of troubleshooting, I noticed that the data were not immediately available right after inserting them into DocumentDB. Since DocumentDB separate storage and compute, it took a bit of time to store the data and make them available. In my code, I need to immediately queried the inserted data. That means, sometimes, it saved the data fast enough that the data are available and sometimes they are not. So my solution is putting a slight delay between insert and query code and I managed to get consistent result.",{"id":652,"title":653,"titles":654,"content":655,"level":9},"/2026/01/04-userprofile-environment-variable-resolves-to-systemprofile-via-aws-systems-manager","04 USERPROFILE Environment Variable Resolves To Systemprofile Via AWS Systems Manager",[],"USERPROFILE Environment Variable Resolves to C:\\windows\\system32\\config\\systemprofile via AWS Systems Manager This is a repost from my old blog. First posted in 2/15/2021. Context is important which is why different environment can and will produce different values. This time it happened when I ran a PowerShell script through AWS Systems Manager (SSM). I intended to download a file reliably to Downloads directory through PowerShell script and AWS Systems Manager. At first, it seems straight forward, SSM Agent usually runs as ssm-user with administrator privilege. And USERPROFILE environment variable usually resolves to C:\\Users\\\u003Cusername>, well, at least locally. So, $env:USERPROFILE\\Downloads should work as intended. But it isn't so in my particular case. Instead, it resolves to C:\\windows\\system32\\config\\systemprofile\\Downloads which of course doesn't exist and failed. I also tried using $HOME and it resolves to the same path as $env:USERPROFILE. Reading online, there are indicators that it happened on some machines and not the others. And also, this behavior has been around for a while. Some solutions online suggest tweaking the registry but in my case, I'd rather not do that which might complicate the issue further. And some solutions suggest using the Public user folder and another option is to use ProgramData folder. Both options are not very clear for my use case. In the end, I decided to use and create a custom directory if it doesn't exist using the following script: $DownloadDirectory=\"C:\\temp\"\nif (!(Test-Path $DownloadDirectory)) {\n    New-Item -ItemType directory -Path $DownloadDirectory\n} Of course, it will fail if somehow the SSM agent doesn't have permission to create a directory, but in my case, this is acceptable.",{"id":657,"title":658,"titles":659,"content":660,"level":9},"/2026/01/05-vb.net-property-is-of-unsupported-type","05 VBNET Property Is Of Unsupported Type",[],"VB.NET Property is of Unsupported Type This is a repost from my old blog. First posted in 2/15/2021. Backward compatibility is hard and there is a saying \"The only constant is change\". The error message this time makes me scratch my head for an hour or so. I updated the CsvHelper package in one of my applications to 23.0.0 and immediately notice errors. Looking at the change log (https://joshclose.github.io/CsvHelper/change-log) and indeed there is a breaking change. I'm aware of the parameter change to a struct as specified in the change log and made the required change. For somewhat reason, Visual Studio didn't like the configuration part, for example the PrepareHeaderForMatch delegate, in which it can't access the property of the struct argument. The error message says: Property 'CsvHelper.PrepareHeaderForMatchArgs.Header' is of unsupported type. This happens on Visual Studio 2017. So, I visited the GitHub repository: https://github.com/JoshClose/CsvHelper/blob/master/src/CsvHelper/Delegates/PrepareHeaderForMatch.cs and noticed the following code: public string Header { get; init; } After searching online, seems like the 'init' setter is the issue. It is supported in VB 16.9 which is immediately available in Visual Studio 2019. https://docs.microsoft.com/en-us/dotnet/visual-basic/whats-new/#visual-basic-169 When I opened the code in Visual Studio 2019, the error went away. So due to time constraint, I switch to VS 2019 for that particular application.",{"id":662,"title":663,"titles":664,"content":665,"level":9},"/2026/01/06-retain-web.config-transformation-files-in-azure-devops","06 Retain WebConfig Transformation Files In Azure DevOps",[],"Retain Web.Config Transformation Files in Azure DevOps This is a repost from my old blog. First posted in 2/15/2021. Documentation is never enough and it will never be able to keep up with the change. The only way to really find answer to a problem is to experiment. I have a simple task. Keep the web.config transformation files during build pipeline in Azure DevOps so I can use them to transform the web.config during release pipeline to customize by environment. By transformation files, I mean files such as web.Release.config. I had it working by adding a copy task in Azure DevOps but it was just a workaround, so I'm trying to find a more elegant way on doing the same thing. At first, I only set the Build Action of each transformation file to Content. It is supposed to be included during deployment. However, after build is done, I noticed the transformation files were discarded and thus not included. After few trial and error, the steps that work for me are: Setting the Build Action to Content for each transformation fileRemove \u003CDependentUpon> tag of each transformation file in project file The following thread triggered my removal of \u003CDependentUpon> tag\nhttps://github.com/microsoft/azure-pipelines-tasks/issues/4372#issuecomment-303298798 Update Feb 16, 2021 My transformation task threw a NullReferenceException. It happened because during build, there was a transformation that took place and removed the tag that supposedly exists. To fix this, I have to disable the transformation during build and I manage to do that by providing the following MSBuild argument: /p:TransformWebConfigEnabled=False In my case, I built a .NET Framework app using VS2017. There are cases online which the tag above doesn't work and it might not work on .NET Core app. Some people manage to suppress transformation using the following MSBuild argument which sadly didn't work for me: /p:IsTransformWebConfigDisabled=True",{"id":667,"title":668,"titles":669,"content":670,"level":9},"/2026/01/07-nullreferenceexception-on-vb.net-anonymous-type","07 NullReferenceException On VBNET Anonymous Type",[],"NullReferenceException on VB.NET Anonymous Type This is a repost from my old blog. First posted in 2/17/2021. As much as we talk about decoupling in computer world, it is probably quite impossible to achieve. The best thing we can do is reduce coupling. But my point is actually on how fragile our code is nowadays. Seems like I have to keep relying on workarounds just to keep the application working. I have a working anonymous type and there is no change on that particular line. It looks like the following: Dim theValue = SharedFunction.GetValue() Some changes on the project, however, has nothing to do with that particular line of code. I switched to VS2019 instead of VS2017 and update Nuget packages without touching that code. The project builds successfully. But during runtime, that particular line threw NullReferenceException. At first, I thought it is my shared function, but it worked great when I ran it on Immediate Window. Few other things are the project is using .NET Framework 4.6.2 and the problematic code is nested inside an if statement which is nested inside #If directive. It might have something to do with the way the compiler generates the name of the anonymous type such as the \"caution\" section in the following article, but I didn't pursue any further. https://docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/objects-and-classes/anonymous-types I took the problematic code out from the if statement and #If directive and it works fine. So my code goes from: #If Not Debug Then\n  If condition = true Then\n    Dim theValue = SharedFunction.GetValue()\n    DoSomething(theValue)\n  End If\n#End If becomes: Dim theValue = SharedFunction.GetValue()\n\n#If Not Debug Then\n  If condition = true Then\n    DoSomething(theValue)\n  End If\n#End If",{"id":672,"title":673,"titles":674,"content":675,"level":9},"/2026/01/08-app.config-file-transformation-in-azure-devops","08 AppConfig File Transformation In Azure DevOps",[],"App.config File Transformation in Azure DevOps This is a repost from my old blog. First posted in 2/17/2021. Utilizing the right tool for the right job makes life easier. That also means we have to keep learning and exploring new tools. For some if not many of us, we probably wish we can do config file transformation on app.config for various environment just like web.config. To do that locally, we can use something like SlowCheetah, but in my case, I want to do it before deploying to the server. So I use Azure DevOps File Transform task. Learning from my experience with web.config, I added couple of transformation file such as App.Prod.config. It took couple of tries for me to get it working right and the following are the steps I take: Add transformation file and set its Copy to Output Directory property to Always.Since App.config is usually renamed to \u003CApplicationName>.exe.config and File transform task requires config files to follow certain naming pattern, for example, App.\u003Cenvironment>.config can only be used to transform App.config, I set Copy to Output Directory property of App.config file to Always. Another option is probably to change the transformation file name but it doesn't look nice locally.Set the transformation rules of the File Transform task to: -transform **/App.Prod.config -xml **/App.config -result \u003Cappname>.exe.config Reference https://stackoverflow.com/questions/57498234/file-transform-task-fails-to-transform-xml-configurations-on-zipped-package",{"id":677,"title":678,"titles":679,"content":680,"level":9},"/2026/01/09-aws-ec2-can't-reach-ec2-metadata-service-after-subnetchange","09 AWS EC2 Can't Reach EC2 Metadata Service After Subnetchange",[],"AWS EC2 Can't Reach EC2 Metadata Service After Subnet Change This is a repost from my old blog. First posted in 3/8/2021. Just another black box day. I had to move an EC2 instance to a different subnet, so I created an AMI out of it and launch it on a different subnet. Everything went well and it has no issue reaching the internet, but apparently not everything went well. The AWS agents such as SSM agent and CodeDeploy agent in the instance stop working. After checking the logs, they can't access the EC2 metadata. Since this is a Windows Server 2019 instance, it also shows that it is not activated, which is strange. On the following article, I found out that my issue was due to the \"Gateway Address doesn't match that of the current subnet\". https://aws.amazon.com/premiumsupport/knowledge-center/waiting-for-metadata/ Running the suggested command fixed the issue: Import-Module c:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Module\\Ec2Launch.psm1 ; Add-Routes",{"id":682,"title":683,"titles":684,"content":685,"level":9},"/2026/01/10-azure-invalidtemplate-error-the-language-expression-property-array-index-'1'-is-out-of-bounds.","10 Azure InvalidTemplate Error The Language Expression Property Array Index '1' Is Out Of Bounds",[],"Azure InvalidTemplate Error: The language expression property array index '1' is out of bounds. This is a repost from my old blog. First posted in 6/20/2024. I'm trying to spin up a Redis Cache in Azure and placed it in my Virtual Network. However, it threw an error and the error message was not helping but I eventually figured it out. Here's my Bicep template which threw an error: resource cacheSubnet 'Microsoft.Network/virtualNetworks/subnets@2023-11-01' existing = {\n  name: 'mySubnet'\n}\n\nresource redis 'Microsoft.Cache/redis@2023-08-01' = {\n  name: 'myRedis'\n  location: resourceGroup().location\n  properties: {\n    enableNonSslPort: true\n    publicNetworkAccess: 'Disabled'\n    sku: {\n      capacity: 1\n      family: 'P'\n      name: 'Premium'\n    }\n  subnetId: cacheSubnet.id\n} Apparently, I needed the parent field on the subnet reference, so I ended with the following template which successfully launched my Redis cache. resource vNet 'Microsoft.Network/virtualNetworks@2023-11-01' existing = {\n  name: 'myVNet'\n}\n\nresource cacheSubnet 'Microsoft.Network/virtualNetworks/subnets@2023-11-01' existing = {\n  name: 'mySubnet'\n  parent: vNet\n}\n\nresource redis 'Microsoft.Cache/redis@2023-08-01' = {\n  name: 'myRedis'\n  location: resourceGroup().location\n  properties: {\n    enableNonSslPort: true\n    publicNetworkAccess: 'Disabled'\n    sku: {\n      capacity: 1\n      family: 'P'\n      name: 'Premium'\n    }\n  subnetId: cacheSubnet.id\n}",{"id":687,"title":688,"titles":689,"content":690,"level":9},"/2026/01/11-copying-files-with-certain-file-extensions-using-azcopy-task-in-azure-devops","11 Copying Files With Certain File Extensions Using AzCopy Task In Azure DevOps",[],"Copying Files with Certain File Extensions using AzCopy Task in Azure DevOps This is a repost from my old blog. First posted in 6/20/2024. I was trying to copy only certain files within a directory to Azure Storage Account instead of the whole directory content. The files that I tried to copy are those ends with .zip, .tag.gz, and .py. AzCopy support wildcard on the source, so I would like to do something like this: azcopy copy C:\\{directory}\\[*.zip|*.tar.gz|*.py] ... I found out later that there's --include-pattern option, so this works: azcopy copy C:\\{directory}\\* --include-pattern *.zip;*.tar.gz;*.py",{"id":692,"title":693,"titles":694,"content":695,"level":9},"/2026/01/12-can't-find-synology-nas-in-my-network","12 Can't Find Synology NAS In My Network",[],"Can't Find Synology NAS in my Network This is a repost from my old blog. First posted in 6/21/2024. One day, mapped drives to my NAS stopped working and the NAS itself just disappeared from my network. My first thought was either the NAS broke or my router. But my router seems fine, so I first checked my NAS by directly connecting to it via ethernet cable to my laptop (using USB converter). I also downloaded the Synology Assistant software which helps a lot in finding whether there's Synology NAS in the network. The Synology Assistant can be found in Synology Download Center under Desktop Utilities. Synology NAS model required to find the right software. https://www.synology.com/en-us/support/download My NAS was working well, so I decided to reboot my router. After the router reboots, I detached the NAS from the laptop and connect it back to the router. And my NAS is discoverable in the network again. However, it happened again when I transferred a large amount of files. Probably it overwhelms the router as I use an old Netgear Wifi 5 router. There's also a possibility that firewall on the laptop interferes in discovering the NAS, but in my case, since I was able to find it before the issue and no configuration changed since then, it is not a point of concern. But just in case, I did check the firewall configuration as well and it was configured correctly.",{"id":697,"title":698,"titles":699,"content":700,"level":9},"/2026/01/13-jetpack-compose-infinite-recomposition-loop","13 Jetpack Compose Infinite Recomposition Loop",[],"Jetpack Compose Infinite Recomposition Loop This is a repost from my old blog. First posted in 8/14/2024. I finally got some time to get back to mobile development after many years. And Android has a new way to create an app with Jetpack Compose. At a glance, it is amazing, I managed to create a complex app much faster than using XAML, yep, you read that right, that's how I used to do it. All is well until I encountered infinite loop when trying to remove item in a mutableList displayed using LazyColumn on a button click. Basically, the button click somehow causing a recomposition and then the recomposition retrigger the button click event again and again. But it only happened when I remove an item, adding an item is fine. Here's the example of initial code: data class Pet(var timestamp: Instant, var name: String)\n  \n@Composable\nfun Screen() {\n    val pets = remember { mutableStateListOf\u003CPet>() }\n  \n    fun addPet() {\n        pets.add(Pet(Clock.System.now(), \"Pochi\"))\n        if (pets.count() > 5) {\n             pets.removeAt(0)\n        }\n    }\n  \n    addPet()\n    \n    Surface {\n        LazyColumn {\n            items(items = pets,\n                  key = { it.timestamp.toEpochMilliseconds() }) {\n                Text(text = it.name)\n            }\n        }\n        Button(onClick = { addPet() }) {\n             Text(text = \"Add\")\n        }\n    }\n} I did some searching, even using ChatGPT, but what helps me understand is this article: https://developer.android.com/develop/ui/compose/performance/bestpractices#avoid-backwards Apparently, I accidentally did a backward write. I did a small experiment and the following code doesn't cause recomposition loop: data class Pet(var timestamp: Instant, var name: String)\n  \n@Composable\nfun Screen() {\n    val pets = remember { mutableStateListOf\u003CPet>() }\n  \n    fun addPet() {\n        pets.add(Pet(Clock.System.now(), \"Pochi\"))\n    }\n  \n    addPet()\n    \n    Surface {\n        LazyColumn {\n            items(items = pets,\n                  key = { it.timestamp.toEpochMilliseconds() }) {\n                Text(text = it.name)\n            }\n        }\n        Button(onClick = { \n             addPet() \n             \n             // Moved from addPet()\n             if (pets.count() > 5) {\n                 pets.removeAt(0)\n             }\n             \n             }) {\n             Text(text = \"Add\")\n        }\n    }\n} Both snippets look very similar especially on what the button click will do. However, on the first snippet, pets.count() causes state read due to addPet() call and thus button onClick will cause a backwards write with pets.add(). Now the question is won't moving the pets.count() to within button onClick cause backwards write as well? The answer is, it won't, because the recomposition scope is different. This article will be helpful in understanding more on the recomposition scope. The key is \"Deferring state reads will ensure that Compose re-runs the minimum possible code on recomposition\" https://developer.android.com/develop/ui/compose/performance/bestpractices#defer-reads By moving the pets.count() to the onClick, we reduce the recomposition scope to only the button and because of that, the recomposition doesn't try to recompose everything including the button and its onClick which can cause recomposition loop because onClick will be triggered infinitely.",{"id":702,"title":703,"titles":704,"content":705,"level":9},"/2026/01/14-reviving-samsung-galaxy-note-4","14 Reviving Samsung Galaxy Note 4",[],"Reviving Samsung Galaxy Note 4 This is a repost from my old blog. First posted in 8/15/2024. I have an old Samsung Galaxy Note 4 that was not turning on for a long time now. Out of curiosity, I read about it came back to life by putting it in the freezer, so I gave it a try. I took out the battery, put the phone in a ziploc bag and put in the freezer for at least 8 hours (so I can sleep or work through it). I also make sure the battery is charged separately since I have a battery charger. After 8 hours, I take it out, put the battery in, and surprised that it turns on. However, it won't turn on anymore after I turn it off, so I placed it into the freezer the second time and it works again. My guess is the freezer probably takes some humidity out from the components and allows it to work better.",{"id":707,"title":708,"titles":709,"content":710,"level":9},"/2026/01/15-cheap-way-to-receive-email-on-custom-domain","15 Cheap Way To Receive Email On Custom Domain",[],"Cheap Way to Receive Email on Custom Domain This is a repost from my old blog. First posted in 8/15/2024. I was looking for a budget friendly way to receive email on my custom domain. So, let say, I own example.com and I want to receive email on receive@example.com. As I did my research, I found various way on doing it: Just forward it. My domain name vendor apparently comes with free email forwarder, so I forward it to my non-custom domain email such as gmail.Just forward it (DIY). This is also a very cheap alternative and low cost. One way is to forward it through AWS SES. One such project is: https://github.com/arithmetric/aws-lambda-ses-forwarderReceive it through hosting. I thought about this especially when I already paid for hosting service, usually it comes with mail server for free. Of course, we can always subscribe to some email service, but it will cost more but it has more features too.",{"id":712,"title":713,"titles":714,"content":715,"level":9},"/2026/01/16-outlook-reminder-doesn't-dismiss-old-meetings","16 Outlook Reminder Doesn't Dismiss Old Meetings",[],"Outlook Reminder doesn't Dismiss Old Meetings This is a repost from my old blog. First posted in 8/15/2024. My outlook somehow keeps reminding me on old meetings that occurred weeks before. Dismissing all or each one doesn't work. It keeps coming back. I tried the suggestion to remove cache, clear reminders and none works. Finally, the only one that works for me is to open up the details of each one of the old meetings from the reminder and then dismiss them. They never showed up in the reminder ever since.",{"id":717,"title":718,"titles":719,"content":720,"level":9},"/2026/01/17-sl-command-in-linux","17 SL Command In Linux",[],"SL Command in Linux This is a repost from my old blog. First posted in 8/20/2024. Most of the time we have to type fast, especially in today's world where speed is life. So, we are bound to mistype. In Linux, one of the commonly used command is \"ls\", so to \"train\" user to correct that, an \"sl\" command is created. SL stands for Steam Locomotive. Check it out in your Linux distro, search, install, and run the command and it will show a moving locomotive.",{"id":722,"title":723,"titles":724,"content":725,"level":9},"/2026/01/18-cython-compile-error-on-python-3.12-on-windows-10","18 Cython Compile Error On Python 312 On Windows 10",[],"Cython Compile Error on Python 3.12 on Windows 10 This is a repost from my old blog. First posted in 8/22/2024. I have Python 3.12 installed on my Windows 10 machine. I tried to install a package using Pip. Apparently, the package contains Cython and needs to be compiled. However, the compilation failed with the following message: Cannot open include file: 'io.h': No such file or directory Ok, not a problem, I just go to Visual Studio Installer and install Desktop development with C++ package. That fixed the first issue. But installing the package still failed. This time the error message is: 'C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\VC\\\\Tools\\\\MSVC\\\\14.41.34120\\\\bin\\\\HostX86\\\\x64\\\\cl.exe' failed with exit code 2 To fix the above, I had to downgrade python to 3.10 and the package is installed properly.",{"id":727,"title":728,"titles":729,"content":730,"level":9},"/2026/01/19-python-package-not-found","19 Python Package Not Found",[],"Python Package not Found This is a repost from my old blog. First posted in 8/22/2024. Ok, this is a rookie issue. I had virtual environment created, activated and the package installed for that virtual environment, but somehow I bumped into this error: Import could not be resolved [Pylance] Turns out to be the interpreter is pointing to the wrong one in my VS code bottom right. Changing it to the one in virtual environment fixed that.",{"id":732,"title":733,"titles":734,"content":735,"level":9},"/2026/01/20-data-transfer-cost-due-to-internal-alb-and-nat-gateway-in-the-same-subnet","20 Data Transfer Cost Due To Internal ALB And NAT Gateway In The Same Subnet",[],"Data Transfer Cost due to Internal ALB and NAT Gateway in the Same Subnet This is a repost from my old blog. First posted in 8/29/2024. This is what I heard from my junior after he moved to a different company. They found an issue with data transfer cost due to internal ALB and NAT Gateway in the same subnet. Apparently, the internal application sends data to the ALB and it's being processed by the NAT gateway as well. I'm not exactly sure how it works, but it was a bad networking. They removed the NAT gateway and just let the ALB managed the traffic and save cost.",{"id":737,"title":738,"titles":739,"content":740,"level":9},"/2026/01/21-use-multiple-git-accounts-on-one-computer","21 Use Multiple Git Accounts On One Computer",[],"Use Multiple Git Accounts on One Computer This is a repost from my old blog. First posted in 9/2/2024. I was looking for a way to use two git accounts in a single machine. Apparently, there are multiple ways to do that: Use different protocols for different accounts. One account can use HTTP, another account uses SSH.Use different SSH keys. One per account.Use HTTP and PAT. This might be GitHub specific but per my experience with PAT in Azure DevOps, this is not feasible as PAT has expiration and needs to be renewed. https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-your-personal-account/managing-multiple-accounts I ended up using different protocols since that will save me effort in configuring one of the accounts. First, I need to create an ssh key. https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#generating-a-new-ssh-key. Since I'm in Windows, I can use Git Bash. Launch Git BashRun: ssh-keygen -t ed25519 -C \"your_email@example.com\"If prompted to enter passphrase, make sure you note it somewhere (I saved mine in password manager).If you need to change the passphrase, follow the steps in this link: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/working-with-ssh-key-passphrases#adding-or-changing-a-passphraseAlso note the location of the generated key. In my case, it is ~/.ssh/id_ed25519 or %USERPROFILE%/.ssh/id_ed25519\nOnce the key is generated, we need to add it to ssh_agent. This way, local git will know to use the key. https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#adding-your-ssh-key-to-the-ssh-agent Launch PowerShell in elevated admin mode.Make sure the ssh-agent is running:\nGet-Service -Name ssh-agent | Set-Service -StartupType ManualStart-Service ssh-agentLaunch a separate PowerShell terminal without admin mode.Run the following command: ssh-add c:/Users/{your_user}/.ssh/id_ed25519 After that, we need to add the key to GitHub: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account#adding-a-new-ssh-key-to-your-account. In GitHub, under your profile menu on the top right of the page, select Settings.Then on the left menu, select SSH and GPG keys.Add a new key and use a descriptive name it under Title box. In my case, I use the name of my machine since the key resides in my machine.Go to the key location. In my case: %USERPROFILE%/.sshCopy the content of the {key}.pub (note the .pub extension for public key, don't copy the one without it as it is the private key). In my case, it is id_ed25519.pubPaste the content of the key to GitHub and click Add SSH key. Then I added ssh config as follow: In the key location, create file with name config. In my case, the file path will be: %USERPROFILE%/.ssh/configFor the content, it will be:\nHost github.com\nHostName github.com\nUser git\nIdentityFile ~/.ssh/id_ed25519If there are multiple ssh keys for multiple accounts, it will contain multiple entries where the Host can be different while the HostName can stay the same. Afterwards, I had to configure global .gitconfig in %USERPROFILE% by adding the includeIf section. This is so that I can use different user name and email for different accounts. The content looks like the following: [user]\n   name = {username}\n   email = {email}\n\n[includeIf \"gitdir:~/{other_folder}/\"]\n    path = ~/{other_folder}/.gitconfig As you noticed, the includeIf will need a separate directory with its own .gitconfig file. It works for me as I have a separate directory for repositories that use a separate git account. The content of the other .gitconfig file will be: [user]\n   name = {other_username}\n   email = {other_email} By now, it is pretty much done. If I do a git clone on ssh path, it will prompt for my passphrase and it will work. git clone git@github.com:{account}/{repo}.git But in my case, I have existing repositories that needs to be updated to use ssh, so for each repo, I had to run: git remote set-url origin git@github.com:{account}/{repo}.git Thus, that's the end of my multi accounts journey.",{"id":742,"title":743,"titles":744,"content":745,"level":9},"/2026/01/22-multiple-backgroundservice-or-ihostedservices-but-only-one-works","22 Multiple BackgroundService Or IHostedServices But Only One Works",[],"Multiple BackgroundService or IHostedServices but Only One Works This is a repost from my old blog. First posted in 9/2/2024. In my worker app, I attempted to add multiple hosted services as follow: builder.Services\n    .addSingleton(HostedService1)\n    .addSingleton(HostedService2)\n    .addSingleton(HostedService3); All the hosted services are added, but when the application run, only 1 is executing. Thanks to Stephen Cleary, apparently issue with synchronous call. https://blog.stephencleary.com/2020/05/backgroundservice-gotcha-startup.html. I ended up using Task.Run for code that executes for a long time. Inside the ExecuteAsync: await Task.Run(async () => await LongRunningProcess());",{"id":747,"title":748,"titles":749,"content":750,"level":9},"/2026/01/23-connecting-pod-in-minikube-to-kafka-or-any-services-running-in-docker-desktop","23 Connecting  Pod In Minikube To Kafka Or Any Services Running In Docker Desktop",[],"Connecting Pod in Minikube to Kafka or any Services Running in Docker Desktop This is a repost from my old blog. First posted in 9/3/2024. I'm working on a demo where I need to subscribe my application to Kafka locally in Docker Desktop. I have 3 use cases: Connecting from a different container in Docker desktop, so in the same network as the Kafka container.Connecting from the application running on the host, so outside of Docker desktop for debugging purposes.Connecting from a pod inside Minikube running in Docker Desktop. Same Docker Network On the first case, I actually need to connect AKHQ container to Kafka, my Kafka container env variable for advertised listeners looks like the following: environment:\n    KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092, ... (removed for brevity) Since AKHQ running in Docker desktop as well, it can use kafka:29092. From the Host (my computer) Outside of Docker Network Next is my application that runs outside of Docker desktop, since it won't resolve the kafka host, it has to use the 2nd entry of the advertised listener. In my case, I had to change the port from 9092 to prevent conflict with other Kafka instance, but for it to work, I had to change the port mapping, so the Kafka container configuration looks like the following: ports:\n   - 19092:19092\nenvironment:\n    KAFKA_BROKER_ID: 1\n    KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181\n    KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:19092, ... To prevent conflict, the port mapping on the host and container has to be modified, so my application connects using localhost:19092 From Pod Inside Minikube This one is confusing me, but I found out that kube-dns is installed by default and Minikube provides a convenient hostname. For more details: https://minikube.sigs.k8s.io/docs/handbook/host-access/ host.minikube.internal So updating my configuration a little, I can connect from the pod using host.minikube.internal:19094 ports:\n    - 19092:19092\n    - 19094:19094\nenvironment:\n    KAFKA_BROKER_ID: 1\n    KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181\n    KAFKA_ADVERTISED_LISTENERS: ...,PLAINTEXT_POD://host.minikube.internal:19094\n    KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: ...,PLAINTEXT_POD:PLAINTEXT",{"id":752,"title":753,"titles":754,"content":755,"level":9},"/2026/01/24-rename-pyspark-result-file","24 Rename PySpark Result File",[],"Rename PySpark Result File This is a repost from my old blog. First posted in 9/5/2024. Due to the distributed nature of Apache Spark, when writing result, we can't specify name for the result file. This makes the result file hard to predict which I need for my process orchestration. In my case, I need to write the result to S3 and I finally found a way to do this within a reasonable amount of time by utilizing aws wrangler, Panda, and optionally Arrow. I basically feed Spark dataframe to aws wrangler and have it write to S3 using a specific name. Here's link to my sample: https://github.com/nik-yo/PySparkFilename",{"id":757,"title":758,"titles":759,"content":760,"level":9},"/2026/01/25-delete-git-branches-by-days-ago","25 Delete Git Branches By Days Ago",[],"Delete Git Branches by Days Ago This is a repost from my old blog. First posted in 9/5/2024. Often my branches piled up and I need a way to automatically delete them based on how many days ago. I can't find an easy way online, so I ended up writing my own scripts in PowerShell and Bash. In this repo, I have the script to clean up branches that are 90 days or older based on last committed date. Repo: https://github.com/nik-yo/DeleteGitBranchesByDaysAgo",{"id":762,"title":763,"titles":764,"content":765,"level":9},"/2026/01/26-wordpress-create-block-theme-plugin","26 WordPress Create Block Theme Plugin",[],"WordPress Create Block Theme Plugin This is a repost from my old blog. First posted in 9/12/2024. I'm working on a custom WordPress theme and I saw a very helpful plugin called \"Create Block Theme\" which is supposed to help developer create the theme. So, for starting, I tried to edit one of my templates, but when I hit \"Save Changes\" under \"Save Changes to Theme\" section, I expected it to overwrite my template html file, but it didn't. I was checking permissions and potential bugs, but seems like everything is good. After playing around a little, apparently, I need to hit \"Save\" first, so it records the customization in the database and then click the \"Save Changes to Theme\" will use the value from the database and modified the html file itself.",{"id":767,"title":768,"titles":769,"content":770,"level":9},"/2026/01/27-background-image-on-wordpress-editor","27 Background Image On WordPress Editor",[],"Background Image on WordPress Editor This is a repost from my old blog. First posted in 9/12/2024. I realized that I don't have the Layout option under Styles menu in the Editor. I found out later that I have a bare minimum theme.json. And adding appearanceTools: true field cause it to show up. My theme.json became: {\n    \"version\": 3,\n    \"$schema\": \"https://schemas.wp.org/wp/6.6/theme.json\",\n    \"settings\": {\n        \"appearanceTools\": true\n    }   \n}",{"id":772,"title":773,"titles":774,"content":775,"level":9},"/2026/01/28-swagger-.net-8-error","28 Swagger NET 8 Error",[],"Swagger .NET 8 Error This is a repost from my old blog. First posted in 9/13/2024. Swashbuckle CLI was able to output schema of my API before, but this time, it throws this error message: System.InvalidOperationException: A type named 'StartupProduction' or 'Startup' could not be found in assembly I used top level statement with minimal API on .NET 8 and nothing is changed on that, so I was not able to find anything to do with Startup type. After I investigate further by commenting line by line, I found out that the issue is on my switch statement. So it looks like the following: return config.Section?.Key switch\n{\n  Value1 => services.AddSingleton\u003CHandler1>(),\n  Value2 => services.AddSingleton\u003CHandler2>(),\n  _ => throw new InvalidOperationException();\n} Problem is the Section is pulled from appsettings.json and when the CLI runs, it doesn't have value, so it never returned the services object. Changing the above to the following fixed the issue: return config.Section == null ? services : config.Section.Key switch\n{\n  Value1 => services.AddSingleton\u003CHandler1>(),\n  Value2 => services.AddSingleton\u003CHandler2>(),\n  _ => throw new InvalidOperationException();\n}",{"id":777,"title":778,"titles":779,"content":780,"level":9},"/2026/01/29-jwt-is-not-well-formed-in-asp.net-web-api-jwtbearer-.net-8","29 JWT Is Not Well Formed In ASPNET Web API JwtBearer NET 8",[],"JWT is not well formed in ASP.NET Web API JwtBearer .NET 8 This is a repost from my old blog. First posted in 9/25/2024. It never caused a problem for me to implement JwtBearer token validator, but this time it is really take my time to troubleshoot what's going on. Long story short, there's a breaking change going to .NET 8 and on top of that, the default package version doesn't solve the issue. Here's how I implement my service: services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)\n    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => ...removed for brevity);\nservices.AddAuthorization();\n\n...\n\napp.UseAuthentication();\napp.UseAuthorization(); But checking the bearer token, it was a completely valid token. I retrieved the token using a quick custom middleware. app.Use(async (context, next) =>\n{\n    await next.Invoke();\n    Debug.WriteLine(context.Request.Headers.Authorization);\n});\n\napp.UseAuthentication();\n\n... Then I validate the token in https://jwt.io. The error that I received contains: IDX14100: JWT is not well formed, there are no dots (.). The token needs to be in JWS or JWE Compact Serialization Format. On top of that, the browser response header has the following header: WWW-Authenticate: Bearer error=\"invalid_token\" Searching online, the most helpful hint is probably this thread: https://github.com/dotnet/aspnetcore/issues/52075 There are some suggestions in there, but the one that finally solves my problem is the fact that the following package version doesn't work: Microsoft.IdentityModel.Protocols.OpenIdConnect 7.1.2 It was a transitive package and I have to upgrade it by installing the latest version, as of this time 8.1.0. And that fixed my issue without any code change.",{"id":782,"title":783,"titles":784,"content":785,"level":9},"/2026/01/30-asp.net-application-crashed-without-error-message","30 ASPNET Application Crashed Without Error Message",[],"ASP.NET Application Crashed without Error Message This is a repost from my old blog. First posted in 9/27/2024. I encountered a strange error with ASP.NET Web API application. It runs fine locally, but when we deployed to Kubernetes cluster, it crashed as soon as it starts. And no error message was thrown. So, I pulled the application to my local and it crashed as well no matter how I run it, dotnet cli, Docker Desktop, Visual Studio debug. The only one that runs fine is the version from the repo. At this point, there are only two possibilities, either the environment is the issue or the application is the issue, so I decided to deploy it to a different environment and it's still not working, so it must be something with the application. Since it is the application, I tried to change the log level to Trace to get more information but no new error message that provides a hint on what's going on. Memory dump didn't work as the collector didn't have enough time to collect before the application crashed. At the end, I decided to approach this the hard way. So, in my local, there are two versions. One is freshly pulled from the environment which is not working. The other one is from the source control repository which works. The most obvious difference between the two is the configuration, in this case, we use appsettings.json. But it looks fine. My next guess is one of the dlls is probably the issue, so I started to try to break the one that works by substituting the file with different size one-by-one from the broken application. However, all the suspicious dlls don't seem to cause a problem. As I run out of dlls, I start substituting the appsettings.json. It has different size, why not. And that's when the working version stops working. To zero in on the cause, I start removing fields in the appsettings.json file to see if I can make it to work. Finally, there's one field that's the cause. It looks similar to the following: {\n  \"Settings\": {\n     \"Key\": \"Value\"\n  }\n} Looking into the code that read that field, it is immediately obvious. In ASP.NET, there's a way to deserialize the field to an object and we can use enum for the value. Let say: {\n  \"Settings\": {\n     \"Pet\": \"Dog\"\n  }\n} The code to retrieve the setting will be similar to the following: public enum Pets {Cat, Fish}\n\npublic class TheSettings {\n  public Pets Pet { get; set; }\n}\n\nTheSettings settings = configuration.GetSection(\"Settings\").Get\u003CTheSettings>(); All looks great, except, the enum doesn't have the value specified in the appsettings.json file. In the example above, Dog is not an enum of Pets.  So, when it tries to deserialize the config, it breaks and somehow it didn't throw an error. Fix either the enum or the value in the field in appsettings.json finally fixed the issue and the application can start without crashing.",{"id":787,"title":788,"titles":789,"content":790,"level":9},"/2026/01/31-aws-cognito-error-on-sign-up","31 AWS Cognito Error On Sign Up",[],"AWS Cognito Error on Sign Up This is a repost from my old blog. First posted in 9/29/2024. I was exploring AWS Cognito for authentication. It works great, but I got the following error message after I tested the sign up process: An error was encountered with the requested page. I found out later that I misunderstood the AutoVerifiedAttributes field in my CloudFormation. I thought it would mark an email or phone number as verified without actually verifying them. Apparently, it means it will try to verify either email or phone number. So, when I set it to email, it sent a verification email and the sign up process went without error.",{"id":792,"title":793,"titles":794,"content":795,"level":9},"/2026/02/01-logitech-mouse-and-keyboard-do-not-work","01 Logitech Mouse And Keyboard Do Not Work",[],"Logitech Mouse and Keyboard do not Work This is a repost from my old blog. First posted in 10/4/2024. I found a Logitech mouse and keyboard combo on clearance. The model is MK470 and it looks returned. For the steep discounted price, I decided to give a try. Expectedly, it didn't work, so that starts my troubleshooting. Battery is fine, no on/off button on keyboard, both mouse and keyboard are not working, no sign of damage, dongle is properly inserted into the USB port. Short while later, I found that Logitech has a neat Connection Utility software. I downloaded it and ran it twice, once to reconnect the mouse and once for the keyboard. My guess is the frequency and channel somehow was not lining up between the mouse and keyboard and the dongle. The previous buyer probably returned it because they were not working. But the connection is finally restored.",{"id":797,"title":798,"titles":799,"content":800,"level":9},"/2026/02/02-timezoneinfo-and-alpine","02 TimeZoneInfo And Alpine",[],"TimeZoneInfo and Alpine I was helping a co-worker fixing a TimeZoneNotFoundException error. The error was actually on TimeZoneInfo.FindSystemTimeZoneById(). Per my experience, it was based on timezone installed in the machine. I was told that using Windows or Linux Id both throw an exception. I found out that the application Docker base image is based on Alpine Linux. A quick search reveals that Alpine Linux doesn't have tzdata package installed. Added the following line in the Dockerfile fixed the error. RUN apk add --no-cache tzdata",{"id":802,"title":803,"titles":804,"content":805,"level":9},"/2026/02/03-http-server-vs-serve-run-from-dist-directory","03 Http Server Vs Serve Run From Dist Directory",[],"Http-server vs Serve: Run from dist directory My team had to test an MFE repository locally. However, it's meant to be run from \"dist\" folder after build and package steps. I saw some recommendation online to use http-server (https://www.npmjs.com/package/http-server). So, I gave it a try and I managed to get it running really quick. And I quickly found issues too. After installation, I just need to run: http-server dist Accessing from the client, browser threw CORS error. Fixing that was quick with --cors option. http-server --cors dist Then, for somewhat reason, it didn't send Content-Type response header, so the client got it wrong when parsing the js file. I had to add -e js to set the default Content-Type to application/javascript. http-server -e js --cors dist It's not too bad, but I'm looking for a little simpler solution and I had good experience with serve (https://www.npmjs.com/package/serve). With serve, after installation, I just need to run: serve dist Same case with http-server, I need to enable CORS by adding --cors option, so it becomes: serve --cors dist However, it automatically sends the right Content-Type response header.",{"id":807,"title":808,"titles":809,"content":810,"level":9},"/2026/02/04-run-dotnet-application-on-linux-locally-on-windows-machine","04 Run Dotnet Application On Linux Locally On Windows Machine",[],"Run .NET Application on Linux locally on Windows Machine Back to the TimeZoneInfo. I need to test that TimeZoneInfo.FindSystemTimeZoneById() works on Alpine Linux locally. However, I can only use Windows machine. So, couple of options: WSLDocker Container We can use VM too, but it adds more work for a quick test. I decided to use docker since we already have Dockerfile. Besides, using WSL, we need to configure the networking and have to install .NET SDK which will take more time. To manage the docker container, we are allowed to use Podman. I'm more used to Docker Desktop, but it works and learning curves are not too steep. Another option is Rancher Desktop. However, I don't want to keep running cli command to build and run the containers, so I decided to use .NET Aspire. It requires a small configuration to integrate with Podman. Under launchSettings.json, I added the environment variable below. This way, I don't have to configure machine-wide environment variable. ...\n\n\"ASPIRE_CONTAINER_RUNTIME\": \"podman\"\n\n... Then I create a custom Dockerfile with just enough steps for local build. In AppHost.cs, I added the following code to use the custom Dockerfile: var pathToProject = \"C:/path/to/project\";\n\nbuilder.AddDockerfile(\"api\", pathToProject, \"Dockerfile.local\")\n  .WithBuildArg(\"PWD\", $\"{pathToProject}/.\")\n  .WithEnvironment(\"ASPNETCORE_ENVIRONMENT\", \"Development\")\n  .WithHttpEndpoint(80,8080);\n\n... I exposed a build arg in my Dockerfile, so when Aspire builds the container, it doesn't attempt to use Aspire's directory as the application directory such as: ARG PWD=\".\"\n\n...\n\nCOPY ${PWD} .\n\n... Finally, I simply ran Aspire and it handles building and running the container in a single click.",{"id":812,"title":813,"titles":814,"content":815,"level":9},"/2026/02/05-interrupted-system-call-in-docker-build","05 Interrupted System Call In Docker Build",[],"Interrupted System Call in Docker Build When I build Docker image locally on my machine, it throws Interrupted System Call error intermittently. The issue is on command similar to the following: RUN wget https://example.com/somefile.ext -P /some/local/directory/ && \\\n    cat /some/local/directory/somefile.ext >> /some/other/directory/targetfile.ext I tried many different command and none worked until I read the documentation on wget where it says that wget runs in the background. Apparently, wget hadn't finished downloading the file when cat ran. When I added a small delay, it works consistently in my local. RUN wget https://example.com/somefile.ext -P /some/local/directory/ && \\\n    sleep 2 && \\\n    cat /some/local/directory/somefile.ext >> /some/other/directory/targetfile.ext",{"id":817,"title":818,"titles":819,"content":820,"level":9},"/2026/02/06-error-when-generating-openapi-documents-missing-required-option-'-project'","06 Error When Generating OpenAPI Documents Missing Required Option '  Project'",[],"Error When Generating OpenAPI Documents: Missing required option '--project' This is a repost from my old blog. First posted in 11/15/2024. After I installed Microsoft.Extensions.ApiDescription.Server package, I encountered the following error message when I attempted to generate OpenAPI documents at build-time on .NET 9. Missing required option '--project'\nThe command \"dotnet \"...\"\" exited with code 1 Apparently, it was due to end slash on my attempt to change the output directory. On my csproj file, I have the following entry: \u003CPropertyGroup>\n  \u003COpenApiDocumentsDirectory>../directory/\u003C/OpenApiDocumentsDirectory>\n\u003C/PropertyGroup> It works correctly after I removed the end slash: \u003CPropertyGroup>\n  \u003COpenApiDocumentsDirectory>../directory\u003C/OpenApiDocumentsDirectory>\n\u003C/PropertyGroup>",{"id":822,"title":823,"titles":824,"content":825,"level":9},"/2026/02/07-sentinel-one-strikes-again-no-internet-connection-uninstall-sentinel-one-agent.","07 Sentinel One Strikes Again No Internet Connection Uninstall Sentinel One Agent",[],"Sentinel One Strikes Again. No internet connection. Uninstall Sentinel One Agent. This is a repost from my old blog. First posted in 11/19/2024. This happened to a co-worker of mine a while back when his test application file was marked as suspicious by Sentinel One antivirus and had his internet on his laptop disabled. Today, it happened to me without any suspicious file. Probably suspicious activity, who knows. On Microsoft Edge, it says \"Hmmm... your Internet access is blocked.\", \"Firewall or antivirus software may have blocked the connection\", and \"ERR_NETWORK_ACCESS_DENIED\". So, I worked with my IT to uninstall the agent, but uninstalling is not without a fight. Here are the steps that I took: Since it is a Windows 11 machine with Bitlocker, I have to first get the Bitlocker key. From command prompt run: manage-bde -protectors -get C:After I verified it is the same key that the IT has, I saved the key outside of the machine.Then go to system configuration by searching for \"sysconfig\" or run msconfig. Under \"boot\" tab, check the \"Safe boot\" option, then click \"Apply\" and then \"OK\". In my case, it alerts about Bitlocker after clicking \"Apply\", so I just agree to it since I already have the key.Restart/reboot the machine and it will run in safe mode.Rename \"C:\\ProgramData\\Sentinel\" to something else. Then go to \"C:\\Program Files\\Sentinel One\\Sentinel Agent {Version}\\config\". We are supposed to delete files here, but the files are owned and managed by SentinelHelperService, so I wasn't able to delete them, and the service can't start in safe mode.Since I'm local admin, on a privileged (administrator mode) command prompt, I can change ownership of the files by running: takeown /F \"C:\\Program Files\\Sentinel One\\Sentinel Agent {Version}\\config\\*\". Replace {Version} with the version of the agent on your machine.Then we need to change the permissions of the files by running:  icacls \"C:\\Program Files\\Sentinel One\\Sentinel Agent {Version}\\config\\*\" /grant {YourUserName}:F /tGo back to \"C:\\Program Files\\Sentinel One\\Sentinel Agent {Version}\\config\" and delete the files. You can also run the command: rm \"C:\\Program Files\\Sentinel One\\Sentinel Agent {Version}\\config*\".Once that's done, go back to system configuration, either search for sysconfig or run msconfig, under \"boot\" tab, uncheck the \"Safe boot\" option, \"Apply\", \"OK\", and restart/reboot. This should launch in normal mode.After login, I just uninstall the agent as usual, then restart/reboot once more and the issue is fixed. Ref: https://justinshafer.blogspot.com/2022/08/how-to-uninstall-sentinel-one-without.html",{"id":827,"title":828,"titles":829,"content":830,"level":9},"/2026/02/08-opensearch-container-unreachable-in-ecs","08 OpenSearch Container Unreachable In ECS",[],"OpenSearch Container Unreachable in ECS This is a repost from my old blog. First posted in 12/2/2024. So, I have to launch Opensearch in ECS. And I need to add persistent storage. The container ran fine but it threw AccessDeniedException. And even though the container ran, my application was unable to connect to it. After few tries, I found out that it is due to the permission of the directory where the data are supposed to reside. The container runs in ECS on EC2. The path, in this case, I use /usr/share/opensearch/data on EC2 is owned by root, but the container runs as ec2-user. So, I had to update the user data field on the launch template (since I used ASG) to include the following commands: mkdir -p /usr/share/opensearch/data\nsudo chown 1000:1000 /usr/share/opensearch/data That fixed the exception and the reachability issue.",{"id":832,"title":833,"titles":834,"content":835,"level":9},"/2026/02/09-lambda-times-out-when-getting-object-from-s3","09 Lambda Times Out When Getting Object From S3",[],"Lambda Times Out When Getting Object from S3 This is a repost from my old blog. First posted in 12/10/2024. I had the issue where Lambda function launched in private network times out when trying to get object from S3 bucket. Typically, there are two solutions: Use S3 VPC endpoint (either gateway or interface) since it resolves s3 endpoint to private IP.Attach public IP. This is done using NAT Gateway with Elastic IP (EIP). The problem is, in my case, the S3 bucket is in different region, different account, than the Lambda function while the first solution, even though S3 is a global service, the VPC endpoint can't resolve to S3 in different region. In short, the first solution only works when S3 bucket and Lambda function are in the same region. That left us with solution 2 which is more expensive but works. Also I need to make sure that the S3 bucket policy allows cross account access.",{"id":837,"title":838,"titles":839,"content":840,"level":9},"/2026/02/10-playwright-intermittent-connection-refused-error","10 Playwright Intermittent Connection Refused Error",[],"Playwright Intermittent Connection Refused Error This is a repost from my old blog. First posted in 2/26/2025. As I have more tests in Playwright, the number of workers required grow and I happened to encounter the following error: Error: page.goto: NS_ERROR_CONNECTION_REFUSED And the tests that failed changes every time playwright test is run. To solve this, I reduce the workers in playwright.config.ts. from: workers: process.env.CI ? 1 : undefined, to: workers: process.env.CI ? 1 : 8, //8 works fine for me. I will go smaller like 4 or 5 if the issue persists. This defines the max workers Alternatively, workers can be set when running the test. npx playwright test --workers 8 For more information: https://playwright.dev/docs/test-parallel#limit-workers",{"id":842,"title":843,"titles":844,"content":845,"level":9},"/2026/02/11-cypress-connection-refused-error","11 Cypress Connection Refused Error",[],"Cypress Connection Refused Error This is a repost from my old blog. First posted in 2/26/2025. I had a case where I need to call an api then visit the app in Cypress and it turns out to be causing an issue with the following error message: Error: connect ECONNREFUSED 127.0.0.1:4200 It turns out to be Cypress' origin safety issue. I wrapped the cy.request() with cy.origin() and that solves the issue with a catch. If I call cy.origin() before I call cy.visit() then it doesn't work somehow. If I call cy.visit() first and then cy.origin() then it works fine. Also, if after code change, it doesn't appear to work, restart cypress app (or test runner if using older version). I had the case where I call cy.origin() first, then cy.visit() which doesn't work, make the change to call cy.visit() first without restarting the app and it still doesn't work. But it works after I restarted cypress app.",{"id":847,"title":848,"titles":849,"content":850,"level":9},"/2026/02/12-docker-build-error","12 Docker Build Error",[],"Docker Build Error This is a repost from my old blog. First posted in 3/20/2025. After many successful build, I happened to bump into the following error when trying to run docker build. => ERROR [internal] booting buildkit\n=> => pulling image moby/buildkit:buildx-stable-1\n\n...\n\nERROR: Error response from daemon: {\"message\":\"x509: certificate signed by unknown authority\"} The only thing changed on my machine was I installed and run podman, so I stop podman machine by running: podman machine stop And docker build works again.",{"id":852,"title":853,"titles":854,"content":855,"level":9},"/2026/03/04-running-coding-ai-agent-locally","04 Running Coding Ai Agent Locally",[],"Running Coding AI Agent Locally I was wondering if there's a decent AI agent that helped with coding but can be run locally. After a quick test, I managed to get it to work with the following stack: OllamaDeepSeek CoderContinue VS Code ExtensionVS Code To set it up, I follow the steps below: First, I install Ollama on my machine using winget: winget install Ollama.Ollama.Then, download DeepSeek Coder to run in Ollama. https://ollama.com/library/. In my case, I just use the smallest model which is 1.3b paramaters: ollama run deepseek-coder:1.3b.Next, I search for and install \"Continue\" VS Code extension by continue.dev.To configure the extension, make sure Ollama is running on http://localhost:11434. If it's not, run ollama serve.In my case, the \"Continue\" extension was unable to detect Ollama. I had to setup the configuration to autodetect. To do that, I open the Configs menu of the extension. Click the setting/gear icon next to Local Config and paste the following config: name: Local Config\nversion: 1.0.0\nschema: v1\nmodels:\n  - name: Autodetect\n    provider: ollama\n    model: AUTODETECT\n    roles:\n      - chat\n      - edit\n      - apply\n      - rerank\n      - autocomplete Then, the LLM works locally, but it will use a lot of CPU and memory.",{"id":857,"title":858,"titles":859,"content":860,"level":9},"/2026/03/08-container-storage-interface","08 Container Storage Interface",[],"Container Storage Interface (CSI) I was investigating how to get a secret from Hashicorp Vault down to a Kubernetes pod and encountered an interesting concept called Container Storage Interface (CSI). Basically, using CSI driver, providing the secret name and key, a SecretProviderClass object can pull each secret value as a file in the filesystem in the pod. Then, use entrypoint script of the pod to pull each file and set environment variable using the file name as key and content as value. The application can then pull the secret from the environment variables without additional package/library. For more information: https://developer.hashicorp.com/vault/docs/deploy/kubernetes/csi",{"id":862,"title":863,"titles":864,"content":865,"level":9},"/2026/03/18-iisexpress-has-exited-with-code-4294967295","18 Iisexpress Has Exited With Code 4294967295",[],"IIS Express Has Exited with Code 4294967295 This happens out of a sudden. It's been working great for a while and suddenly I can't debug the web application, which is still using .NET Framework 4.8. The error message is: The program '[19000] iisexpress.exe' has exited with code 4294967295 Visual studio will launch the browser but before the browser loads, the application exited. Thanks to the following article, I manage to fix it. https://stackoverflow.com/questions/72171694/iis-express-in-visual-studio-2017-crashes-when-debugging-app-and-selecting-file But I follow a slightly different steps: I uncheck the option Stop debugger when browser window is closed, close browser when debugging stops.Close the browser instances.Launch my application. At this point, iisexpress will not exit for no reason.Stop debugging.Check the option Stop debugger when browser window is closed, close browser when debugging stops since this option was initially checked.",{"id":867,"title":868,"titles":869,"content":870,"level":9},"/2026/05/14-forgot-wsl-password","14 Forgot Wsl Password",[],"Forgot WSL Password How to reset the password? If there's only one distribution, run wsl -u root If multiple, run wsl -d \u003Cdistro> -u root Then run passwd \u003Cusername> If you are not sure what your username is, usually cat /etc/passwd can help. It should then prompt for new password.",{"id":872,"title":873,"titles":874,"content":875,"level":9},"/2026/05/19-access-js-object-properties-with-string-and-reduce","19 Access Js Object Properties With String And Reduce",[],"Access JavaScript Object Properties with String and Reduce In this case, I parsed a json file and need to query the object using a string and JavaScript can get one level down using Bracket notation. const theObject = {\n  topLevel: 0\n};\n\nconst topLevelValue = theObject[\"topLevel\"];\n\nconsole.log(topLevelValue); // will be 0\nHowever, bracket notation can't handle multiple levels:const theObject = {\n  topLevel: {\n    firstLevel: 1\n  }\n};\n\nconst firstLevelValue = theObject[\"topLevel.firstLevel\"]; // Doesn't work\nSo, consult with Claude Sonnet and managed to use reduce to get it to work. I tried not to use JMESPath or JsonPath or other query libraries.const theObject = {\n  topLevel: {\n    firstLevel: 1\n  }\n};\n\nfunction getValue(queryString) {\n  const keys = queryString.split('.');\n  const lastKey = keys.pop();\n  const lastObj = keys.reduce((acc, part, index) => {\n    const nextKey = keys[index + 1] !== undefined ? keys[index + 1] : lastKey;\n    if (acc[part] === undefined || acc[part] === null) {\n      acc[part] = {};\n    }\n    return acc[part];\n  }, theObject);\n\n  return lastObj[lastKey];\n}\n\nconst firstLevelValue = getValue(\"topLevel.firstLevel\");\n\nconsole.log(firstLevelValue); // will be 1\nIt works by turning \"topLevel.firstLevel\" into theObject[topLevel][firstLevel] iteratively and it works for multiple level.Next, I need to handle array, so I can use \"topLevel.firstLevel.1.secondLevel\" to get the second element of firstLevel array and return the value of secondLevel property.It requires a small tweaked to the code above:const theObject = {\n  topLevel: {\n    firstLevel: [\n      {\n        secondLevel: \"firstElement\"\n      },\n      {\n        secondLevel: \"secondElement\"\n      }\n    ]\n  }\n};\n\nfunction getValue(queryString) {\n  const keys = queryString.split('.');\n  const lastKey = keys.pop();\n  const lastObj = keys.reduce((acc, part, index) => {\n    const nextKey = keys[index + 1] !== undefined ? keys[index + 1] : lastKey;\n    if (acc[part] === undefined || acc[part] === null) {\n      acc[part] = isNaN(parseInt(nextKey)) ? {} : [];\n    }\n    return acc[part];\n  }, theObject);\n\n  return lastObj[lastKey];\n}\n\nconst secondLevelValue = getValue(\"topLevel.firstLevel.1.secondLevel\");\n\nconsole.log(secondLevelValue); // will be \"secondElement\"\nWithout the code change, it turns \"topLevel.firstLevel.1.secondLevel\" into theObject[topLevel][firstLevel][\"0\"][secondLevel]With the change, basically, if it encounters a number, treat it as an array, so it turns \"topLevel.firstLevel.1.secondLevel\" into theObject[topLevel][firstLevel][0][secondLevel]",{"id":877,"title":878,"titles":879,"content":880,"level":9},"/2026/05/19-ef-side-effect","19 Ef Side Effect",[],"EF Side Effect I happened to find a side effect of Entity Framework that caused a confusion. Thanks to Claude Sonnet (AI) that I managed to understand what's going on. It started with the following example structure. Let say: Blog (ID: 1)\n  - Post 1 (ID: 2)\n  - Post 2 (ID: 3)\nI need to copy the structure as a new structure, but without Post 2, so the first step is set the ID to be 0. That will trigger EF to treat them as new object and thus will perform an insert.Blog (ID: 0)\n  - Post 1 (ID: 0)\n  - Post 2 (ID: 0)\nThen, I removed Post 2 and perform a SaveAsync(), so it is expected to be:Blog (ID: 1)\n  - Post 1 (ID: 2)\n  - Post 2 (ID: 3)\n\nBlog (ID: 5)\n  - Post 1 (ID: 6)\nInstead, what happened was, it became the following. Noticed that the original Post 2 became the child of the new Blog.Blog (ID: 1)\n  - Post 1 (ID: 2)\n\nBlog (ID: 5)\n  - Post 1 (ID: 6)\n  - Post 2 (ID: 3)\nWhat happened was, during setting ID to 0, EF tracks Post 2 and found out that it has changed. Remove Post 2 from memory doesn't detach it (an entity) from the tracker. And thus, in EF, it thought Post 2 needs to be updated instead.class Blog\n{\n  List\u003CPost> Posts { get; set; }\n}\n\nblog.Posts.Remove(post2); // This will not detach it from tracker.\nThe solution is to reset the ID after removal. So, first we perform removal, so EF doesn't think Post 2 has changed and then reset the ID.Remove Post 2 first:Blog (ID: 1)\n  - Post 1 (ID: 2)\nThen reset the ID:Blog (ID: 0)\n  - Post 1 (ID: 0)\nThat way, EF will insert the blog as new entity along with Post 1, but leaving Post 2 alone since in the tracker, it hasn't changed.",{"id":882,"title":883,"titles":884,"content":885,"level":9},"/2026/05/25-bcm4360-rev3-driver-on-ubuntu-26-for-macbook-pro-2014-offline","25 Bcm4360 Rev3 Driver On Ubuntu 26 For Macbook Pro 2014 Offline",[],"Broadcom BCM4360 Driver on Ubuntu 26 for Macbook Pro 2014 Offline I managed to install Ubuntu 26 on my Macbook Pro 2014 using balenaEtcher: https://documentation.ubuntu.com/desktop/en/latest/how-to/create-a-bootable-usb-stick/#using-balenaetcher. However, the wifi is not working. Turns out the adapter is by Broadcom and the driver is not included by default. Even after I opt for third party software installation. Running: lspci -vvnn | grep Network shows that my adapter is Broadcom BCM4360 (rev 03). Since the laptop can't connect to wifi and I don't have ethernet cable, I used a different laptop to find the driver package which lands me on: https://help.ubuntu.com/community/WifiDocs/Driver/bcm43xx My first try, which doesn't work, is to download the .deb packages in a usb drive and plug the drive to the Macbook. In my case, I know I need the sta driver, so I download the dkms from https://launchpad.net/ubuntu/+source/broadcom-sta Then I run the following: cd /run/media/\u003Cusername>/\u003Cusbdrive-name>. In my case, cd '/run/media/nikki/USB DRIVE'sudo apt install ./\u003Cdriver-filename> The installer failed because dependencies are not installed. I found out that you can download the dependencies at https://packages.ubuntu.com/. Soon, it gets tedious due to the number of dependencies. I was like how about if I used a different way. An obvious option is ethernet cable + usb ethernet adapter, but I have none of that. So, I ended up using my Android phone + USB cable and enabled USB tethering. This works! Basically using my phone as wifi adapter. After that, I simply use the Software Updater in Ubuntu to download required packages, restart and wifi works. Another option that I didn't have chance to try is BTPAN (Bluetooth Personal Area Network) to connect my Macbook to my Android phone and enable Bluetooth Tethering.",{"id":887,"title":888,"titles":889,"content":890,"level":9},"/2026/05/25-linux-mint-error-creating-bootable-usb","25 Linux Mint Error Creating Bootable Usb",[],"Linux Mint Error Creating Bootable USB I used balenaEtcher on Windows 11. The error message that I got is: Error:(0 , h.requestMetadata) is not a function. After reading posts online, I got it to work by running balenaEtcher as administrator. Basically, just right click and select Run as administrator and I no longer encounter the error. Etcher version that I used is 2.1.6.0.",{"id":892,"title":893,"titles":894,"content":895,"level":9},"/2026/06/01-exploring-lm-studio","01 Exploring Lm Studio",[],"Exploring LM Studio Today, I explored LM-Studio as it was introduced by my boss since I played with Ollama before. I was able to install it easily in my Macbook using brew and in Windows using winget. But for somewhat reason, I can't get it to work in my Linux machine. There are a few features that caught my attention: UI is really clean.It comes with a lot of information about the AI model. This might be because I enabled the developer mode.I can download new model right from the app itself.It also provides list of endpoints for REST call which is really nice.Before I download a model, it will let me know if the model is too big for my machine to handle. This is a big help. Check it out at https://lmstudio.ai/",{"id":897,"title":898,"titles":899,"content":900,"level":9},"/2026/06/02-ai-use-cases","02 Ai Use Cases",[],"AI Use Cases Reflecting back on what I used AI for these past couple of months, I found that it really helps my development and learning experience that previously requires more time and effort. One of the latest one is I used AI to create a mock data that will satisfy certain code. For example, if the code looks like the following, I will send the code to AI and create a json that will meet the condition. var isEnabled = jsonObject[\"features\"][0][\"enabled\"];\n\nif (Convert.ToBoolean(isEnabled)) {\n  ...\n} Another use case is when I need to find the original use case based on a certain code. Sometimes, the code was written years ago and no one knows why it is that way in the first place. With AI, I don't have to remember the git command. Coupled that with MCP server, it was able to find the ticket and summarize the original intention. This helps us to understand better on the reason for the code. One use case that I used often is to convert a Linq statement to SQL, so I can execute it against the database. It got 80-90% there and it saves me a lot of time. Outside of work, there are also some use cases that AI does well. For example, I have a piece of cloth from IKEA, but not sure if it is machine washable. The icons don't have a word to accompany them and I'm not familiar on what they means, so I snapped a picture and have AI explained to me what those icons mean. Also, I once snap a picture of my friend's dish, ask AI for the recipe and my friend said, it's pretty accurate. Another case is when I was walking around the neighborhood and saw a house on sale. My friend pulled the brochure and wondering what's the square footage of the house since it is not listed in the brochure. Snapped a picture and AI was able to figure it out the location, the average price, and square footage. One of the latest use case is I had a strange bathroom sink stopper configuration. Usually, it's just a pull rod, but mine has a wire. I searched online trying to find out what it is, but nothing comes up. Asked AI and it thinks I have a cable-driven stopper. Pretty nice.",{"id":902,"title":903,"titles":904,"content":905,"level":9},"/2026/06/03-incognito-cookie-handling","03 Incognito Cookie Handling",[],"Incognito Cookie Handling I tried to understand a weird case at work. Basically, I visit a page which will load exam page in an iframe inside an MFE component. However, it works in regular window, but not in incognito. We know that it is cookie based and we are using Chromium based browsers. So, I asked AI few questions and I figured out that incognito/private window will block third party cookie while regular window will allow third party cookie. And in my case, the iframe is loaded from a completely different domain and thus it is considered third party. For example, if the current domain is example.com and the server set cookie for example.com, the cookie is considered first party cookie. If the current domain is example.com and the server set cookie for something-else.com, then the cookie is considered third party. In incognito, the server that serves something-else.com will not receive the cookie.",{"id":907,"title":908,"titles":909,"content":910,"level":9},"/2026/06/04-using-tailscale","04 Using Tailscale",[],"Using Tailscale I have been wondering if there's a way to connect to my machines in my home network securely from outside of my home network. Until now, I just rely on Remote Desktop and Team Viewer to make that connection. Today, I happened to read about Tailscale and Wireguard. I used AI to get a better understanding how it works. Tailscale basically make it easy to use Wireguard and it connects two or more devices so that they can send network traffic to each other from anywhere in the world. It handles network discovery, encryption and routing. Devices connect to Tailscale will behave as they are in the same network. Regarding the internet traffic, the fact that it uses split-tunnel, that means the internet can be routed without going through Tailscale (internet traffic can be routed through Tailscale using exit node if needed). This will improve performance. On top of that, I have Beryl AX router which is supported by Tailscale. That will make it easy if I need multiple devices connected. However, because it is not an actual network, I won't be able to connect to devices in my home network that's not registered to Tailscale. So, that means the device itself needs Tailscale app installed. So far, it works great for my use case. With Tailscale, you can create VLAN between registered devices.",{"id":912,"title":913,"titles":914,"content":915,"level":9},"/2026/07/04-updating-config-per-environment-on-react-in-s3","04 Updating Config Per Environment On React In S3",[],"Updating Config per Environment on React in S3 I have been reading Continuous Delivery book by Jez Humble and David Farley. I really like the idea that to deploy an application, I just need to select a version and environment and hit Deploy button. So, I tried to update my current pipeline to be able to do that. It's not without challenge, especially for SPA hosted in S3. First of all, there's no concept of Environment Variables in S3. Alternatively, I can use .env, but it has to be done during build time which counter to the idea of adjusting the configuration per environment because my artifact will then tied whatever configuration I use on build time. And to deploy to different environment will then requires a different build which counter to keeping the artifact the same between environment. As I was checking online for solutions, one suggestion is to move to compute running Node.js which will then update the config before serving it to the user. But S3 is nice and cheap, so would like to stick with it. With the help of Claude, another suggestion is to create a config file static file. The application will then retrieve it, extract the content before running the application itself. This is not bad, but a bit strange. I'm also a bit worried on config file injection which when I think later, CORS will help mitigate that issue. Besides, being SPA to pull index.html, theoretically it can be hijacked too. And it is a solution indeed. This way, on my pipeline, I can update the value of the config file before deploying the application to any environment after the build stage.",{"id":917,"title":918,"titles":919,"content":920,"level":9},"/2026/07/05-docker-from-scratch","05 Docker From Scratch",[],"Docker from Scratch Today, I'm wondering how did all those base Docker image created. And what happened on the most basic layer of a Docker image. I found out that there's a reserved image called scratch. So, the most basic docker image can be derived from it by adding FROM scratch layer. At the most basic form, it actually runs a Linux kernel, no matter what is the host environment is. Yes, even on Windows. From scratch image, then we can add layers to reach the state of base image that we usually use. Link: https://hub.docker.com/_/scratch",{"id":922,"title":923,"titles":924,"content":925,"level":9},"/2026/07/06-debugging-session-storage","06 Debugging Session Storage",[],"Debugging Session Storage I have a need to check the value of a session storage item. The problem is as soon as the session storage item is set, it will navigate and the new page will then retrieve the item and remove the content. Consulting google and the AI came up with a neat solution by using a JavaScript Interceptor. Basically, just run the following on the console to override the native sessionStorage.setItem method. var originalSetItem = sessionStorage.setItem;\nsessionStorage.setItem = function(key, value) {\n  debugger; // this will create a breakpoint and pause the execution.\n  originalSetItem.apply(this, arguments);\n}; Running it again, it will pause, so I can see the value before it is removed.",{"id":927,"title":928,"titles":929,"content":930,"level":9},"/2026/07/08-change-data-type-of-a-primary-key-in-sql-server","08 Change Data Type Of A Primary Key In Sql Server",[],"Changing Data Type of a Primary Key in SQL Server I'm helping my team changing primary key data type, but a simple ALTER command doesn't work due to the PK constraint. I was under impression that a table always need a PK, so I can't drop the constraint, but I tried it anyway. ALTER TABLE [table]\nDROP CONSTRAINT PK_Id; And it works, I ended up with a table without any PK. Another ALTER to change the data type and one more ALTER to add back the PK constraint and voilà! ALTER TABLE [table]\nALTER COLUMN Id INT; ALTER TABLE [table]\nADD CONSTRAINT PK_Id PRIMARY KEY (Id);",{"id":932,"title":933,"titles":934,"content":935,"level":9},"/2026/07/08-getting-folder-directory-size-in-windows","08 Getting Folder Directory Size In Windows",[],"Getting Folder/Directory Size in Windows My computer is running low on storage, so I'm looking for an efficient way to retrieve list of folders and their size. Apparently the easiest is to use separate application. I used https://windirstat.net/ and managed to find folders that I can clean up. Alternatively, the online community has good experience with https://www.jam-software.com/treesize.",{"id":937,"title":938,"titles":939,"content":940,"level":9},"/2026/07/20-dotnet-pack-didnt-build","20 Dotnet Pack Didnt Build",[],"Dotnet Pack Din't Build My team is a assigned a small project to build a NuGet package. And since I'm familiar with DevOps practice, I took the initiative to build the CI/CD pipeline. Our client has a standard pipeline that needs to be incorporated. The standard pipeline stage for NuGet only runs dotnet pack and it's failing. The error message indicated that it can't find the dll. Checking various online documentation and discussion, dotnet pack is supposed to do implicit build, so it should have produced the dll. After couples of back and forth with the engineer over at the client side, I happened to notice the following note at dotnet pack page: In some cases, the implicit build cannot be performed. This can occur when GeneratePackageOnBuild is set, to avoid a cyclic dependency between build and pack targets. The build can also fail if there is a locked file or other issue. And indeed, our project has GeneratePackageOnBuild since we wanted to make sure that our project indeed produce the package when run locally. Removing the GeneratePackageOnBuild property then allows  dotnet pack to implicitly build the project and produced the dll again.",{"id":942,"title":943,"titles":944,"content":945,"level":9},"/2026/07/21-office-script-as-alternative-to-vba-macro","21 Office Script As Alternative To Vba Macro",[],"Office Script as Alternative to VBA Macro During our retrospective session with our client, we have decided that the stand up leader will call each person's name in turn to reduce delay and awkward silence. Our stand up leader suggested that the list of people be randomized so as not the same person will go first every time. That got me curious on how we can randomize the list. The stand up leader is not technically savvy, so most probably will attempt to use online service. However, online service that doesn't necessarily able to retain the list, so the list might need to be filled every day. So, my thought is if I can randomize the list in Excel and add a button, it is at least easy enough to use. Of course, the first thought is to use VBA, but I'm reluctant to use macro since it's potentially blocked by default. That's when I stumbled upon Office Script, a JavaScript based script runner that's integrated with Excel. With AI, I got started really quick and able to create a script that will randomize the used cells. One small hiccup is when I added a button tied to the script, it didn't work as expected and highlight random cell on the worksheet instead. Running the script directly works great. I found out later that I need to save the script in order for the button to pick up the logic. So, save often! To learn more, visit: https://learn.microsoft.com/en-us/office/dev/scripts/overview/excel",{"id":947,"title":948,"titles":949,"content":950,"level":9},"/2026/07/22-bash-parameter-expansion-syntax","22 Bash Parameter Expansion Syntax",[],"Bash Parameter Expansion Syntax I was in the middle of trying to understand a certain CI process and was wondering if there's a null-colaescing operator in bash. That's when I learned bash parameter expansion syntax. It's pretty simple, but powerful. ${VARIABLE:-default_value} Basically, if VARIABLE is not defined, then it will use default_value. In the CI pipeline that I encountered, it is used as follow: ${PROJECT_PATH:-.} So, if PROJECT_PATH is not defined, just default to the current directory.",{"id":952,"title":953,"titles":954,"content":955,"level":9},"/2026/07/22-webapplicationfactory-and-runsettings","22 Webapplicationfactory And Runsettings",[],"WebApplicationFactory and Runsettings On the project that I'm working on, I intended to have an integration test. But I never built one before and wondering what's the best way to do it for .NET. To do integration test, the idea is we need to deploy the application and write an automation and run it against the deployed application.However, in my case, since the project is a library project, it needs an application that references it. And I don't want to have two additional projects. So, a quick search introduced me to WebApplicationFactory which I can use in my test project. First, I created a regular Program.cs that defines all the pre-launch configurations and services, so I can use dependency injection in the tests. Next, I used WebApplicationFactory to launch the Program for each test case. [TestInitialize]\npublic void Setup()\n{\n  var factory = WebApplicationFactory\u003CProgram>();\n\n  var service = factory.ServiceProvider.GetRequiredSerice\u003CISomeService>();\n} To learn more on integration test for .NET: https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-10.0&pivots=xunit After that, I'm wondering how I can have an environment variable to hold some sensitive information since there's no launchSettings that comes with the project. I might be able to use appSettings.json and I don't want to set it on my machine's environment variable. That's when I found runsettings which allows me to add environment variables for tests. I also added it to .gitignore to prevent sensitive information being checked in into the repository. So, I created .runsettings file and placed it on the root of the solution. \u003C?xml version=\"1.0\" encoding=\"utf-8\"?>\n\u003CRunSettings>\n  \u003CRunConfiguration>\n    \u003CEnvironmentVariables>\n      \u003CASPNETCORE_ENVIRONMENT>Development\u003C/ASPNETCORE_ENVIRONMENT>\n    \u003C/EnvironmentVariables>\n  \u003C/RunConfiguration>\n\u003C/RunSettings> With .runsettings file on the root of the solution, running test through Visual Studio will automatically detect it and use it. To use runsettings when running tests from command line, it needs to be specified using --settings option. dotnet test --settings .runsettings For more information on runsettings: https://learn.microsoft.com/en-us/visualstudio/test/configure-unit-tests-by-using-a-dot-runsettings-file?view=visualstudio",1785167451089]