Why isn't my custom WCF behavior extension element type being found?
Asked Answered
H

11

49

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.

Hepzi answered 3/10, 2008 at 23:44 Comment(0)
H
22

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.

Hepzi answered 14/1, 2009 at 15:54 Comment(4)
I also needed to restart VS before the exception went away.Blender
in vs2008 there is "workaround", but any solution in VS 2010?Heartworm
It appears from other answers below that they've resolved the issue in VS2010. As long as you keep your assembly version numbers synchronized between the assembly and the config file, you should be OK. (I have not tested this personally. YMMV.)Hepzi
I still have the same problem in VS2013. Quick tip - just comment out the extensions element while creating new services and and uncomment after. Adding the file to GAC or IDE folder isn't very cool imo.Selfregulating
S
8

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.

Schlep answered 26/7, 2010 at 4:8 Comment(4)
You'll notice in my example that the type was already fully qualified; the issue is not with full type qualification but with an apparent defect in Visual Studio.Hepzi
you should write the <add /> tag in a single line as shown as above. if you write it in multiple lines then it won't work. hope this helps.Hygienist
Also add platform=MSIL to the FQNSubcelestial
Thanks, adding PublicKeyToken=null to my almost complete list of settings resolved it in my case.Cirque
H
8

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

  1. Back to

    //[assembly: AssemblyVersion("1.0.*")] 
    [assembly: AssemblyVersion("1.0.0.0")]  Keep it manually.
    [assembly: AssemblyFileVersion("1.0.0.0")] 
    
  2. Every build manually replace Version=1.0.0.0 with a correct number.

Hairy answered 24/5, 2012 at 13:38 Comment(4)
The issue wasn't an assembly version problem, it was a defect in VS2008. This may have been fixed in VS2010 - I haven't verified. In VS2010, you do need to have the assembly version numbers correct... but that's not a solution for the question being asked, sorry.Hepzi
@TravisIllig I have VS2010 and when I do EXACTLY I have described it works fine.Hairy
Right. In VS2010. Which means they must have fixed it in VS2010, and I'm happy for that. They didn't have such a fix in VS2008. Thanks for checking in, though.Hepzi
Why is version used in private assembly probing?Haro
S
4

I tried this with a new project just to make sure it wasn't your specific project/config and had the exact same issue.

Using fusion logs, it appears that the system looks for the behavior extensions ONLY in the IDE directory (C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE). Copying the assembly to this directory in a post-build step works, but is ugly.

Subtangent answered 20/10, 2008 at 18:11 Comment(1)
This actually did the trick for me. Installing the DLL in the GAC did not resolve the issue, storing it in Common7\IDE\ did however... Thanks!!!Twenty
E
2

Do you have a copy of Framework.dll with your custom behavior in the bin directory of your web project? If not that is probably the problem. Visual Studio is looking for the implementation of the behavior. Since it's listed in your config it doesn't think to look in the other projects; it expects to find the assembly in the bin.

Depending on how your project is setup, it may be able to run in debug without this assembly being put in the bin, although VS usually builds it and puts it there. But again, it depends on how things are setup.

Anyway, might just want to double check at that the assembly is available at design time.

Elapse answered 4/10, 2008 at 20:56 Comment(1)
The Framework assembly is available in the bin folder at design time. VS just doesn't seem to find it.Hepzi
S
2

Here's the list of steps worked for me:

  • Install dll into GAC, i.e. gacutil /i Bla.dll
  • Get FQN of dll, i.e. gacutil /l Bla
  • Copy resulting FQN into Web.config
  • Add new service in VS
  • Uninstall dll from GAC, i.e. gacutil /u Bla

All together only.

Subcelestial answered 29/12, 2012 at 8:34 Comment(2)
As shown in the question and mentioned in various comments, the type was already fully qualified. The root problem was a defect in VS2008. Also, you don't need to install to the GAC to get an assembly's name, you can just use reflection.Hepzi
@TravisIllig: I just described my own steps to make it working in VS2012U1. My type was also fully qualified and throwing an exception still. But I put no platform=MSIL which wasn't listed in FQN by Reflector. Then I performed this steps and got it working. But 0 lines was added to Web.config by VS eventually so next time I will just copy-paste an existing service.Subcelestial
H
1

Putting the assembly in the GAC would probably help, but I appreciate this isn't the answer you're looking for. Not sure where else VS will look for assemblies apart from the GAC and the directory containing devenv.exe.

Hornbeck answered 7/10, 2008 at 20:27 Comment(1)
Unfortunately, that's not really an option.Hepzi
F
0

I solved this by commenting out the relevant sections in the web.config including the element that used the custom extension, the element and the element.

After that I was able to add a WCF service to the project, add the lines back into the web.config and publish the project.

Flushing answered 9/8, 2013 at 21:29 Comment(0)
S
0

if you are using framework 3.5 the Culture=neutral in small not Culture=Neutral in CAPITAL

Sulphide answered 14/1, 2014 at 20:17 Comment(1)
The example in the question shows that Culture=neutral is correctly using the lower case.Hepzi
T
0

I had the extension class within the same project (dll) as my service class and could not get it to work. Once I moved it to another project and referenced it from the service project it worked. Just in case anyone else runs into this issue.

Tetrapody answered 25/9, 2014 at 13:46 Comment(0)
L
0

I had the extension class defined in my class that implements my interface, which resulted in a "could not load" error, where WCF was unable to load my extension class.

Moving the extension class definition out of the interface implementation (but still in the same project/dll) sorted out my issue.

Lithography answered 6/3, 2021 at 8:4 Comment(1)
Your post seems to have been made without due regard to what has already been posted. I'm not sure that you carefully read the question and answers as Travis posted an answer given by a MS workaround for the 08 IDE. In future please provide valuable well thought out feedback.Flense

© 2022 - 2024 — McMap. All rights reserved.