The Infragistics SharePoint Demo Is Funny, But Depressing

So, I recently got solicited for feedback and comment from Infragistics because I was for some time heavily into using their control set. Regardless of some of the unwieldy operations to sustain the nifty functions, I think they are neat and a lot of the times clients have a pre-existing license agreements so I just use ’em.

Infragistics appears to be making a tactical move into the SharePoint space; therefore curiosity arose in me to go test out what they had recently released. Regrettably, in conventional let’s hurry up and provide a SharePoint solution format which can be vendor criterion, Infragistics wins for the most cumbersome deployment process feasible. Well, maybe not that bad, but it’s pretty damn close.  The WORST part about this situation is the code behind for the solution is fantastic (not being sarcastic, it really is pretty good!), and it’s a bummer that they dropped the ball on everything BUT managed code development. Kudos to the developer on the code though.

So, here is the page of concern:
http://www.infragistics.com/hot/sharepoint.aspx#SharePoint

And here is a link to the configuration guide:
http://dl.infragistics.com/products/NetAdvantage/Silverlight/2008.1/ReferenceApplications/Pomegranate%20-%20Configuration%20Document.pdf

Alrighty, let’s get started. Once the PDF is open, scroll down to page 10.

1) Get to step one. WTF?!?! Cmon Infragistics, you want *manual* web.config modifications? LAME. That can take forever to complete on a staging farm, and is subject to substantial human error. I mean come on; the SPWebConfigModification class exists for a reason and there are all sorts of receivers.
– Moving right along, reference point 1 for the custom configuration sections instances. Are people really supposed to copy and paste that shit?
– Manual safe control entries. HA! I like that one. No note needed on that sweetness.
– Manual CAS adjustments make me want to cry. Seriously, as someone that takes code security critically, I want to shove a pen in my eye to damn the tears up like a Bic beaver.
– Again, the session state stuff? See above.
– Could go on with the rest of em, but you get the point…
2) Creating folders at the root of the site can be automated, that’s why we have SPWebApplication, etc. objects. You can even do your permission requirements as well.
3) You want people to copy things into the 12 hive. Is there a point to that? I mean, it is breaking the fundamental principle of SharePoint Solution architecture. That’s one of the reasons WE HAVE SOLUTIONS.
4) Uploading a master page can be automated since the Master Page Gallery upload is the same as any document library. Sigh.
5) As opposed to packing .webpart or .dwp files, you are asking people to new them up out of the gallery. The extent of that laziness is immeasurable in words.
6) Well, I guess back to the 12 hive thing, again, manual Theme deployment. Word.
7) After I saw SPD, I threw up a little bit in my mouth and stopped reading.

I am not bagging on the controls, but FFS, if you are going to build a sample solution, MAKE IT EASY AND QUICK TO DEPLOY. I don’t want to spend a fucking afternoon trying to get some pie charts and random data grids into a demo site.

Share

SharePoint WebPart Versioning

WebPart versioning is a discussion that I have with clients, as well as internally, consistently. Largely this is because it can hit sensitive organizational points (if they have a reasonable software development initiative) and is terribly prone to developer opinion. It can rapidly move from a pragmatic to esoteric discussion.

For these reasons, it is challenging to structure a best practice regarding WebPart versioning, since there really is no best practice. However, after presenting some options I think it is reasonable to assume that an organizational best practice can be cultivated and everyone can be happy.

To try to get those gears turning, I am going to fly through at a 10,000 foot view of various problems typically encountered when implementing a WebPart versioning strategy, some approaches, and a base class that I use that leverages one of the discussed version approaches using a display vehicle I like the most.

Before I continue, let me state that the remainder of this post is going to assume strong named/signed assemblies, as well, these assemblies are being stored in the GAC.

Problems with Versioning

Arguably, the most difficult segment to tackle when dealing with WebPart versioning is that the AssemblyVersion attribute tends to be of little use because WebParts can be considered to use static versioning. AssemblyVersion within orthodox managed development tends to be heavily leveraged because it defines an integral number regarding the assembly’s identity. So, why is the AssemblyVersion such an ineffective mechanism to rely on when dealing with SharePoint WebPart development?
There are three main reasons:

Referencing the AssemblyVersion attribute, as managed assemblies in the GAC do, will break if this value changes.

The SharePoint WebPart Description File (.webpart or .dwp) references the AssemblyVersion attribute within the type element in its XML structure. This element consists of a string with type and assembly information about the corresponding webPart element. As a result, any description files already instantiated on a page won’t bind right due to an incorrect assembly version number.

Without modifying the safe controls entries for the SharePoint site, there will be an assembly mismatch when altering the AssemblyVersion number, resulting in a safe control error when attempting to render the WebPart (if already on a page, otherwise it won’t be allowed on the WebPartPage). This can be solved with solution redeployment or manual web.config modifications; however you are following still subject to the same problem as described above so while fixable, isn’t a rational solution.

