Sunday, August 20, 2023

Pixel Phone Owners using eSIM - Get a Backup physical SIM immediately!!!

I was on vacation and my billing cycle ended with Google Fi.  I had changed my subscription plan mid-month so it would upgrade to unlimited data for the next billing month because I would be mostly travelling that month. 

A plan change must initiate an eSIM update and it failed. Not only did my plan upgrade fail to apply, but I could not get any service activated on my phone from Google Fi then.  Hours on chat with Google Fi, numerous emails with screenshots and debug logs back and forth, and resetting my phone twice.  Nothing allowed the Google Fi app to activate my eSIM.

Two weeks later and I returned back to the states and got a new physical SIM for Google Fi and everything works now. Googling, you'll find numerous reports of users with Pixels and eSIMs that stop working. Some blame security patches in Android, some blame the carrier (Google Fi), some blame the Pixel hardware. All I know is you can't trust eSIM and when it's broken, no cell service makes it difficult to do a lot of things. I will never trust eSIM technology again. And I think I may travel with a backup SIM card even. I learned that lesson the hard way.

If you use Google Fi, they'll send you an SIM card for free: https://fi.google.com/order-sim.  Do it now!

Monday, September 30, 2019

Override xaml.xml files in the ~/sitecore/shell/override folder

Occasionally you'll have the desire to add your own custom functionality to dialogs in the Content Editor.  Many of these dialogs can be found under the ~/sitecore/shell/ folder.

Sitecore already comes pre-configured to look in the ~/sitecore/shell/override to find override XmlControls under the node.  That is baked into the Sitecore.config file.

<controlSources>
  <source mode="on" namespace="Sitecore.Web.UI.XmlControls" folder="/sitecore/shell/override" deep="true"/>

This allows you to drop into that folder your customized .xml dialog file that contains your own layout and custom CodeBeside.  The Content Editor will load that one instead of the Sitecore coded one.

However some of the controls under the ~/sitecore/shell/ folder are built with a different technology.

