Tuesday, October 13, 2009

SysFader Hater

I recently encountered the SysFader error within Internet Explorer 8 on Windows 2k3 R2.

This initially worried me because it was within a page I had built that contained some jQuery animation. It turned out it was not just my page though – at least MSN, Amazon, and MajorGeeks caused the same error to appear. That seemed like a decent enough variety to assume it was not just my page.

There are some good posts about the SysFader error out there:

This error seems to have been around for a while – third link above is a thread that spans nearly 2 years.

I tried some of the proposed ‘fixes’ out there – with no success. I admittedly did not try that hard on the ones that had me turning off animation effects and 3rd party browser extensions within IE – since 1) I like me some animations & extensions and 2) The animation effects have been working fine for years, why would I suddenly need to turn them off? (No, I don’t fear change at all…)

There is even a post that points the blame at poor innocent MOSS: http://biztalkdev.com/blogs/paulwu/archive/2007/03/09/IE7-Crash-when-accessing-MOSS-2007.aspx This was interesting because the page that initially threw the error at me was MOSS-based. I also DID NOT attempt to disable the OWSSUPP.DLL ActiveX control since it had been working well for a while and as I mentioned earlier, I was seeing the error from other sites that were definitely not MOSS-based.

Even tried reboot – no dice. Scary because that was the second time in the past month that reboot has failed me!

So how I fixed it: Actually, it was pretty easy. I reinstalled Adobe Flash 10. Not sure what the minor version that I had was, but I had updated Flash recently on the affected machine and it was version 10 – so I may have reinstalled the current version – or at most it was a minor version update. Either way, the net effect of reinstalling flash and restarting IE was that the Sysfader error was a nothing but (a) bad memory.

Later SysFader!

Friday, October 9, 2009

Web Parts Down: A SharePoint Tragedy

Prologue:

There are times when I am a click or two away from registering some derivative of IHateSharePoint.com or SharePointIsKillingMe.com or WasSaneBeforeSharePoint.com. I was VERY close after encountering the following problem…

 

Act I Scene I

I had been through the Code – Build – Debug cycle with this particular feature numerous times (especially the Debug step). Suddenly one of the builds resulted in the informative web part error:

Web Part Error: A Web Part or Web Form Control on this Page cannot be displayed or imported. The type could not be found or it is not registered as safe.

…which I have seen before – but usually only when the web part is first deployed. 99% of the time this error is caused by the entry for your web part in the SafeControls section of the web.config file. It usually boils down to something like a spelling error, the namespace, assembly version, etc.

ACT I Scene II

Remove the code I just added. No dice – same issue.

ACT I Scene III

IISRESET. Strike two – same issue.

ACT I Scene IV

Remove code I added several builds previous. Same issue.

ACT I Scene V

Re-add the feature and web part to the page. Adding web part fails. Interesting. Upon navigation to home page, notice that ALL web parts are showing errors – even the out of the box ones. Also interesting in a ‘just what I needed’ sort of way.

 wp_error2

Intermission

Magic reboot. Same issue. Strange, because magic reboots rarely fail to resolve issues.

 

ACT II SCENE I

Hit up the internet to see what he knows. Typical stuff: make sure there is a SafeControls entry, make sure it is right, etc. etc. Found some good posts about what to check. Here are a few of them:

Check on all of it for me though – double checked in fact. Re-add assemblies to GAC just in case. Same issue.

ACT II SCENE II

Restore a web.config from previous day. SAME ISSUE.

Act II Scene III

Crank up ULS logging level to the deepest depths of verbosity – you know, the ‘disk filler and killer’ levels. But they gave me no additional information – showed me the same as what is rendered within page…

Act II Scene IV

Restore web.config from previous month. All web parts back up except the one I had been working on, which did not exist a month earlier.

Epilogue

So it was web.config related, and also probably an issue with my custom web part. After some experimentation, it turned out to be the entry in the SafeControls section. But not because it was invalid – remember I checked that in act 2 scene 1 – it was because the assembly could not be loaded because one of its dependencies could not be found. Why could it not be found? It was not in app’s bin folder or in GAC. Easy enough to fix once I finally found the real problem. My questions are:

> Why did this not show up as an error somewhere? I could have solved it within minutes rather than burning an entire afternoon.

> Why did this kill ALL SafeControls in the SafeControls section of the web.config, and not just the ones within the problematic entry? If there is a problem with a SafeControl node, the typical behavior is that it only affects anything in that namespace, not every SafeControl node.

 

