Welcome to Catalyst Blogs Sign in | Join | Help

This morning's keynote at PDC 2008 was all about MS Research.  I think a number of people weren't that interested with the first half of the keynote (judging by the number of people who left), but those that left missed a couple of great demos at the end -- primarily Boku and SecondLight (though the WorldWide Telescope final screenshot of the universe was rather cool).  While I do think the first part of the keynote got a little long-winded (it was mostly a discussion of the history of MS Research, the really smart people who work there, and their university partnerships), the second part (the demos) made up for it.

SecondLight looks like "Surface 2.0".  By rapidly turning on and off an LCD-ish panel (might have actually been an LCD -- missed that part) directly under the surface, the projector in the table was able to alternately project onto the surface and onto translucent objects held above the surface.  In the demo, a satellite image was projected on the screen, and a street map onto tracing paper held above it.  Of course, since the projector can target objects above the surface, the infrared camera can see infrared points in that area too, so the second part of the demo involved the system tracking the location of a surface held above the screen (the second surface had LEDs on the back for tracking) and projecting a pre-distorted image onto the secondary surface, even when it is held at an extreme angle.  It could even track touches on the surface (though I forget if the second surface was touch-sensitive or if it was the main infrared camera handling that).

SecondLight just "looks cool".  I'm guessing that some interesting applications will be created for it, especially in conjunction with being able to track the location of the second surface -- it might be a way to put a series of smaller "auxiliary" windows each with extra content above the "main" window on the surface.  Imaging editing a picture, then being able to literally *pick up* the tool window, change settings, and have it reflected in the main window.  It should be interesting to watch this progress.

Boku is a "programming environment for kids".  It's basically a simple event-driven programming model with a series of different "modes" (pages) each object can run off of (and the pages can be changed as a result of an event).  Objects can react to their word around them (see, bump, etc.), other objects, and the gamepad (to allow the user to control an object).  In the demo, a saucer and blimp were created.  The saucer was told to move with one control stick and fire missiles with the other.  Then, the blimp was told to shoot at the saucer when it saw it.  A couple more settings to make the blimp a "copyable" (basically a template of an object -- I forget the exact term used in the demo) and tell a cloud (which was made indestructible) to spawn a new blimp every 2 seconds, and now the player had an endless supply of blimps to shoot at them and serve as targets.

Boku is just downright amazing.  Yes, the characters are cartoon-ish, sure, and it doesn't have the power of a real programming environment, but I can tell you I would have spent a *ton* of time on something like this when I was a kid (and who knows -- when it comes out, I still may end up spending a bunch of time playing with it).  The ability to create a world where all the basics are taken care of and you're free to experiment and customize it to your heart's content is really interesting.  Assuming they include a mechanism to "build your own actor" using something along the lines of what Spore has, provide a way for users to share content with each other (freely I hope), and show of their achievements in each other's content, this thing will really have the potential to take off.  What aspiring programmer doesn't want to build games for them and their friends to play?  Who knows -- maybe it'll even be socially acceptable for kids to want to be *gasp* programmers?

So, SecondLight and Boku.  I don't think you can call MS Research boring -- they've got some slick stuff in the pipe.  I'm just hoping there's more where that came from.

So, I've been to two talks about Oslo and I still don't completely know what it's supposed to do :)  Long story short, I think this is going to be a little while before it's fully baked, but it does show some promise.  M (the language) sounds slick, and some of what Quadrant (the GUI modeling tool) can do looks really slick (as a data manipulation tool).  Getting the runtime right is going to be the tricky part.