(To read more about the two different control types, Mark Stiles has done an amazing job at documenting them: https://markstiles.net/blog/2014/1/5/sheer-ui-1-a-tale-of-two-systems/)

The extension of these controls is xaml.xml.  Sitecore defines where it finds these controls in the xamlSharp.config file.  Oddly enough, this one doesn't include the  ~/sitecore/shell/override folder.

It is simple to create your own override config for this in Sitecore.

1. Create a new file called xamlSharpOverride.config

2. It should contain the following:
<configuration>
  <sitecore>
    <xamlsharp>
      <sources>
        <source type="Sitecore.Web.UI.XamlSharp.Xaml.XamlFileControlSource,Sitecore.Kernel" patch:before="*">
          <watchers hint="list:AddWatcher">
            <watcher type="Sitecore.Web.UI.XamlSharp.Xaml.XamlFileWatcher,Sitecore.Kernel">
              <folder>/sitecore/shell/override</folder>
              <filter>*.xaml.xml</filter>
              <codefilter>*.xaml.xml.cs</codefilter>
              <includesubdirectories>true</includesubdirectories>
            </watcher>
          </watchers>
        </source>
      </sources>
    </xamlsharp>
  </sitecore>
</configuration>

This config will insert that source folder at the top of the xamlSharp sources list.  Any .xaml.xml file you customize can now be placed into the ~/sitecore/shell/override folder.

Wednesday, May 1, 2019

You can skip the WITH(NOLOCK) when querying Sitecore's dbo.Fields sql view

Don't worry about adding a NOLOCK hint to your SELECT queries against the Fields view in Sitecore.  They already include that hint on all of the tables.


SELECT id, 
       itemid, 
       '' AS Language, 
       fieldid, 
       value, 
       created, 
       updated 
FROM   dbo.sharedfields WITH (nolock) 
UNION ALL 
SELECT id, 
       itemid, 
       language, 
       fieldid, 
       value, 
       created, 
       updated 
FROM   dbo.unversionedfields WITH (nolock) 
UNION ALL 
SELECT dbo.versionedfields.id, 
       dbo.versionedfields.itemid, 
       dbo.versionedfields.language, 
       dbo.versionedfields.fieldid, 
       dbo.versionedfields.value, 
       dbo.versionedfields.created, 
       dbo.versionedfields.updated 
FROM   dbo.versionedfields WITH (nolock) 
       INNER JOIN (SELECT itemid, 
                          language, 
                          Max(version) AS Version 
                   FROM   dbo.versionedfields AS VersionedFields_1 WITH (nolock) 
                   GROUP  BY itemid, 
                             language) AS b 
               ON dbo.versionedfields.itemid = b.itemid 
                  AND dbo.versionedfields.language = b.language 
                  AND dbo.versionedfields.version = b.version 

Wednesday, October 10, 2018

Alexa Skill Developer #1 Support Issue for Me

I took a long hiatus from building skills and am just getting back into it.  I made some dumb mistakes getting stuff to work.  But recently I realized it wasn't always my dumb mistakes.  I ran into an issue twice where all I had to do was "reboot" my Alexa skill.  Equivalent of the the favorite help desk suggestion of turn it off and back on again; unplug it and plug it back in.




Flipping the Test is enabled for this skill was required a couple of times that I remember.

  1. I updated my invocation phrase and rebuilt my models, but things did not work right until I toggled this switch.
  2. After having my certification fail, I tried testing my interactions again and my skill didn't respond.  Toggling the switch fixed that also.
So, when all else fails... flip this switch off and on again.

Friday, August 18, 2017

Don't Let Microsoft SQL Round Your DateTime Field's Milliseconds

I needed to export some data out of Application Insights and save it locally.  While doing a sanity check, I realized that some of my datetime values were not the same.

Therefore, I created a simple test.
  1. Create a table with just a datetime field.
  2. Insert the value I expected.
  3. Select that data back out and witness the rounded value.



I finally found an answer here:
https://stackoverflow.com/questions/36414315/inserting-datetime-with-milliseconds-into-sql-server-table-issue

MS SQL rounds the DateTime field in increments of .000, .003, and .007.  I would assume that means it is saving on memory space behind the scenes by only offering 3 options for the single digit of milliseconds?

Whatever the case, if precision is necessary (as it was for the Application Insights data I was getting),  use the newer datetime2(3) field definition.

Friday, January 6, 2017

Why do I have a binding for SitecoreApplicationCenter in my web.config?

I was doing some cleanup in our config files, and I noticed we have a binding called "SitecoreApplicationCenter".  Looking through our Sitecore solution, I didn't see this referred to anywhere, until I opened the Sitecore.Kernel.dll.

This reference is used when communicating with Sitecore's App Center... just like it's named.  It will be used when making calls to the service: https://apps.sitecore.net/appsservice.asmx

We'll never use this on our frontend servers, so I transformed it out of that config.  But I kept it in our Content Manager server config.

Friday, December 2, 2016

[HttpException (0x80004005): Unable to validate data.] when changing FormsAuthentication machineKey encryption

A new feature on our website required us to use a different encryption algorithm for our Forms Authentication cookie.

Simple change; just update one line in the web.config.  However we read data from that cookie on every web request.  And so as soon as we changed that algorithm, anyone who had previously visited our site would get an ASP.NET yellow screen of death.

"Unable to validate data." ASP.NET error message screen


No problem, I thought.  I can just delete that cookie instead of reading it.  That turns out not to be so easy to do.  The best I could do was set an expiration on the cookie in the client response.  And then I also deleted the cookie in the server request.

// Remove the cookie from the server request
contextBase.Request.Cookies.Remove(FormsAuthentication.FormsCookieName);
                            
// Expire the cookie on the client
authCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Remove(authCookie.Name);
Response.Cookies.Add(authCookie);

This got me past some errors, but somewhere deep in someone else's DLL the problem still lingered.  I tried a different approach.  I resorted to using a base Forms Authentication method, SignOut().  That worked perfect!  Here is the code I ended up with.  It was placed in the Global.asax Application_PostAuthenticateRequest() event.

protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
    var contextBase = ServiceLocator.Current.GetInstance();
    var authCookie = contextBase.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie != null)
    {
        var encodedTicket = authCookie.Value;
        if (!String.IsNullOrEmpty(encodedTicket))
        {
            FormsAuthenticationTicket ticket = null;
            try
            {
                ticket = FormsAuthentication.Decrypt(encodedTicket);
            }
            catch(HttpException hex) 
            {
                if(hex.Message == "Unable to validate data.")
                {
                    // Clean up any AUTH cookies with 
                    // a different encryption
                    FormsAuthentication.SignOut();
                    return;
                }
            }
            // Unimportant company stuff happens here
        }
    }
}