There are some more issues, most I consider negligible so I won’t go over them; however those are the largest ones.

Versioning Storage

In order to resolve not having a dependency on the AssemblyVersion, a margin of people rely on the AssemblyFileVersion attribute since this can arbitrarily change with little effect on the WebPart. Use of this also provides the same experience as using the AssemblyFileVersion since this value is mutable from VS.NET with nearly the same invocation. As well, for people that are using Reflection in order to hydrate objects with the relevant assembly information, the mechanics are consistent once you have an Assembly object.

Otherwise, static string representation is simple and popular. This involves setting the values of the version and build name within the assembly, a satellite assembly, or from some other arbitrary source. It could be a wide range of objects, even from a tabulated text file, it doesn’t really matter. All that matters is that the version information is read from a source, and that source is not the calling assembly.

Choosing a Display Vehicle

The display mechanisms for versioning vary depending on the organization. I have seen in the majority of projects these four major types:

Toggle the corresponding SharePoint Feature description element prior to the SharePoint solution packaging.

Just format and dump it out to directly out to standard output as part of the control.

Add a new WebPartVerb object to the current instance WebPartVerbCollection with the version information.

Add a new EditorPart to the current instance EditorPartCollection with the version information

Making It Work

As an example, I am going to use the last option, and place my versioning information in an EditorPart object. In order to consistently enforce this across multiple WebPart type projects, a new base WebPart class for subclass use will be defined which contains all the relevant code to handle the versioning. In order to pass unique values for the program name and the version number, the derived class constructor will be used. The approach is similar to using the WebPartVerb approach, and could easily be ported over to that construct if EditorPart  objects don’t really blow your back.

To do this, three different classes are used. VersionInfo contains a static method that renders to standard output the required strings using strongly typed formatting objects. EditorVersionPart inherits from the EditorPart class, and contains two backing fields that are toggled in the constructor. EditorVersionPart calls the static VersionInfo.CreateVersion method to build out the visual representation of the version information. The WebPartBase class inherits from the WebPart, and IWebEditable interface. Regarding the latter of these, its type members are implemented, which call the custom EditorVersionPart class.

As a result of using this class, you will be presented with the following when using it as your base class, demonstrated in a trivial WebPart.

In order to provide the required strings, in the WebPart constructor the desired values are being provided.

As a result, the WebPart class structure will take on the following form:

[csharp]
namespace buenz.SharePoint.WebParts
{
public class VersionDemo : WebPartBase
{
public VersionDemo()
{
_name = “My WebPart”;
_version = “1.0.0.0 (Debug / Checked)”;
}
}
}
[/csharp]

And the related classes to achieve this effect are:

[csharp]
using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using midwave.SharePoint.WebParts;

namespace buenz.SharePoint.WebParts
{
public class VersionInfo
{
public static void CreateVersionSegement(HtmlTextWriter writer, string version, string name)
{
var tbl = new Table {HorizontalAlign = HorizontalAlign.Center};
var row = new TableRow {HorizontalAlign = HorizontalAlign.Center};
var versionRow = new TableRow {HorizontalAlign = HorizontalAlign.Center};
var cell = new TableCell {HorizontalAlign = HorizontalAlign.Center, Text = string.Format(“{0}”, name)};
var versionCell = new TableCell {HorizontalAlign = HorizontalAlign.Center, Text = string.Format(“{0}”, version)};
row.Cells.Add(cell);
versionRow.Cells.Add(versionCell);
tbl.Rows.Add(row);
tbl.Rows.Add(versionRow);
tbl.RenderControl(writer);
}
}
}

public class EditorVersionPart : EditorPart
{
public string _name;
public string _version;

public EditorVersionPart(string webPartID, string name, string version)
{
Title = “WebPart Versioning”;
ID = string.Format(“MyEditorPart{0}”, webPartID);
_name = name;
_version = version;
}

protected override void RenderContents(HtmlTextWriter writer)
{
base.RenderContents(writer);
VersionInfo.CreateVersionSegement(writer, _version, _name);
}

public override bool ApplyChanges()
{
EnsureChildControls();
return true;
}

public override void SyncChanges()
{
EnsureChildControls();
}
}

public class WebPartBase : WebPart, IWebEditable
{
public string _name;
public string _version;

EditorPartCollection IWebEditable.CreateEditorParts()
{
var editors = new List {new EditorVersionPart(ID, _name, _version)};
return new EditorPartCollection(editors);
}

object IWebEditable.WebBrowsableObject
{
get { return this; }
}
}

}

[/csharp]

Happy Versioning! :)

Share