Oslo is Microsoft's modeling-centric environment.  It has a textual language (M) for creating/working with models, a graphical tool for creating/working with models (Quadrant), and a series of runtimes to execute the models (eventually WCF/WF/IIS/"Dublin").  I haven't seen much of the runtimes yet, but from what I can see there's not a whole lot there yet, which I can understand -- a model-driven execution environment is *not* trivial to create.  Right now the runtime part appears to be limited to custom-written ones (over custom models described in a custom language).  MS is at least starting at the right place here -- with the tooling for building and working with the models (M and Quadrant), as well as the repositories.  It's a nice side benefit that these tools are immediately useful for other stuff (building grammars to parse data into C# objects to build small DSLs, like the one Don Box demonstrated in his part of the keynote on Tuesday with Chris Anderson).

Using M to specify a data model is very straight-forward, and defining a syntax for specifying it looks doable (though far from simple -- however, I didn't make the talk focusing on that part, so it may be easier than I think).  Plus, Oslo includes full syntax highlighting for the base languages and custom syntaxes in Intellipad (Intellisense Workpad -- a display surface in Quadrant is a Workpad).  The editor is also able to detect violations of constraints or custom syntax via the standard red-squiggly-line effect.

A couple of other notes from the sessions and the Q&A that followed them:

  • The first Oslo milestone was just a box-and-arrow tool, no textual tool, but the team soon realized that a tool like M was needed to allow people to express themselves in text.  Textual input is important.
  • In Oslo models, matching shapes == matching types
  • Oslo is not intended to solve the expedience mismatch between object model, SQL model, and XML model (it also won't solve world hunger)
  • Though the current toolkit can generate SQL create/inserts from an M model, but there is no SQL differencing -- will use eventually use another tech MS is working on for that
  • A custom function can be defined in M using LINQ syntax that will result be turned into a SQL function when it creates a database.

Also, a little tidbit that Don dropped during the M session:

  • There is a new XAML stack in 4.0 - completely decoupled from WF/WPF (both use this new stack)

In short, it sounds interesting (like almost everything I've heard so far at PDC), but I'm not seeing the short-term benefits.  Long-term?  Could be interesting.  I'll probably review the session videos on these once I get back home to make sure I'm fully understanding this, but if it stays the way I'm seeing it, I'll probably just wait-and-see where MS goes with this.

Plus, boot-from-VHD, mounting VHDs and more.  This should be interesting.

On my current project, we're in a 'make it faster' mode right now.  We've already knocked out a bunch of low-hanging fruit, and the profiler is telling me that about 10-15% of my time is spent by CSLA looking up authorization rules in a Dictionary<string,X>.  So, I got to thinking: is there something faster than a Dictionary<K,V> that we could use here -- is there a better data structure?  As my mind floated back to my college algorithms and data structures classes, my first thought was a form of a Trie, probably with element compression (to reduce the number of nodes in the tree).  Then I got to thinking -- well, in this case, my list of strings (the names of the properties of my object) are known when the data structure is built.  A few searches later, I stumbled across this blog post by Jomo Fisher: http://blogs.msdn.com/jomo_fisher/archive/2007/03/28/fast-switching-with-linq.aspx

Here's the basic idea: let's say you need a piece of code that is given a value as input and based on that value returns some other value.  You have a list of all possible inputs and the desired output for each when starting.  The first approach many of us would use is to load all the input/output pairs as key/value pairs into a Dictionary<K,V>, then call use dictionary[input] to get the output.  However, the lookup will then require calling string.GetHashCode for the input, then finding the bucket corresponding to that hash code, compare the input value to the key of the first item in the bucket to confirm it matches, then return it.  That requires two full passes through the input string.

Here's how Jomo's technique is different: instead of the dictionary, you build a LINQ expression that uses several cheap properties of your possible inputs to figure out which one it is (Jomo's example uses the length and as many characters as needed to separate the inputs -- at most 1 in his example).  Then, you call the Compile method of the expression to get a delegate to a dynamically-generated method that follows the input->output mapping provided.

Jomo's tests were showing 900% increase in performance using this technique over a dictionary.  Granted, most of us don't write applications that are this CPU-bound for simple things like lookups, but it is definitely an interesting technique I'd never seen LINQ applied to, and it's hard to argue with a performance increase that doesn't result in a readability decrease.  Before this, the way to handle this would have been to either write a program that took the static list as input and output C# code (as Jomo's initial example), or using DynamicMethod and writing the code in IL.  Both are so much of a pain that it's rarely worth doing.  This technique is easy enough that it just might get used sometimes.  This looks like one of those things I'll have to file away for those couple of times a year when I have a stubborn performance problem to tackle -- dynamic code generation with LINQ.

I'm currently working on a simple online-store-like app that includes several pictures of the items for sale.  We're using the new Dynamic Data extensions and LINQ-to-SQL to handle most of the heavy lifting, but I ran into a problem this morning.  On my 'list' screen (the one that shows several of the items for sale), I wanted to display one of the images for each item.  Simple, I figured.  I added a property to the user control we use to render the whole list of images on the detail screens and added a property to control whether it showed one image or all of them.  Then, in the OnDataBinding method, I added code to check for that property and only load the data for one of the child images if it was set (as opposed to loading the data for all of them like we did on the detail pages).  I added the DynamicFieldControl entry to the list screen to display this field and set the 'only show one image' property, but no luck -- I got no image.  I added a breakpoint and sure enough, the Images EntitySet had a count of 0 and was marked as loaded.  When I clicked on my link to see the details, I saw all the images without issue.  So, I started digging....  In System.Web.UI.WebControls.LinqDataSourceView, I found this code:

image

I saw the 'CanDelete/CanInsert/CanUpdate' check and it made me curious....  Here's the declaration of the LinqDataSource from my details screen (that worked):

    1     <asp:LinqDataSource ID="DetailsDataSource" runat="server" EnableInsert="true" EnableUpdate="true" TableName="Items" >

    2         <WhereParameters>

    3             <asp:DynamicQueryStringParameter />

    4         </WhereParameters>

    5     </asp:LinqDataSource>

And here's the code from my list screen that didn't:

    1     <asp:LinqDataSource ID="GridDataSource" runat="server" TableName="Items">

    2         <WhereParameters>

    3         </WhereParameters>

    4     </asp:LinqDataSource>

So, on a whim, I added 'EnableInsert="true"' to my list screen, and sure enough, now my child collection is getting populated like I need.  I'm not sure why this makes a difference (well, I know it leaves object tracking enabled, but I don't know why that makes a difference), but "it works for me"...

The Sharepoint installation I've been working on recently has a number of sites, with custom security applied to each one of them (to allow only the specific group access to it) -- ie. the normal way to do it.  These sites are all publishing sites, as they wanted to be able to have a bunch of content up there, plus some other lists of things.  The problem was, users that they thought were just 'normal' users were editing the main page of the site, ie. "default.aspx' in the 'Pages' document library.  I was asked to take a look at the permissions to determine why the users of the site were able to edit the pages.  After a couple of quick checks, I found their 'normal users' group was given a permission that included 'Edit Items', which allowed them to edit the items in the 'Pages' document library.  They replied that the users shouldn't be able to edit it because they didn't have the 'Add/Edit Pages' permission.  It turns out, that permission is only for editing pages in the way that Sharepoint Designer does -- ie. without a document library.  The proper way to prevent 'normal' users from editing the published pages in the site is to disable permission inheritance for the 'Pages' document library, and configure the security on that list to not give the 'edit items' right to the 'normal' users.

The lesson?  The 'Pages' document library isn't special, at least when it comes to security.

Thanks to Chris Domino for confirming my understanding of how these permissions worked.

Yesterday, Josh brought our Community Server installation up-to-date, including adding Live Writer support.  I've never actually used Live Writer before, but I figured I'd give it a shot if Josh was high enough on it to spend a Sunday afternoon tinkering with CS so he could use it.

Though I've never used a client application to post to my blog (I always just used the web tools with CS), I'm impressed by Live Writer.  I looks like it has quite a few bells and whistles I'll never use, but it does the simple stuff right -- it lets me compose my thoughts offline and upload them when I'm ready.  And, things look good enough that I don't feel like I have to switch to HTML view and clean them up so it'll flow right.   I had a couple of blog posts I'd been meaning to get written -- I had the code together and knew what i wanted to say, I just had to find time to write them out and post them.  I set up Live Writer while I was in the office today, and now as I ride the train, I can write these posts, and sync them up when I get connected.

It Just Works.

Who knows, maybe I'll start to post more often if it's this easy?

I've been doing a lot of work in Sharepoint recently, including several small features to allow advanced users to dig around in some properties that Sharepoint doesn't expose very well, as well as run some searches that would be nearly impossible from the normal UI.

Of course, I could just drop files in the layouts directory and tweak templates and such, but I want to make this easy to deploy, and just as easy to remove from the server if I ever have to.  So, I've created a full WSP to deploy (with all the XML goo that needed -- way to much in my opinion, but at least it works...) and I've deployed and undeployed it several times from my test server trying to get it just right.  While running through final fit-and-polish checks before I send it off to my users for testing, I noticed that on one of my test sites, my link shows up twice on the 'Site Actions' menu, but when I retract the feature, it disappears completely.

I probably could have let it go, as none of the other sites were having a problem, but one morning on my train ride into the city, as I'm in that stage where I'm not quite awake, but not actually asleep, I realized what was different about that site -- that's the site I was initially testing my feature on before I changed it to a farm-wide feature.  Once I made my way into the office and fired up my tools, I retracted the solution, changed it back to a web-specific solution, and deployed it again.  Sure enough, I went to the site actions menu for the 'buggy' site, and it showed my item listed once.  In the site features, it was activated.  I deactivated it, retracted it, changed it back to farm-wide, and deployed it again.  All was well.

Apparently, if you initially deploy a feature as web-specific and activate it on a web, then later retract the feature without deactivating it for the web (which did actually warn me as I recall), the reinstall the feature, the feature will still be active for that web, even if you've changed the feature to be farm-wide instead.  That's how you end up with it active twice for that web, once at the web level, once at the farm level.

Lesson: if you're going to change the scope of a feature, make sure you de-activate it everywhere first.

The other day I was given a bug to investigate -- a Sharepoint webpart that asked the user for some input, impersonated a domain user and updated a file wasn't working right -- it failed with a permission error.  On the test server though, things were working fine.  The code matched, the user had all the permissions in the right places, the only difference was that on the test server, the folder was on a local drive, on the production server, the folder was on a network share.  After changing the test server to write to a remote server, it started failing as well.

So, for some reason, my impersonation is good enough to write files to the local machine, but not good enough to write them to a remote machine.  I know that 'normal' impersonation (ie. web.config-based connecting user impersonation) is only good for one hop -- to the server.  The server cannot use those credentials to make a request to another machine (like a database server).  Enter NTLM vs. Kerberos.  If you use the 'normal' impersonation code (http://support.microsoft.com/kb/306158), apparently you can't leave the machine.  However, if you explicitly ask for 'new credentials' from the 'WinNT50' provider, you get a Kerberos token, which *is* good on a remote machine, which solved my problem.

public void Operation(string sUser, string sDomain, string sPassword)

{

     // MS-recommended impersonation implementation - http://support.microsoft.com/kb/306158

     // normal tokens (LOGON32_LOGON_TYPE.LOGON32_LOGON_NETWORK / LOGON32_PROVIDER.LOGON32_PROVIDER_DEFAULT) don't work to access remote file servers

     // using kerb tokens per http://www.thescripts.com/forum/thread263595.html

     if (LogonUser(sUser, sDomain, sPassword, LOGON32_LOGON_TYPE.LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER.LOGON32_PROVIDER_WINNT50, token) != 0)

     {

         // use token here as per http://support.microsoft.com/kb/306158

     }

}

 

 public enum LOGON32_LOGON_TYPE : int

{

     LOGON32_LOGON_INTERACTIVE = 2,

     LOGON32_LOGON_NETWORK = 3,

     LOGON32_LOGON_BATCH = 4,

     LOGON32_LOGON_SERVICE = 5,

     LOGON32_LOGON_UNLOCK = 7,

     LOGON32_LOGON_NETWORK_CLEARTEXT = 8,

     LOGON32_LOGON_NEW_CREDENTIALS = 9,

}

 private enum LOGON32_PROVIDER : int

{

     LOGON32_PROVIDER_DEFAULT = 0,

     LOGON32_PROVIDER_WINNT50 = 3,

     LOGON32_PROVIDER_WINNT40 = 2,

     LOGON32_PROVIDER_WINNT35 = 1,

}

http://blogs.msdn.com/sharepoint/archive/2008/02/11/announcing-the-final-release-of-vsewss-1-1-and-the-upcoming-version-1-2.aspx

Plus, 1.2 is announced with VS 2008 support. 

Now, if only I could figure out how to hack this to work without requring Sharepoint on the same box...  On my current project, I don't have access to a W2K3 server to develop on, so I'm stuck on a Windows XP machine.

UseAccessibleHeader="true" of course.  What did you think it'd be called, "UseTHTag" or something reasonable?  We can't do that, you might be able to figure it out on your own that way.

Friday morning, one of my co-workers idly remarked about something that occasionally happens to all of us -- we write an email and in some way reference a file we're intending to attach, but forget to attach the file.  Especially if you're sending a build to a client and leaving for the day right away, this can be quite annoying.  He rightly wondered aloud why Outlook doesn't warn you about that.

That evening on my train ride home, my mind wandered back to that comment, and I remembered that I installed the latest VSTO for Office 2007 a few weeks ago, so I thought I'd see how hard it would be to write an addon for Outlook that did just that.  So, I fired up VS 2008 and created an Outlook Addin project, and got this:

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
}

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}

After checking for instance variables, I noticed an 'Application' object.  So, I checked it for events, and found an 'ItemSend'.  A quick hook of the event (and unhook in the shutdown to be clean), and I had the ability to run my code when I wanted -- just before a message was sent.  I added the checks and sure enough, I had a working version of the code in about 5 minutes.

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
  this.Application.ItemSend += Application_ItemSend;
}

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
  this.Application.ItemSend -= Application_ItemSend;
}