Pray for no sequel!

Tuesday, September 1, 2009

Web Part wrapper for the Google Dynamic Feed Control

If this is out there, 2 minutes of searching couldn’t find it. Interesting little exercise even if it is out there.

The out of the box SharePoint 2007 RSS Viewer web part is pretty lame. It is pretty much the Xml Web part with 300+ lines of ready made XSL. This might just be my opinion, but XSL is only really interesting the first time you do something with it. After that, you can have it back – especially when it comes to debugging it.

So I was looking around for a pinch hitter for the out of the box RSS web part and came across the Google Dynamic Feed Control. This is what it looks like in vertical mode with the default CSS applied:

dynamicfeed

Works well. Looks good enough. Free. What more could one ask for? How about the following advantages over the RSS Viewer web part:

  • Can consume both RSS and Atom feeds.
  • SSL Friendly – can consume an HTTP feed from an HTTPS site without the annoying security warning dialog. This is actually a pretty important advantage if you are within an SSL site.
  • Aggregation – it can handle more than one feed.
  • Built in AJAX updates. Side bonus: It won’t cause script errors – specifically the infamous ASP.NET pendingCallbacks bug – if there is more than one instance on a page.
  • Superior UI and use of screen real estate.
  • Does not require XSL manipulation to change.
  • No half-baked loading bar graphic. Where did that thing come from anyways? If it played the Knight Rider theme while it loaded or a KITT sound effect, it would possibly have some value.

CRPERSPC

This javascript control is built on the Google Feeds API, and as with all of Google’s ‘free’ stuff, the integration point for this is within the client tier via javascript. This will make it easier for Google to steal your customers in the future. I like to joke around – but unfortunately that was not a joke. Having their API’s all javascript – and therefore in almost all cases from the client tier – is a brilliant move. But only for them – and maybe the rest of us who take advantage of their price points in the short term.

OK – digression phase complete. I set out to create a web part wrapper to make the incorporation of this control into a SharePoint site easer. The web part essentially generates the javascript required to initialize and render the control using the Google API.

Web Part Construction

Within the web part, there are essentially three main pieces:

  1. Create personalizable properties that allow the web part to be customized.
  2. Get the Google Ajax API and the Dynamic Feed Control scripts into the page.
  3. Render the client script that loads the control based on the configured properties and the containing HTML element (just a DIV).

Step 1: This is pretty standard web part stuff. Some of the customizable properties I created:

  • FeedURL – Allows the specification of an RSS/Atom feed. This can be a semicolon delimited list to show multiple feeds. I know - a crude way to do it – but we can save the custom editor for a rainy day.
  • PageSize – How many records to show.
  • DisplayTime – How many seconds to show the details of an item before moving on to the next one. The Dynamic Feed Control continuously cycles through the items in the list and displays the details of one item at a time.
  • CssUrl – the url of the stylesheet containing the classes used in the markup. The schema for the CSS is outlined here.

Step 2: The core Google javascript does not do well if it is not loaded into the page before content – or more importantly other scripts – are rendered. In other words, it needs to be in the HEAD section. This means that the normal means of doing this – using the regular Page.ClientScript.RegisterClientScriptBlock method – will not be good enough, since that loads scripts into the BODY section. One way to get script into the HEAD section is to add to the Page.Head.Controls collection. So here is the code to register the Google JSAPI core – and the Dynamic Feed Control:



