I was setting up a new Umbraco Project, for the first time in a while. At my company, we have a base implementation that we 'fork' manually by copy/pasting the repository and creating a specific one for each client.
I set it up and try to run it, and immediately hit this error:
A route named 'something or other' is already in the route collection. Route names must be unique.
A good error message that describes the problem exactly, and how to fix it. My problem? I'm not defining any routes manually, and this is the same code that was working in another project. What gives? There are lots of posts explaining how to update your RouteConfig to remove the duplicate.
Eventually I come across a highly up voted post, suggesting to delete the bin files and try again. I know the bin folder is created by the compiler for my project; but deleting everything in there felt a little draconian to me. This is an axe kind of fix, and I'm thinking this is more of a scalpel problem.
One of those manual steps to creating our client specific projects, is to go in and rename folders, solution, and project files (and their internal path references to each other). This went just fine, and from a Visual Studio perspective everything linked up worked, and built.
Then it hit me. I renamed the project and its compiled output was in the bin folder along with the newly built and compiled version with my new name. Ultimately I had two copies of identical code in the bin folder with different physical file names.
I deleted the dll files from my original build with the old name, and that ultimately fixed the problem.
Utilizing .NET Core has been a pretty great experience. There have been a few gotchas with APIs not being available in the base package. I was really stoked to see that the SqlBulkCopy classes are part of .NET Core. I was less thrilled to note that DataTable is there in .NET Core 1.0 but just an empty non-usable class.
That means converting from a generic IEnumerable<T> to a DataTable/Set is not an option.
Enter DbDataReader: another way to utilize BulkCopy.
If you have an IDataReader instance, the BulkCopy WriteToServer method has an overload to cover that; however, I'm an ORM to pull in some data form various sources so I basically have List<T>s, not IDataReaders. Searching the web it's pretty difficult to find a generic way to convert from a generic collection to a IDataReader. Much harder than it should be.
This great package makes the process easy and extremely fast. Basic demo shows how simple this package makes things.
using (SqlBulkCopy bulkcopy = new SqlBulkCopy(connection)
using (var reader = ObjectReader.Create(toInsert))
Sounds simple enough, right? The blob storage account has a Uri and each part means something.
There are only three levels of hierarchy built into the system:
Within the Blob itself, the NAME property can be used to create additional ‘virtual’ directories, but they are just that. Virtual. This is where things get pretty powerful. Using the Storage Client libraries for .NET, the ListBlobsSegmentedAsync method allows you to have Azure filter out blobs based on prefix. The prefix filter here only applies to the Blob Name. If we look at a specific example (redacted to protect the guilty):
You see this whole part [VirtualFolder1/2017/07/01/15/fileanme.ext] is all the Blob Name. It just so happens to be setup by folders Year/Month/Date/Hour and because of this we can use the ListBlobsSegmentedAsync to filter based on it.
var list = await container.ListBlobsSegmentedAsync(
This would give us all files for the month of July in the year 2017, regardless of which day or hour they are listed in. Doing it this way allows me to query a much more limited set of data, meaning I have to process out fewer files locally and there is less data transfer in and out as a result.
The main caveat I’ve found is that you cannot use wildcards, so you can’t find all the blobs for July in any year without doing multiple queries. Because the container is not part of the blob name, you cannot query across containers either.
Had two azure subscriptions along with two AppServicePlans (one each) for cost savings I wanted to combine them, but you can’t use the ‘Change AppServicePlan’ on the individual AppServices unless they’re in the same sub, resource group, and region.
Each time I tried to use the portal to move one AppServicePlan to the other subscription, I would get this error:
the subscription ‘subscription-guid’ is not registered for resource types 'microsoft.insights/webtests (centralus)'. #code: missingregistrationsfortypes#
Turns out that I had some existing web tests from the old portal that were orphaned and couldn’t be opened/read from the new portal.
Enter the commandline tool from the web portal (yes, the terminal in the web portal, its neat check it out!):
az resource list –resource-type microsoft.insights/webtests
and there I get a nice json list of the resources that were giving me trouble, along with their “id” so I was able to delete them with
az resource delete –id /subscriptions/[guid]/resourceGroups/[my-resource-group]/providers/microsoft.insights.webtests/[test-name]
Someone more in tune with the bash shell could probably link those up to double down and delete all the items returned with a single command, but I was able to do it manually as I only had a few of these troublesome resources clogging up my migration.
I’m going to use this post to tag a series of great tools that I use. For those times when a screenshot isn’t quite good enough. ScreenToGif is a nice, clean screen capture and gif editor. Its a free download and it just runs. No installer (though it does need .NET 4.6.1) just download, save, and go.
Here’s a screenshot of the tool, around my Live Writer editor:
ScreenToGif has multiple capture options, but the one I find most useful is screen. You drag the ScreenToGif window around the screen area you wish to record. You simply hit the record/stop buttons to record while you work, then it opens your project in the editor to make any post-production changes you need. Then you can save as a .gif file for distribution.
Here is a short recording of the above:
Often a screenshot is plenty, but sometimes a quick gif communicates so much more.