void Application_ItemSend(object Item, ref bool Cancel)
{
  Outlook.MailItem mailItem = Item as Outlook.MailItem;
  if (null != mailItem && mailItem.Attachments.Count == 0 && mailItem.Body.ToLower().Contains("attach"))   {
    if (MessageBox.Show("There are no attachments on this message and by the content of your message, it appears " +
      "you may have intended to attach something. Are you sure you want to send this message?",
      "Are you sure you want to send this message?",
      MessageBoxButtons.YesNo,
      MessageBoxIcon.Question,
      MessageBoxDefaultButton.Button2) == DialogResult.No)
    {
      Cancel = true;
    }
  }
}

Finally, something that was actually as simple to do as it seemed it should have been.

I haven't been developing for Sharepoint recently, so I missed this - the VSeWSS 1.1 CTP (download).  I had been looking at examples that manually created all the needed XML files and used MakeCab to assemble everything, but this is *much, much* easier.

Add project, select WebPart, add in the code I need, go to Build-Deploy, and it's deployed and working on my local Sharepoint installation, and the command file and WSP needed are sitting in my release directory to be used to deploy the code to a production server.

Now I don't have to worry so much about when I'll do when the SmartPart can't handle the level of integration I need.

The project I'm currently working on is using unit tests will nearly full code coverage to ensure things continue to work as we refactor the code.  Today, I was working on writing the unit tests for some code that adds some logging to exceptions throw by code it's calling.  To test this, I created a mock class with a method that threw an exception and ran the test.  I got an "Exception was unhandled by user code" error, with Visual Studio highlighting the line where I threw the exception.