Code Snippet



  1. protected virtual void RegisterScripts()
  2. {
  3. if (CanRender)
  4. {
  5. //add scripts to header - the registered block is used just as indication that we already
  6. // added the script to the page
  7. //google jsapi script does not do well if it is not already loaded into head section
  8. if (!Page.ClientScript.IsClientScriptBlockRegistered(this.GetType(), GoogleAjaxKey))
  9. {
  10. Page.ClientScript.RegisterClientScriptBlock(
  11. this.GetType(),
  12. GoogleAjaxKey,
  13. string.Empty);
  14. Page.Header.Controls.Add(new LiteralControl(string.Format(ScriptLinkTemplate,
  15. string.Format(GoogleAjaxUrl,
  16. HttpContext.Current.Request.Url.Scheme,
  17. string.IsNullOrEmpty(ApiKey)
  18. ? string.Empty
  19. : string.Format("?key={0}", ApiKey)))));
  20. }
  21. if (!Page.ClientScript.IsClientScriptBlockRegistered(this.GetType(), GoogleDynamicFeedKey))
  22. {
  23. Page.ClientScript.RegisterClientScriptBlock(
  24. this.GetType(),
  25. GoogleDynamicFeedKey,
  26. string.Empty);
  27. Page.Header.Controls.Add(new LiteralControl(string.Format(ScriptLinkTemplate,
  28. string.Format(GoogleDynamicFeedUrl,
  29. HttpContext.Current.Request.Url.Scheme))));
  30. }
  31. }
  32. \




Step 3: Rendering the script is just string manipulation. It is possible to get really fancy when building javascript dynamically within C#, but sometimes you can’t beat a good old fashioned StringBuilder. The most important thing to get right is the order – you do not want something to reference script that has not loaded yet or an object that has not yet been defined. So the general order here will be:

Body Load > Google Feeds Load > Dynamic Feed Control Load

which translates to (all javascript):

_spBodyOnLoadFunctionNames this allows us to add a function to be called when the SharePoint-rendered DOM is loaded

google.load('feeds'…) this loads the Google feeds api – used by the dynamic feed control

new GFdynamicFeedControl() creates the javascript object – it will do the rest

The rest of it is the dynamic generation of the options objects based on the configured property values (remember step 1?) Here is what I mean – actually pretty simple:



Code Snippet



  1. protected virtual string BuildFeedOptionsScript()
  2. {
  3. StringBuilder script = new StringBuilder();
  4. script.Append("var options = {");
  5. script.Append("stacked : true, ");
  6. script.Append("horizontal : false, ");
  7. script.AppendFormat("numResults : {0}, ",
  8. PageSize);
  9. script.AppendFormat("displaytime: {0}, ",
  10. DisplayTime * 1000);
  11. script.Append("fadeOutTime : 1000, ");
  12. script.Append("scrollOnFadeOut : true, ");
  13. script.AppendFormat("title : \"{0}\"",
  14. Page.Server.HtmlEncode(this.Title));
  15. script.Append("};");
  16. return script.ToString();
  17. \




That is pretty much the bulk of it. In the end you have yourself an RSS (and Atom) consuming web part that is superior to what you get out of the box.

The Visual Studio 2008 solution uses takes advantage of feature based web part deployment and uses STSDev2008 (you will need to install it if you want to build).

VS2008 Solution:

Just the WSP
Tuesday, June 23, 2009

Mmmm… MCTS Cake

Recently passed the MCTS 70-630 Exam – MOSS – Configuration. I have had some time to think about it and I think my opinion is: too #^$%$ easy.

I am not trying to be be all ‘me so smart’ – I am not. The comparison is based my only other two certification exams: 70-536 and 70-XXX (the .NET Framework: Web Applications ones). Compared to those the MOSS exam was cake. No, it was like sitting in a lay-z-boy and having someone feed you cake. With a robotic chewing device so you did not have to do that work either.

So exaggerations aside, if you have spent a reasonable amount of time within Central Admin and know a little something about InfoPath, you will be in good shape. Even more, if you have even modest deductive reasoning skills, you will do really well. I don’t want to give any specifics away, but take this example question:

You are a SharePoint admin and need to perform a task you do not know much about. What should you do:

a. Do something ridiculous.
b. Do something even more ridiculous.
c. Do something that kind of makes sense.
d. Do something that is a completely made up admin task.

I actually laughed a few times during the test at how farfetched some of the options were. Then the doubt started: “This is too easy – am I missing something?”, “It can’t be this easy – what am I doing wrong?”,  “Did I lock my car?”

In the end it turned out OK. I plan on taking more MOSS/SP exams, so I am looking forward to comparison. But if you are looking for an easy entry into MCTS-dom, and a fair test (had some issues with MCTS: .Net Framework Web Apps tests), the 70-630 is probably a good way to go.

Tuesday, May 26, 2009

JavaScript Finally Gets Red Carpet Treatment

Visual Studio 2010 – you complete me.

In addition to the well advertised javascript intellisense (no longer a meager add in) and jQuery integration, I read something today that is further evidence  of JavaScript’s “here to stay (so you better get on board)” status: The JavaScript profiling features built in to Visual Studio 2010. Read more about it here on the VS Profiler Team Blog:  http://blogs.msdn.com/profiler/archive/2009/04/21/website-performance-talk-at-mix09.aspx

Can’t wait for Visual Studio 2010? You can get the predecessor to this feature today in the form of the VS 2008 AJAX Profiling Extensions. Soma Somasegar’s blog has a good post on this: http://blogs.msdn.com/somasegar/archive/2009/04/29/vs2008-ajax-profiling-extensions.aspx

What is cool is that there are no client requirements for all of this – JavaScript is modified on the fly from the server to include instrumentation that captures the performance data. This may sound a little redundant if you are familiar with the profiling features built in to the latest browsers/add-on’s, like IE8’s profiler or FireBug. These are great tools, but I think making a browser-independent ‘tool’ is almost more useful, since in general if you are using IE8 or FireFox with FireBug installed, you are probably NOT experiencing performance problems! I see a particular value here in determining the delta between antique browsers and those who stay reasonably current with technology. That is another way of saying this will help U.S. gov’ment users still using IE6, as most of them still are.

I may experiment with this in the near future and post my results. If there’s time.

Monday, May 18, 2009

Setting AfterProperties in Event Receiver

They just couldn’t be the same.

I needed to capture the current date and user when a field was changed. So in the event receiver’s ItemAdding event, I thought I would set the AfterProperties the same way you would normally set an item’s field value:

properties.AfterProperties[userField] = user;
properties.AfterProperties[dateField]
= DateTime.Now;


No dice: Error on both lines of code. So how to set them? To find out I set the fields manually and examined the AfterProperties during the event receiver’s invocation. Here is what I found:



A SPUser field is not an SPUser in the AfterProperties dictionary, it is the SPUser.ID converted to a string. And why wouldn’t it be…



A DateTime field is also a string, except not just a string produced by the DateTime.ToX functions – since that would be too logical. The DateTime AfterProperty is actually a string produced by the SPUtility.CreateISO8601DateTimeFromSystemDateTime method. No – I did not make that up – it is very real. So I guess DateTime in AfterProperties goes all international on you, since that is what that naming convention implies. (see here)



SO here is the working code that captures user and current datetime in the AfterProperties:



properties.AfterProperties[userField] = user.ID.ToString();
properties.AfterProperties[dateField]
= SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now);
Thursday, May 14, 2009

Setting ContentType of SPListItem

The ContentType property of a SPListItem is readonly. Yet the SharePoint UI lets you change it. So how to change it? This guy beat me to it and has two nice methods that accomplish this should-be-simple-but-yet-again-not-obvious task:

Alexander B's Blog

SPSaturday DC Presentations

Non-biased opinion: Some great presentations here:

SharePoint Saturday DC Resources

Wednesday, May 13, 2009

SPListItem will not update

Not even close to a record – second “easy thing that eats up a few hours”.

The situation: Simple postback event handler that updates a field in a list to a new value. Here is the code:

protected void DenyRequest( object sender, EventArgs e )
{
    try
    {
        Item[fieldname] = RequestStatus.Denied;
                
        Item.Update();
        RedirectToPreviousPage();
    }
    catch (Exception ex)
    {
        errorLabel.Text = string.Format("Sorry, there was an unexpected error: {0}", ex.Message);
    }
}


The issue: The field value never changes! The line of code gives no indication of failure – the update also succeeds – but the value never freakin changed.



The solution I found to by way of this dude’s blog: Nick Grattan Blog Post who needed to get a new reference to the item to have it change the value. So the working code looks like this:



protected void DenyRequest( object sender, EventArgs e )
{
    try
    {
        SPListItem item = List.GetItemById(Convert.ToInt32(ItemID));
        item[fieldname] = RequestStatus.Denied;
        item.Update();
        RedirectToPreviousPage();
    }
    catch (Exception ex)
    {
        errorLabel.Text = string.Format("Sorry, there was an unexpected error: {0}", ex.Message);
    }
}


So the difference was that before the Item was a property that returned the list item using the GetItemById method using the same ItemID property, and now that is done inline with the update code. Is it just me, or should the code work either way? What is the difference if you have a property that returns the item or get the item inline with the update?!



Oh, SharePoint Object Model, you’ve done it again!

SharePoint Retract|Deploy|Annoy

Problem:

Solution redeployment kept failing from STSDEV project. So I headed into central admin – status was deployed. Retracting had no effect – solution status still said deployed! So then I took a look at what exactly it was deployed to. It was the central admin site. Went to try to retract one more time, but this time instead of selecting ‘all content urls’ I intended to select the CA url. One problem: it was not in the drop down list. Annoyance complete.

Solution:

Had to run a command line with the specific CA url:

"C:\Program Files\Common Files\Microsoft
Shared\web server extensions\12\bin\stsadm.exe" -o retractsolution -name MySolution.wsp -immediate -url http://mossCA

 

 
© I caught you a delicious bass.
Back to top