Most people I think have a rough idea of the steps involved in replacing a lost wallet or purse. Photo ID, bank cards, insurance cards, and if you're really unlucky, social security cards or birth certificates all need replaced. Sometimes in a certain order. And the things you have to do to replace each thing can often become mini projects of their own. Now enter the lost smartphone.
Replacing a lost smartphone includes everything that replacing a dumbphone involves such as contacting your service provider to discuss options for a new device, contract, or even a new service provider entirely. But smartphones have one really important element to them that you should know the implications of BEFORE you've lost yours: connectivity to your data. As of the time of me writing this, every smartphone I've seen to date: expects you to connect it to your data, and then caches the credentials you provided so that it can always access your data without you having to provide those credentials all the time. The upside to this is usability of course. Nobody wants to be typing passwords into any phone, like ever. But the downside is that the jackass that picked up your phone and walked off with it is now connected to your data. This means he gets to status jack you, dig through your email, and soon much more.
Smartphones and people are evolving together into so much more than something that allows us to call, text, and take pictures; they are becoming hubs into our data which we use to make decisions and take action. How many times have you pulled over pull up a route to somewhere, let someone know you're on your way, maybe put on some music or simply pull up an email that contains details of a something that needs thought through so you can figure things out along the way, such as the suite number you need to find of the interview you're headed to, or the campsite number where you are to rondevu with your friends and family. As people have come to trust smartphones to provide essential information, they also must trust that their data is accessible(even though battery life leaves a lot to be desired).
All the while, the cloud is omnipresent. Highly reliable and available are attractive specifications to smartphones wanting to deliver your data to you wherever and whenever you need it. And whether you are embracing the cloud, having it foisted upon you, or could care less, the cloud's ability to keep and dish out our data reliably and securely has thus create a celebrated, offensive or negligible (accordingly) marriage between it and your smartphone. And once you bless this union with your credentials, they don't need you anymore to stay connected.
In fact all they really need to be together is a data connection, some battery, and your credentials. This presents a few potentially potent problems when your smartphone fall into the hands of someone else AND it remembers your credentials. At least for now (until quantum computing), you don't have to worry about your phone spilling your password, thanks to one-way encryption. But while in the hands of its new owner, your data, sensitive as it may or may not be, is highly available to that person. Whether you get your phone back from its benevolent captor, status jacked for a good laugh, or have your identity stolen is simply a matter of how much the universe (dis)likes you. How concerned you are about this seems like it would be a function of how vulnerable you are when your data is in someone else's hands, and is as good a thing as any to risk-manage.
Fortunately, like replacing your wallet or purse, systems exist and are improving all the time for dealing with lost or stolen smartphones. The two I'd like to illuminate are GPS tracking functionality and what i'm going to just call "active session" management tools provided by the services that host your data. Instead of talking about them here myself, I will refer to posts which already exist to describe exactly these things.
Windows Phone GPS tracking
Android GPS tracking
Facebook active session management
Gmail active session management
Collection.OfType(WebLog)
Wednesday, July 17, 2013
Wednesday, May 16, 2012
Maybe you should leave those key lookups alone
So.... In my last post I shined a flashlight on the concept of creating covering indexes to eliminate key lookups for your queries. Turns out that covering indexes are killer to tables that endure constant updates. After adding covering indexes to several of these kind of tables, my database saves came crashing to a halt, overwhelmed with locks. I'm not sure yet what the answer is, but for the time being, I've made amends with those key lookups.
Monday, April 16, 2012
Eliminate those key-lookups
If you are developing for any database involved application that deals with a moderate quantity of data and you stick around long enough, you will find yourself investigating performance. Maybe you operate like our team did on a recent project where we started with some base expectations of performance, moved forward until gross disappointment set it, hacked at performance enhancements until we felt better about things, adjusted our expectations, and moved on. This cycle repeated itself many times and each time, I learned something new about how not to do a variety to things.
I won't spoil the fun for you, but if you are using SQL Server 2005 or greater, I will offer this one thing that I found enlightening: key-lookups in my query execution plans were my failure to understand(or care about) included columns. I would explain more myself, but that has already been done so very well in this post here by Joe Webb.
So this still counts as a blog entry right?
Cheers!
I won't spoil the fun for you, but if you are using SQL Server 2005 or greater, I will offer this one thing that I found enlightening: key-lookups in my query execution plans were my failure to understand(or care about) included columns. I would explain more myself, but that has already been done so very well in this post here by Joe Webb.
So this still counts as a blog entry right?
Cheers!
Friday, February 3, 2012
Comparing nullable dates
Sometimes working with Nullable<T> can be like arguing with a pedantic nerd. And while being able to do this effectively is probably not something you want to advertise in the skills section of your résumé, you can win friends by translating for such challenged communicators. Just as such, you can win programmer friends by writing extension methods that simplify overly verbose operations with... say... Nullable<DateTime>.
If you accept all that, then I present this here "friend catcher" to you. Keep the anecdote close to heart that with great power comes great responsibility and always remember that you cannot hold me responsible if you crash Facebook with all the new friends you amass. I will ignore any emails I receive blaming me so.
If you accept all that, then I present this here "friend catcher" to you. Keep the anecdote close to heart that with great power comes great responsibility and always remember that you cannot hold me responsible if you crash Facebook with all the new friends you amass. I will ignore any emails I receive blaming me so.
/// <summary> /// Compares two nullable dates using only the day, month, and year. /// Ignores hours, minutes, seconds... /// </summary> public static int DateCompare(this DateTime? dt, DateTime? compareDate) { DateTime? a = dt.HasValue ? dt.Value.Date as DateTime? : null; DateTime? b = compareDate.HasValue ? compareDate.Value.Date as DateTime? : null; return Nullable.Compare<DateTime>(a, b); }
Wednesday, November 30, 2011
Unlocking the power of IEnumerable T
Since becoming proficient with using LINQ to find shit, I have never looked back. That is until I run into collection types that I can’t immediately query with LINQ expressions. And it seems like every time I encounter such a collection, my first course of action is hate on it for a little while. ControlCollection.FindControl hardly counts as a way to find controls and NameValueCollection has no apparent way to find things just to mention a couple. This goes for any of your custom collection types as well, unless you implemented your own search methods.
So one thing I have found myself doing time and time again is adding an extension method called AsEnumerable() to these types so that I don’t have to hate them. This method returns the collection as an IEnumerable<T>, unlocking a pile of extension methods that allow me to query and otherwise manipulate said collection in more ways than I can imagine.
Many collection classes in the framework already provide such a method, but many still do not. Also note that the non-generic IEnumerable is not the same as the generic one and is far lesser in power compared to its generic counterpart IEnumerable.
As an example, lets do this for the ControlCollection class so we can find all the controls on a page that have a certain css class.
Now that the extension is in place, we can write some code like this to find what we want:
And for working with QueryStrings, this extension for the NameValueCollection class does the trick:
Allowing us to do something like this:
Go forth now and be cured of lame collection hate knowing that you can spend less time crawling collections and more time racing against the clock that is always counting, always ticking away at the relevancy of your current developer skill set. Hell, with all the extra time you can spend now writing LINQ instead of wrestling with iterators, think of how much longer you can procrastinate now on that certification your boss has pestering you about...
So one thing I have found myself doing time and time again is adding an extension method called AsEnumerable() to these types so that I don’t have to hate them. This method returns the collection as an IEnumerable<T>, unlocking a pile of extension methods that allow me to query and otherwise manipulate said collection in more ways than I can imagine.
Many collection classes in the framework already provide such a method, but many still do not. Also note that the non-generic IEnumerable is not the same as the generic one and is far lesser in power compared to its generic counterpart IEnumerable
As an example, lets do this for the ControlCollection class so we can find all the controls on a page that have a certain css class.
public static IEnumerable<Control> AsEnumerable(this ControlCollection controls) { foreach (Control ctrl in controls) { foreach (var subCtrl in ctrl.Controls.AsEnumerable()) { yield return subCtrl; } yield return ctrl; } }
Now that the extension is in place, we can write some code like this to find what we want:
protected void Page_Load(object sender, EventArgs e) { IEnumerable<Control>blueControls = Controls.AsEnumerable().Where(c => c.CssClass.Contains(“blue”)); }
And for working with QueryStrings, this extension for the NameValueCollection class does the trick:
public static IEnumerable<KeyValuePair<string, string>> AsEnumerable(this NameValueCollection col) { return col.Cast<string>().Select(key => new KeyValuePair<string, string>(key, col[key])); }
Allowing us to do something like this:
Request.QueryString.AsEnumerable().Where(c => c.Key == "someParameter");
Go forth now and be cured of lame collection hate knowing that you can spend less time crawling collections and more time racing against the clock that is always counting, always ticking away at the relevancy of your current developer skill set. Hell, with all the extra time you can spend now writing LINQ instead of wrestling with iterators, think of how much longer you can procrastinate now on that certification your boss has pestering you about...
Friday, March 12, 2010
Making Sharepoint RTE aways create a popup window for editing
stick this hackjob of a function in your head tag and call it at the end of your document.
function fixEditorButtons() {
// rewire rich text editor buttons to popup source view RTE window in content mode
var anchors = document.getElementsByTagName("A");
if(anchors.length == 0) return;
var rteArray = new Array();
// gather up the rich text editor edit buttons
for(var i = 0; i < anchors.length; i++) {
if(anchors[i].attributes.getNamedItem("title") != null) {
if(anchors[i].attributes.getNamedItem("title").value == "Edit Content") {
rteArray.push(anchors[i]); }}}
for(var i = 0; i < rteArray.length; i++) {
var oEditButton = rteArray[i];
// grab the code as SP created it
var code = new String(oEditButton.onclick);
// snag the control name of the RTE current display control
var controlnameBeginIndex = code.search(/RTE2_LaunchEditor/) + 27;
var temp = code.substring(controlnameBeginIndex);
var controlnameEndIndex = temp.search(/\'/);
var controlName = temp.substring(0,controlnameEndIndex) + "_displayContent";
// find where we need to insert our additional code that creates the popup window
var insertPoint = code.search(/cancelBubble/) - 67;
// build new code, start with old code
var newcode = code.substring(0,insertPoint);
newcode += "RTE2_SaveHtmlStateIfChanged('" + controlName + "');";
newcode += "var instanceVariables=RTE_GetEditorInstanceVariables('"+ controlName +"');";
newcode += "RTE2_LaunchEditor( instanceVariables.aSettings, instanceVariables.clientId,
instanceVariables.displayContentElement.id, instanceVariables.emptyPanel.id,
instanceVariables.hiddenInputField.id, instanceVariables.webUrl,
'True', false,true);";
newcode += code.substring(insertPoint); rteArray[i].onclick =
Function(newcode.slice(20,newcode.length - 1));
}
}
function fixEditorButtons() {
// rewire rich text editor buttons to popup source view RTE window in content mode
var anchors = document.getElementsByTagName("A");
if(anchors.length == 0) return;
var rteArray = new Array();
// gather up the rich text editor edit buttons
for(var i = 0; i < anchors.length; i++) {
if(anchors[i].attributes.getNamedItem("title") != null) {
if(anchors[i].attributes.getNamedItem("title").value == "Edit Content") {
rteArray.push(anchors[i]); }}}
for(var i = 0; i < rteArray.length; i++) {
var oEditButton = rteArray[i];
// grab the code as SP created it
var code = new String(oEditButton.onclick);
// snag the control name of the RTE current display control
var controlnameBeginIndex = code.search(/RTE2_LaunchEditor/) + 27;
var temp = code.substring(controlnameBeginIndex);
var controlnameEndIndex = temp.search(/\'/);
var controlName = temp.substring(0,controlnameEndIndex) + "_displayContent";
// find where we need to insert our additional code that creates the popup window
var insertPoint = code.search(/cancelBubble/) - 67;
// build new code, start with old code
var newcode = code.substring(0,insertPoint);
newcode += "RTE2_SaveHtmlStateIfChanged('" + controlName + "');";
newcode += "var instanceVariables=RTE_GetEditorInstanceVariables('"+ controlName +"');";
newcode += "RTE2_LaunchEditor( instanceVariables.aSettings, instanceVariables.clientId,
instanceVariables.displayContentElement.id, instanceVariables.emptyPanel.id,
instanceVariables.hiddenInputField.id, instanceVariables.webUrl,
'True', false,true);";
newcode += code.substring(insertPoint); rteArray[i].onclick =
Function(newcode.slice(20,newcode.length - 1));
}
}
Thursday, March 6, 2008
Are parents responsible the delinquency of teenaged SPLists?
Ever since I hooked up with Microsoft and began fathering little bits of softwares, I always thought that I would raise good code. However, like many have endured, one of my softwares began acting defiant and outrageous. We debugged the software repeatedly and how stubborn it was! Certainly didn't get any of that from MY influence! ahem! Lets get into the psyche of this little rebel a bit...
The victim of such a crime is one that wants the list for its views and is given this list as joke. How did I deal with such reckless behavior? Well, it didn't go down without a hairy fight thats for sure, but in the end, I taught it to return regular SPLists that were not special.
public static SPList GetListByName(SPWeb rootWeb, string listName)
{
foreach (SPList list in rootWeb.Lists)
{
if (list.Title.Equals(listName,
StringComparison.InvariantCultureIgnoreCase))
{
return list;
}
}
foreach (SPWeb web in rootWeb.Webs)
{
SPList resultList = GetListByName(web, listName);
if (resultList != null)
{
return resultList;
}
}
return null;
}
Take a look at the base case where the list is found and returned. Pretty standard stuff no? What is not (by even a far stretch of even the most eclectic programmer's imagination) obvious here is that the list being returned has a... how do I say this.... special Views property (of type SPViewCollection). The crime here is that these views are wrong. No, The collection isn't empty, it doesn't throw exceptions when you try to access it, it isn't null, it doesn't contain any number of views other than the amount of views it really does have, and the views aren't uninitialized or anything. They are wrong because they only have two columns, no matter what.The victim of such a crime is one that wants the list for its views and is given this list as joke. How did I deal with such reckless behavior? Well, it didn't go down without a hairy fight thats for sure, but in the end, I taught it to return regular SPLists that were not special.
SPSite s = SPContext.Current.Site;
SPList l = s.AllWebs[rootWeb.Name].Lists[listName];
return l;
Subscribe to:
Posts (Atom)