Solved! - The service 'System.Workflow.ComponentModel. Compiler.ITypeProvider' must be installed for this operation to succeed.

Posted by | Filed under , , ,

I'm working on a SharePoint project where several componenets (Workflow, List Definitions, Content Types, etc.) are tightly related to the same functionality. To reduce the risk of components breaking because of an out-of-sequence or missing dependency, and just to make things easier, I wanted to throw everything together in the same project. I discovered something interesting about Workflows in the process, however.

Namely, if you try to add a Workflow to a typical project, you'll get an error in the Workflow designer saying:

     "The service 'System.Workflow.ComponentModel.Compiler.ITypeProvider' must be installed for this operation to succeed."

This happens if you added references to the proper assemblies (System.Workflow.Activities, System.Workflow.ComponentModel, System.Workflow.Runtime and microsoft.sharepoint.WorkflowActions)!

Odd, but luckily there are solutions. One is to write a bunch of code to build the support that the Workflow Designer needs, but I was looking for something even simpler. What I discovered, is that you can add support for Workflows to your project (the .csproj or .vbproj file) by cracking it open in notepad and adding some "ProductTypeGuids" to the project XML. Just add both of the GUIDs featured in the ProjectTypeGuids element below (or add the element if it's not there), and you should be good to go!

<PropertyGroup>
    ...
    <AssemblyName>MyCompany.Technnology</AssemblyName>
    <ProjectTypeGuids>{14822709-B5A1-4724-98CA-57A101D1B079};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    ...
  </PropertyGroup>

 I'm curious to see if you can add these GUIDs to many types of projects to enable Workflow support (and further curious about if there are any consequences apart from designer support),

Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

The Very Basics of a Custom ConfigurationSection

Posted by | Filed under , , ,

In my view, the custom configuration API in .NET is one of the most underappreciated tools at a .NET developer's disposal.

 The .NET Framework team made it dirt simple to create configuration extensions that harness the capabilities you're used to. With one simple class, you have all you need to add entries to web.config/app.config and machine.config files, you have rich API's supporting features like XML encryption, and you do it all without any XML parsing logic or file IO!

 At the core, a custom configuration section consists of three pieces:

  1. A class that inherits from System.Configuration.ConfigurationSection (be sure you add a reference to System.Configuration).
  2. A registration of your custom configuration section in configSections element your .NET configuration file.
  3. The XML configuration itself, which you add later in the file.

We'll examine each f these parts seperately, and briefly cover what you need to know about each.

 First, the ConfigurationSection class! In my case, I created an overly simplified section that includes the email address of someone you want to send notifications to.

 In it, you'll want to pay attention to four things. First, data access is handled by ConfigurationManager though of note is that WebConfigurationManager, a web-centric class with extra capabilities, may also be used for web apps. The second thing to note is the path we use to access our configuraiton section, "cSharpConsultant/notifications" in our case. This corresponds to our configuration XML and the configSections entry we make for it.

 Third, notice how we implemented our property via a ConfigurationPropertyAttribute. The "emailAddress" value we use in the attribute works in conjuction with the property getter and setter to access the internally parsed and managed configuraiton value. You'll see later on that "emailAddress" directly relates to an XML attribute in our custom configuration.

 Lastly, see how we can apply validation rules to our property via a RegexStringValidatorAttribute. RegexStringValidator is just one of the many available rules we can apply to our configuration property. The biggest gotcha to note, however, is that the validation rules will run on the default value of a property before they validate the actual value in the configuration file. This means that without a "DefaultValue" set in ConfigurationProperty, our RegexStringValidator would actually run against a blank default value and throw an exception saying "The value does not conform to the validation regex string"!

public class NotificationsConfigurationSection : ConfigurationSection
{
  private const string configPath = "cSharpConsultant/notifications"
  public static NotificationsConfigurationSection GetSection()
  { 
    return (NotificationsConfigurationSection) 
      ConfigurationManager.GetSection(configPath);
  }

  /*This regular expression only accepts a valid email address. */ 
  [RegexStringValidator(@"[\w._%+-]+@[\w.-]+\.\w{2,4}")] 
  /*Here, we register our configuration property with an attribute. 
  Note that the default value is required if we use 
  the property validation attributes, which will unfortunately 
  attempt to validate the initial blank value if a default isn't found*/
  [ConfigurationProperty("emailAddress", DefaultValue=Address@Domain.com)]
  public string EmailAddress
  { 
    get{ return (string)this["emailAddress"]; }
    set{ this["emailAddress"] = value; }
  }
}

 The second part of our setup is to register our configuration class in the file where we want to use the configuration. At the top of all .NET configuration files is a "configSections" element, where we'll register the schema and type of custom ConfigurationSection. Notice how our setup relates to "cSharpConsultant/notifications", the path we used to access our section in the above code.

<configSections> 
  <sectionGroup name="cSharpConsultant">
    <section name="notifications"
        type="ConfigurationSample.NotificationsConfigurationSection,
        ConfigurationSample, Version=1.0.0.0, 
        Culture=neutral, PublicKeyToken=null"/>
</sectionGroup>

Finally, to complete our setup, we need the actual configuration! Notice how the attribute "emailAddress" relates to the ConfigurationProperty value we registered in our custom configuration section's "EmailAddress" property.

<cSharpConsultant>
    <notifications emailAddress="NotifiedPerson@Domain.com"/>
</cSharpConsultant>

 That's it! Now to access our custom configuration, it's as simple as this!

NotificationsConfigurationSection section 
  = NotificationsConfigurationSection.GetSection();
string emailAddress = section.EmailAddress;

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5