Disclaimer

The views expressed on this weblog are mine alone and do not necessarily reflect the views of my employer, Avanade.

Search
Recomends...
  • Code Complete, Second Edition
    Code Complete, Second Edition
    by Steve McConnell
Login

Try Snip-It Pro 2.5 Free

Sni-It Pro is a code snippet manager with features designed to make you more productive. Version 2.5 has just been released and includes a ton of new features including support for code teplates, automatic commenting, snipplr integration and more. Try it Today!
> Learn More
Sunday
24Jan2010

Method get_XXX from assembly YYYY does not have an implementation

I just spent way too much time trying to figure out why a particular unit test was failing after a round of refactoring.

I kept getting an error that basically said "Method get_XXX from assembly YYYY does not have an implementation" and the test wouldn't even load. I couldn't even attach the debugger to it.

What made it equally confusing was that the code in question was really just a stub class I created for testing purposes.

Somewhat related was the fact that the assemblies I was testing were used in SharePoint, and I was running Visual Studio in my test SharePoint environment, so even though I updated the code and everything compiled fine, what I didn't realize was that the test was getting an old version of the dll from the GAC, hence the error.

I removed the dll from the gac and the test ran fine.

 

Saturday
23Jan2010

Painless SharePoint Web Config Modifications with Custom Features

One of the challenging aspects of custom development when working with MOSS is dealing with changes needed for the Web.config file. If you do it manually, you risk MOSS blowing away your changes whenever it feels like, as certain administrative actions will do this if you’re not careful.

If you instead create a feature that uses the object model and SPWebConfigModification, you have to deal with several layers of quirkiness. For example, the “Name” property isn’t just descriptive, it’s an XPath Selector.  Another example is that any mistakes you make with your XPath selectors will cause the feature to fail, but not roll back your changes (the faulty web config mod is still in the collection), so you need to ensure that you manually write code that removes the modification.

But with the right approach, you can get around those limitations and use SPWebConfigModification to update web config files for a given web application and not have to worry about SharePoint blowing things away. The biggest problem of all is how tedious it is to create these modifications for each and every node you want to add to the Web.config. It makes it extremely painful to update the web config for complex configurations needed to support IoC containers, Enterprise Library blocks or other time saving libraries.

For example, to get this simple configuration for the Enterprise Library Exception and Logging blocks we would need to create 22 separate SPWebConfigModification objects, each with its own xpath selectors for specifying where in the config file each node goes:

<loggingConfiguration tracingEnabled="true"
    defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
    <listeners>
      <add source="Enterprise Library Logging" formatter="Text Formatter" log="Application" machineName="" listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"traceOutputOptions="None" filter="All" />
    </listeners>
    <formatters>
      <add template="Timestamp: {timestamp}&#xD;&#xA;Message: {message}&#xD;&#xA;Category: {category}&#xD;&#xA;Priority: {priority}&#xD;&#xA;EventId: {eventid}&#xD;&#xA;Severity: {severity}&#xD;&#xA;Title:{title}&#xD;&#xA;Machine: {machine}&#xD;&#xA;Application Domain: {appDomain}&#xD;&#xA;Process Id: {processId}&#xD;&#xA;Process Name: {processName}&#xD;&#xA;Win32 Thread Id: {win32ThreadId}&#xD;&#xA;Thread Name: {threadName}&#xD;&#xA;Extended Properties: {dictionary({key} - {value}&#xD;&#xA;)}"        type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </formatters>
    <categorySources>
      <add switchValue="All">
        <listeners>
          <add />
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" />
      <notProcessed switchValue="All" />
      <errors switchValue="All">
        <listeners>
          <add />
        </listeners>
      </errors>
    </specialSources>
  </loggingConfiguration>
  <exceptionHandling>
    <exceptionPolicies>
      <add>
        <exceptionTypes>
          <add
            postHandlingAction="None">
            <exceptionHandlers>
              <add logCategory="General" eventId="100" severity="Error" title="Enterprise Library Exception Handling" formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" priority="0" useDefaultLogger="false"
               name="Logging Handler" />
            </exceptionHandlers>
          </add>
        </exceptionTypes>
      </add>
    </exceptionPolicies>
  </exceptionHandling>

I always had a love/hate relationship with this approach, and always thought of building something to make it easier. I ended up creating an abstract base class for “FeatureReceivers” that makes it easy to convert Xml Strings with configuration data in it, to a collection of SPWebConfigModification objects (with EnsureChildControls) that can be then applied to merge those configuration changes into the MOSS Web.config file.

