Why isn't my custom WCF behavior extension element type being found?
I have a solution that contains two projects. One project is an ASP.NET Web Application Project, and one is a class library. The web application has a project reference to the class library. Neither of these is strongly-named.
In the class library, which I'll call "Framework," I have an endpoint behavior (an IEndpointBehavior implementation) and a configuration element (a class derived from BehaviorExtensionsElement). The configuration element is so I can attach the endpoint behavior to a service via configuration.
In the web application, I have an AJAX-enabled WCF service. In web.config, I have the AJAX service configured to use my custom behavior. The system.serviceModel section of the configuration is pretty standard and looks like this:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="MyEndpointBehavior">
<enableWebScript />
<customEndpointBehavior />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service name="WebSite.AjaxService">
<endpoint
address=""
behaviorConfiguration="MyEndpointBehavior"
binding="webHttpBinding"
contract="WebSite.AjaxService" />
</service>
</services>
<extensions>
<behaviorExtensions>
<add
name="customEndpointBehavior"
type="Framework.MyBehaviorExtensionsElement, Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
At runtime, this works perfectly. The AJAX enabled WCF service correctly uses my custom configured endpoint behavior.
The problem is when I try to add a new AJAX WCF service. If I do Add -> New Item... and select "AJAX-enabled WCF Service," I can watch it add the .svc file and codebehind, but when it gets to updating the web.config file, I get this error:
The configuration file is not a valid configuration file for WCF Service Library.
The type 'Framework.MyBehaviorExtensionsElement, Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' registered for extension 'customEndpointBehavior' could not be loaded.
Obviously the configuration is entirely valid since it works perfectly at runtime. If I remove the element from my behavior configuration temporarily and then add the AJAX-enabled WCF Service, everything goes without a hitch.
Unfortunately, in a larger project where we will have multiple services with various configurations, removing all of the custom behaviors temporarily is going to be error prone. While I realize I could go without using the wizard and do everything manually, not everyone can, and it'd be nice to be able to just use the product as it was meant to be used - wizards and all.
Why isn't my custom WCF behavior extension element type being found?
Updates/clarifications:
- It does work at runtime, just not design time.
- The Framework assembly is in the web project's bin folder when I attempt to add the service.
- While I could add services manually ("without configuration"), I need the out-of-the-box item template to work - that's the whole goal of the question.
- This issue is being seen in Visual Studio 2008. In VS 2010 this appears to be resolved.
I filed this issue on Microsoft Connect and it turns out you either have to put your custom configuration element in the GAC or put it in the IDE folder. They won't be fixing it, at least for now. I've posted the workaround they provided as the "answer" to this question.
Solution 1:
Per the workaround that Microsoft posted on the Connect issue I filed for this, it's a known issue and there won't be any solution for it, at least in the current release:
The reason for failing to add a new service item: When adding a new item and updating the configuration file, the system will try to load configuration file, so it will try to search and load the assembly of the cusom extension in this config file. Only in the cases that the assembly is GACed or is located in the same path as vs exe (Program Files\Microsoft Visual Studio 9.0\Common7\IDE), the system can find it. Otherwise, the error dialog will pop up and "add a new item" will fail.
I understand your pain points. Unfortunately we cannot take this change in current release. We will investigate it in later releases and try to provide a better solution then,such as providing a browse dialog to enable customers to specify the path, or better error message to indicate some work around solution, etc...
Can you try the work around in current stage: GAC your custom extension assembly or copy it to "Program Files\Microsoft Visual Studio 9.0\Common7\IDE"?
We will provide the readme to help other customers who may run into the same issue.
Unfortunately, it appears I'm out of luck on this one.
Solution 2:
As an FYI to anyone who stumbles across this these days a possible solution is to FULLY qualify your assembly in your app.config/web.config. EG if you had
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="clientCredential" type="Client.ClientCredentialElement, Client" />
</behaviorExtensions>
</extensions>
try - replacing the values as necassary
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="clientCredential" type="Client.ClientCredentialElement, Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
this particular solution worked for me.
Solution 3:
I just used
[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]
So I have new assembly build number every time.
But we have
<add name="clientCredential" type="Client.ClientCredentialElement, Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
where Version=1.0.0.0 THIS IS WRONG!!!
So you have 2 options
-
Back to
//[assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] Keep it manually. [assembly: AssemblyFileVersion("1.0.0.0")]
Every build manually replace Version=1.0.0.0 with a correct number.