Looking at the call stack, I could see why VS thought the error was unhandled, as the 'caller' was the class under test, a dynamically generated proxy.  Since VS didn't think I built the class (and doesn't have source for it), it assumed it is non-user code.  Since my (mock) class was throwing an exception back to that code, VS thinks it's going from a user class (the mock) to a non-user class (the generated code).

Workaround?  [DebuggerNonUserCode] on the method in my mock.  Now, VS thinks that method is also non-user, and doesn't complain.  However, I still think this isn't quite the right solution.  Maybe I should modify the generated classes to claim they are user code?

Well, at least now I can run all the tests under the debugger without it pausing.

A few weeks ago, I finally got around to joining my laptop to our internal domain -- our admin says some of the new Exchange 2007 stuff I'll want to play with will require it.

Today, when I went to our Sharepoint site to fill out my timesheet this morning, it challenged me for my password.  I thought this was odd, as it's using standard windows (NTLM) authentication off our domain, which I'm now logged onto my laptop as a member of.  It should 'just work'.  After a bit of digging, I found that IE 7 now doesn't automatically attempt to log on to every server that supports NTLM.  I seem to remember that a previous version (maybe 5?) did, but no matter. 

All I needed to do was add the sharepoint site to the 'intranet sites' list, and everything authenticated automatically like I was hoping.

More Posts Next page »