Then to painlessly create a feature that updates the Web Config modification, inherit from the provided base class and use the following code, passing in your own config string, owner string, and collection of nodes to ignore.

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
  //Custom Function in the base class to get the Web App despite the feature scope
  SPWebApplication application = GetCurrentWebApplication(properties);
  if (application != null)
  {
    //Clean out any old ones first, in case we had an issue previously. Should also be called on
    //feature deactivate.
    RemoveWebConfigModificationsByOwner(application, SPWebConfigModificationOwner);

    //This will parse the string and convert to all spwebmods with EnsureChildNode as the type.
    List<SPWebConfigModification> mods = CreateModifications(ConfigXML, SPWebConfigModificationOwner, NodesToIgnore);
    AddWebConfigModifications(application, mods);
  }
}

The Nodes to ignore parameter is there to create a collection of strings that if the node matches on of them, the base class won't create a SPWebConfigModification for it. This is useful if you don't want to add an extra node for appSettings, or othe types of nodes which you know are already in the web config.

The base class itself, turns your configuration string into an XMLDocument and iterates through each node creating SPWebConfigModifications as long as the node name isn’t in the IgnoreCollection. Keep in mind, the WebConfigModifications are all of type “EnsureChildControls” which works very well for adding new nodes to the web config, but don’t work well if the config node already exists. For this type of requirement (for example updating the CustomErrors to off, you need a modification of type “EnsureAttribute” and will have to roll this on your own.)

I haven’t tested every situation, so I’m sure this code will need to be tweaked to meet specific needs, but it should give you a nice head start for creating a clean feature. For example, keep in mind for Xpath selectors, it will use the node name alone if there is one or less attributes, otherwise it will use the “Name” attribute if it exists, otherwise the first attribute found for the node.

Once you create your custom class, you’ll need to specify it as the receiver class in a custom feature xml that gets deployed via wsp or manually, and then activate it. I recommend giving the feature the Web Application scope, and creating separate features for each environment you want to deploy (dev, staging, production), this way you can integrate the stsadm call to activate the environment specific feature in your build scripts.

I know it’s a shameless plug, but I’ve packaged all the code (for the base class, sample feature xml and sample inherited class) into a Snip-It Pro import file. So if you don’t have it, you can install a thirty day trial here. Then you can download and import this Snippet Library (by creating a snippet collection, right clicking the folder and selecting “Import” and then navigating to the file). Each file provided is a parameterized snippet which will allow you to customize class names, namespaces and values in the Configure Snippet area (bottom of the docking bar) before drag/dropping into Visual Studio.

 > Download the code snippets. (Snip-It Pro snippet archive)

Saturday
16Jan2010

Converting to Snip-It Pro's ".snip" format

One of my goals in creating Snip-It Pro was to make it very easy to export your snippets to another format, so that using a proprietary format was not an excuse for not using Snip-It Pro. The latest release of Snip-It Pro introduces two additional export features: the ability to export folders to a single text file and the ability to define an export template and export all the snippets in a folder using that template. This feature effectively enables you to convert your snippets into any other text based format. I even included an example in the help file of defining a template for converting to the Visual Studio “.snippet” format.

But just as important as the ability to export, is the ability to import. Sure you can drag and drop text right into Snip-It Pro, but then you would still need to set a description and other properties. And there is also the ability to publish and retrieve favorite snippets from Snipplr, but then again you might not be using Snipplr, or you’re trying to import from a local format.

I thought about creating a similar import feature by allowing users to define regular expressions, but thought that would probably not be such a great feature, since as the old saying goes “if you have a problem that requires you to use regular expressions, then you have two problems.”

So until I crack this nut of a problem, I figured the best thing I could do, would be to write a post explaining the XML based “.snip” format that Snip-It Pro uses.  After all, most Snip-It Pro users are programmers, and writing scripts to convert between formats is just the sort of problem we like to solve.

Here is a guide to the nodes/fields within the format, with tips if you are going to populate these yourself:

Description – The title/description of the snippet. This is what is displayed as the name of the snippet in the toolbar and folder view.

Content – The actual contents of the snippet. In version 1, this field actually contained RTF. In version 2 and above, plain text is used since we began to support Syntax Highlighting.

FileVersion – If you are using RTF for your content field, set this to 1, otherwise set it to 2. If you do set it to 1, keep in mind the next time the snippets is edited, Snip-It Pro automatically converts it to 2, stripping any RTF from your content.

