This is the third installment of personal reflection and I'm marginally neutral about what transpired in 2018 and what 2019 may bring. As before, I will list the original goals and whether they were achieved along with some things that were never listed. There is a bit of personal concern some of these "goals" are just busywork. However, the main challenge to myself is not to become lazy–both mentally and physically. That doesn't mean I won't take a day here and there to just relax and hang out. There's probably a word to describe it, but it's the sense of wanting to get as much done in life and using your abilities to their fullest, especially not knowing what could happen tomorrow. And, with that slightly morbid intro., let's get to the review!
... and other SIP providers
I have been using Vonage for home phone service since 2007. There are no complaints about service from me. It was never down when I needed it and the price/feature is pretty good (sans taxes that almost double the bill). But, the family only uses it sparingly and mostly as a default number for anything that needs a number. The service is paired with a Linksys PAP2v2 purchased at the time I originally signed-up for a Vonage account. The unfortunate downside to this pairing is the hardware is locked to Vonage. Fast-forward to mid-2018 and I'm switching SIP providers. I'm looking for lower monthly costs and an opportunity to build my telephony skills via in-house PBX using FreePBX.
🕳️🚶 ☛ 🗬🕳️ ☛ 🚧🕳️🚧 ☛ 🔁
Extension methods are a great feature of C# (and other .NET languages). But, their usage on interfaces recently caused me some problems. I made an assumption about how the object would be "seen" at runtime and caused a loop. A quick fix was to cast the interface-instance to a known type, but this ultimately wouldn't scale since I needed to manually check the type at runtime and either build
switch logic. Here's a modified form of the initial problem and the solution.
I have a few apps. running on subdirectories at https://labs.billbogaiv.com/. Each app. runs on a separate port and Nginx is setup to proxy requests to each respective app. The trouble begins when those apps. generate links for things like CSS or images. Those apps. don't inherently know they are running on a subdirectory, so the resulting links are broken from the viewpoint of the browser. Here's a simplified setup to demonstrate this behavior:
Personal introductory side-note: Today, my wife and I have been together for fifteen-years and married ten of those years. I love what we have accomplished together and wait with eager anticipation those journeys we have yet to fulfill.
Around this time last year, I wrote how 2016 was a pretty neutral year. 2017 fared better, but I'm still a 90% finisher. I can't find another word/phrase to describe it, but it means someone who produces something that functions, but doesn't give it the polish that would make it great (they have already moved on to the next thing). For me, it's the challenge of solving a problem. I really enjoy it, but once the problem is solved, my interest wanes. Things like documentation or marketing become interference. So, my main goal for 2018 is to increase my finisher-status. I'll list some quick wins to get me there, but first, let's review 2017 goals and see where I hit the mark and where ambition tanked progress:
If you rely on default behavior, then port 5000 is used (running in VS+IIS Express will give a random port designated by VS). And, only one app. at a time can use the same port (on the same machine/interface). If a second app. is run, this error is thrown:
> dotnet run crit: Microsoft.AspNetCore.Server.Kestrel Unable to start Kestrel. System.IO.IOException: Failed to bind to address http://127.0.0.1:5000: address already in use. ---> Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.AddressInUseException: Error -4091 EADDRINUSE address already in use ---> Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal.Networking.UvException: Error-4091 EADDRINUSE address already in use
Cue references to Superman III and Office Space
For the longest time, I would only focus on the cost when putting fuel in my car. However, a quirk in U.S. fuel pricing means I could be shorting the amount of fuel I get for the same cost. Read on to discover the ease of maximizing fuel purchases and why the potential shortage increases with lower fuel prices.
Why it's important to always be vigilant
Most email providers do a decent job of filtering email spam. They're either outright deleted for you or put in a separate spam/junk/clutter folder. But, they're not perfect, and knowing how to spot the fakes becomes important. Submitting personally identifiable information (PII) to an unknown party allows them to open lines of credit, make purchases, assume your identity, etc. General rule of thumb is the more information given the more personal damage that can arise.
And, a preview of 2017
I think 2016 might end up being neutral if I just sum up the number of positives and negatives. Starting a personal website had been on my list for years and finally getting it started felt really good. But, I never really thought about the site's overall design. And, I started several new projects, but quickly shifted focus to the "next thing". Overall, I did not have a clear plan of action. And, it's odd, too, because I generally see myself as someone who prefers to plan ahead. My wife reminded me the other day she has always seen me as someone who "doesn't settle for average". This year, I did. Although, it's not accurate to say I was lazy. Maybe I took too many things for granted. But, enough of this pity party.
I have been coding a personal project for the past couple weeks. It is a little too soon to unveil, but will say it involves lights, sounds, door switches, and motion sensors. Part of my testing involves running on the intended hardware–Raspberry Pi. However, coding the project in .NET Core left me with a couple stumbling blocks…
Prior to submitting my entry in this year's 10k apart competition, I played-around with the overall board-size to see how well browsers could handle tens of thousands of DOM-elements. The result: not too well. There are just too many styling rules within the grid and performance noticably suffers. For example, a 32x32 grid contains a minimum of 6,144 child-elements (six-elements per "pixel"). The grid is wrapped with a form-tag and when submitted, results in 1,024 values being submitted…
Lately, I have been using the Web Markup Minifier package to reduce asset-size as part of my entry in this year's 10k apart competition. Since this is a piece of middleware, I wanted to use it for any asset–not just MVC-things. When the browser queried CSS-files or images, though, no content was returned. The status code was
200, however. So, I began to investigate…
While testing a site on an iPhone, I came across unexpected behavior related to some simple markup and styling. My initial assumption was 'this was a problem due to running an older version of iOS–7, I think'. But, the same behavior was later confirmed running Safari on El Capitain. Chrome, Firefox, and IE do not exhibit this behavior on any platform. Below, I explain the scenario and how I "fixed" the Safari bug.
Hey, where's my content?
Note: the issue referenced in this post has been fixed and will get released with ASP.NET Core 1.1.0.
While creating a small piece of middleware to modify the response body's content, I had trouble getting anything to appear in my browser. I would get a
200 response-code, but no content (i.e.
Content-Length: 0). Here is an example that creates a similar setup:
Turning GPS-points into a progress bar
In a previous post, I demonstrated creating a Twitter configuration provider for ASP.NET Monster's #SummerOfConfig contest. This post is a follow-up demonstrating how to create a provider leveraging GPS coordinates to create a unique type of progress bar. Source code available on GitHub.
Taking tweets to the next level!
This is the first in an eventual series of posts related to ASP.NET Monster's #SummerOfConfig contest. The general idea is to implement zany configuration providers (i.e. not the kind you would expect to use in a production environment 😁 ). For my first entry, Twitter has been enlisted to provide "on-the-fly" configuration values. Imagine having the ability to change aspects of your site just by Tweeting! Read on to see how this jazz comes together.
New behavior, implementation, and... name change?
Between the time I initially wrote about hybrid model binding, later about its updated behavior, and now, a series of changes were made to make the binding behavior safer and less verbose to implement.
Local testing and how to update existing discussion links
Using Disqus is an easy way to get a comment-system on your site. Part of its initialization requires passing a unique Id per page so it knows what comments to retrieve. However, if you like to test your sites locally before deploying to production and use the same identifier for both environments, then you will find your production Disqus links reference your local-URI. When someone wants to share a page using Disqus, the link will point to your local site (which
probably won't should not work for anyone but you 😉 ). However, there are several ways to keep the links up-to-date.
Why being greedy by default was the wrong approach.
In my previous introductory post on hybrid model binding, I demonstrated how a binder could be used with both body and URI content. After receiving feedback (thanks @buhakmeh), it became apparent being greedy by default was not the best option and would most-likely hinder adoption of the binder by the community.
For those who want the utmost flexibility in model binding.
Imagine you have a REST-ish API and your code follows the OMIOMO/Thunderdome principle.
GET-endpoints are easy to bind–just decorate the action-parameter with
[FromQuery]. But, what to do about
PUT? Now, there is content coming from the body of the request in addition to properies we want to bind from the URI. The oft-repeated answer is to have two or more parameters:
Get up and running in under thirty-minutes (depending on your skill-level, of course)
Here is the scenario for those of us who still use a pull-start mower:
you pull on the starter cord and instead of the usual feeling of the recoil spring being fully unwound, the cord keeps coming towards you. This is the end-result:
Why is it
Production and how can I change it?
So, your new web app. is ready for QA and you have all your app. settings neatly separated using
appsettings files. But, when you launch the app. on your brand new server, you know something is wrong and quickly realize the app. just loaded production settings. How do you correct this problem? There are several ways and they all involve setting the hosting environment's environment-name.
You will need this if you want to host multiple apps. on the same machine.
Back in the RC1 days, you could just pass an argument on the command-line to set the host URI. It went like this:
> dnx web myapp --server.urls="http://localhost:10000/"
Revealing data through image stacking
I recently read an article about integrating Azure Active Directory into an application. This allows the former to host login duties for the latter. The article contained several screenshots showing where to find information to complete the integration. The author obscured sensitive information by using Microsoft's Paint app. and its airbrush effect. One screenshot, in particular, contained a shot of the endpoints needed to handle logins of various technologies (i.e. WS-Federation, SAML-P, OAuth 2.0). However, this shot contained repeating information–a GUID that is part of a URI. Because the author manually obscured this data, the pattern of the airbrush effect varied between each row of URIs. Individually, the GUID could not be recovered. However, by stacking cropped frames of each row (seven in total), I was able to retrieve eighty-nine percent of the GUID (thirty-two out of thirty-six characters). What follows is a brief tutorial of how this was achieved. In this particular case, knowing the endpoint is not a crucial security leak, but the point that should be remembered is: repeating data intended to be obscured must be fully obscured. A better approach is to just not include the sensitive data in a screenshot–delete the particular section.
Note: this is only applicable for EF versions less than or equal to six. Version seven (part of .NET Core) has a completely different migration strategy.
Knowing whether a tree has the potential to crash into your house
Here is a classic scenario: Local would-be lumberjack decides to cut-down tall tree right beside house. Tree falls towards house. Disaster ensues. Others have a laugh at the homeowner's expense. This post will not help if you find yourself in a similar situation. Instead, this post will allow you to make an informed decision when that tree has a little bit of distance between itself and the house and its height makes the outcome a little blurry.
Why are my requests taking forever?
Update: this problem has been fixed and is confirmed working as-expected with the release of ASP.NET Core 1.0.
Or, numbers are fun and here is a way to wow someone
I love finding relationships in number-sets. A favorite memory from high school deals with a game we would play in Algebra class. The teacher would give us a set of numbers and one target number. The goal was to use the set of numbers and arithmetic operations to get to the target. Here is an example:
Is ordering the larger size worth the extra cost?
Took a short drive with the family to get lunch today. Among other items, we ordered small and medium-sized portions of fries. Everything tasted great, but I thought the amount of fries received between the two-sized boxes looked really similar. I began to think whether getting a medium was really worth the extra fourty-cents. So, I kept one of each and took some measurements to see whether ordering the larger size had any benefit. Ultimately, my interest is quantity per dollar. Keep in mind my method and results have some degree of error, but I will leave what percentage up to you.
Breaking down my own mental barriers
First off, Happy Pi Day! I have been putting off owning and running a personal website for a long time. It seems weird, too, since I work predominantly with software (see About me). There are many options for hosting and storing content. But, I
have had a tendency to over-think solutions to problems (i.e. Analysis paralysis). Over the course of several years, I built up this collection of ideas and never held myself responsible for making deposits into my idea bank (see Idea Debt). While the ideas are varied, most have a writing-part where I want to share the knowledge gained from completing the idea. And in this case, one idea was to create the engine which drove the display of my writings.