Order– Used to order the snippets in a folder. We don’t do any validation on this other than the fact that it has to be an integer. Once we load all the snippets in a folder, we use this to sort them before displaying in the UI

PreviewText– This is used to populate the tool tip that displays when you hover over the snippet. It was much more useful in version 1, as the tool tips couldn’t display RTF, but normally this is just set to the content.

Notes – This field can have any notes you want and can include RTF text.

Category– The Display Name of the category the snippet is in. Snip-It Pro does a lookup in the categories file located in the “AppData\Roaming\Snip-It Pro” folder. That file has info about how to comment it, what the internal Snipplr category is and which “.syn” file to load from the lib directory in the installation directory to get syntax highlight rules for that language.

ReferenceUrl– Here you should put any reference url as the UI gives you the ability to right click and navigate to the url, but you can put any string in here if you wanted to.

Tags – Put each Tag in a string node as this is a collection of strings.

ID– A guid that can serve as the ID of the snippet. If you don’t want to generate these, leave off the entire Node, as Snip-It Pro will complain if the node is there with no value. This is only used in the “auto commenting” feature, so leaving it off isn’t an issue. Snip-It Pro will actually generate a new Guid if you leave it off next time you save the snippet.

DisableAutoComments – Set to true or false. Controls whether to override the global application setting of inserting auto comments for this particular snippet.

LastUpdated – Put the last updated date time, or better yet, just leave off this node as well as it’s not required.

Here is a sample “.snip” file :

<?xml version="1.0" encoding="utf-8"?>
<Snippet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Description>C# Property</Description>
  <Order>2</Order>
  <PreviewText>private [[Data Type]] _[[Property Name]];
public [[Data Type]] [[Property Name]]
{
 get { return _[[Property Name]]; }
 set { _[[Property Name]] = value; }
}</PreviewText>
  <FileVersion>2</FileVersion>
  <Notes>{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Verdana;}}
\viewkind4\uc1\pard\f0\fs17 Use configure snippet to configure\par
}
</Notes>
  <Category>C#</Category>
  <ReferenceUrl>http://snipplr.com/view/14656/templated-property</ReferenceUrl>
  <Tags>
    <string>property</string>
    <string>getter</string>
    <string>setter</string>
  </Tags>
  <Content>private [[Data Type]] _[[Property Name]];
public [[Data Type]] [[Property Name]]
{
 get { return _[[Property Name]]; }
 set { _[[Property Name]] = value; }
}</Content>
  <ID>22033523-1561-4d9a-96ec-29d44b4b3a26</ID>
  <DisableAutoComments>false</DisableAutoComments>
  <LastUpdated>2009-05-16T11:52:40.824-04:00</LastUpdated>
</Snippet>

Something to keep in mind, is that Snip files are just .Net objects (Snip-it Pro is written in C#) that are serialized using the default XML serializer. They are deserialized using the same serializer. If you're a dot net developer, you actually can add references to the Service.File assembly and create your own instances of FileSnippet (Inherits from an abstract snippet class in the Infrastructure.Interface assembly). You can even call the SaveSnippet method of the FileSnippetService in the same assembly to save it once you've populated the fields instead of writing your own serialization code.

If you have any issues creating this format, send me an email or leave a comment.

Thursday
07Jan2010

Minor Tweaks

One of my Snip-It Pro users gave me three suggestions that I thought were very good and were easy for me to implement. I was able to get them done and I re-released Snip-It Pro officially as version 2.5.0.2

Here's what was changed:

  • Now you can set a default category for new snippets. I Added a default checkbox to the Categories page of the advanced options dialog. Just check the checkbox (and click add or change).
  • Description Text box is now a combo box with auto complete. If you're creating a bunch of similarly named snippets, this will make it easy to fill in the description. The combo box list items are only saved in memory, so restarting the application clears the selectable items.
  • Warn Users of Unsaved work. Now when you click "New Snippet" anywhere in the interface, you will get a warning message asking you if you want to discard your changes if you had previously modified a snippet.

Nothing huge, but nice usability improvements none the less.

You can download the latest from http://www.snipitpro.com/

Enjoy!

Sunday
03Jan2010

Snip-It Pro is On Twitter

Just created a twitter account for Snip-It Pro to promote the 2.5 release.

I am using Twuffer to schedule daily Tip of the Day and Feature Mention Tweets.

Follow me.