Error when writing C++ wrapper for WCF - wcf

I'm getting the following error in my WCF project:
"An unhandled exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll
Additional information: Could not find default endpoint element that references contract 'IPhiFeed' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element."
The WCF project is a bit experimental: is a mixture of managed and unmanaged C++, and C#. I've got everything working in pure C#, but I have to consume WCF from unmanaged C++, thus the need to write a C++ wrapper around WCF.
Update
As requested, here is the code thats throws the exception:
// WCF library written in C#
public class EngineAPI : IEngineAPI
{
public FeedClient client;
// constructor
public EngineAPI()
{
// the line below in this C# library works *perfectly* when called from a C#
// console app, but it fails when a C++ console app calls the same C# library
// UPDATE: exception fixed if you copy app.config to out.exe.config, see comments below
client = new FeedClient(); // << exception here
}
.....
}
// NOTE: the line "client = new FeedClient" instantiates generatedProxy.cs,
// which is generated with svcutil
// NOTE: if I temporarily delete "app.config" from the pure C# project, it generates *exactly* the same error as I'm getting when I attempt to call everything from the separate C++ project with managed code.
Update
Found the problem, it was unrelated to the code: you have to copy app.config to out.exe.config. I now have a 100% working C++/CLI project calling a C# library which uses WCF. See my comments below.

Typically when you are using wcf in the client project you have entries in your config file that describe the binding to be used as well as the endpoint where the service is located:
I am presuming that your FeedClient class is the class that inherits from ClientBase(IPhiFeed). ClientBase actually defines numerous constructors, if you call the constructor with no parameters it will attempt to find the 'default' client endpoint in your configuration file; and in this case there isn't one because the only endpoint defined in the configuration has a name. To correct this you can do one of two things: you could call the ClientBase constructor that takes a string parameter with the endpoint name: ClientBase<IPhiFeed>("MyService")
or you could change the configuration file so that the endpoint does not have a name:
Edits:
The code you have in your question looks like C# code. Does the FeedClient class inherit from ClientBase? If yes and the C# code that calls it works then what is the C++ code that doesn't work? In general in C++ code you can have both managed and unmanaged code; that is unmanaged code can call into managed code. In your unmanaged project you should do the following: go to the property page for the project, Click Configuration Properties the General; in the general tab under Project Defaults the second from the bottom option should be Common Language Runtime Support, make sure it is set to Common Language Runtime Support (/clr). Add the project that contains the FeedClient class in as a reference to the unmanaged project if necessary. Then you should be able to instantiate the FeedClient class directly in unmanaged code:
MyNamespace::FeedClient wcfClient;
wcfClient.SomeMethod() // Add parameters as appropriate...

Related

How to load COM dll modules and expose their interfaces as out of proccess servers

I have an out of process server based on the ATL Service VC++2010 Template. Now I wont to extend his COM Interface by dynamically loading additional dlls that contain its own COM Classes.
The dll to load is based on ATL dll VC++2010 Template, containing a simple ATL-object "IMModule". I changed the corresponding .rgs file to connect the class from the dll to the EXE server by adding a LocalServer section and the server's AppID as follows:
HKCR
{
NoRemove CLSID
{
ForceRemove {59276614-A811-4D27-B131-514656E643D3} = s 'IMModule Class'
{
ForceRemove Programmable
LocalServer32 = s 'path to the service exe'
{
val ServerExecutable = s 'path to the service exe'
}
TypeLib = s '{250685C7-CBD3-4FF8-A3A6-2AF668794CFC}'
Version = s '1.0'
val AppID = s '{7EFD508A-53C6-4EA0-B21A-D29277B86CBC}'
}
}
}
In a dll init() method called by the service after loading the dll I call CoRegisterClassObject to register the IMModule class object. But im not sure how to obtain the IUnknown interface pointer (second parameter to CoRegisterClassObject ). I tried the following:
CIMModule::_ClassFactoryCreatorClass* pClassFak =
new CIMModule::_ClassFactoryCreatorClass;
IUnknown* pUnk;
HRESULT hr =
pClassFak->CreateInstance(CIMModule::_ClassFactoryCreatorClass::CreateInstance,
IID_IIMModule, (LPVOID*)&pUnk);
But the call to CreateInstance fails with E_NOINTERFACE.
So, how to register my IMModule class implemented inside a dll to be available for COM clients from my out of process server?
With the help from Roman.R I get the behavior that I need. I can't say thank you enough, #roman-r. I will precisely describe what I did, so maybe someone can retrace the steps and give me some response.
First I created an ATL based Windows service (named UmbrellaService). Inside UmbrellaService I added a simple ATL-Object named Control and added the method:
FindMeAnInterface(BSTR moduleName, IDispatch** ppDispach);
Thats all with the VC++ Wizard. Then I fixed the Control.rgs file by adding:
val AppID = s '%APPID%'
Why has VC++ still such bugs after 17 years of evolution? (See
CoCreateInstance does not start or connect to ATL COM service)
Then I created an ATL-dll Project, named MyModule, with a "Module"
simple ATL-Object inside. The Module class has a method
testMethod (LONG a, LONG b, LONG* sum)"
The MyModule dll is registered as a in-proc server. Furthermore the dll has some classes
that makes the dll a plugin as I need it.
In the PreMessageLoop method of the UmbrellaService the MyModule dll will be loaded with LoadLibrary and through GetProcAddress the address of a factory creation method is obtained. The factory creation method returns a plugin-dependent FactoryClass that acts as a plugin entry point. This is my COM-independent plugin mechanism.
Now to export the module interface from the plugin dll through the UmbrellaService interface I did the following: On the FactoryClass I add the method:
IDispatch* getInterface();
In getInterface method I call
CoCreateInstance(__uuidof(Module), NULL , CLSCTX_INPROC_SERVER , __uuidof(IDispatch), (VOID**) &pDispatch);
and return the obtained IDispatch interface. The FactoryClass::getInterface method is called inside the Control::FindMeAnInterface method of the UmbrellaService after comparing the name passed to FindMeAnInterface with the name provided by the FactoryClass. FindMeAnInterface returns the then obtained IDispatch pointer to the client.
On the client side I import the tlb file from the UmbrellaService and the tlb from the apropriate plugin dll. I call testMethod as follows:
IControlPtr pControl(__uuidof(Control));
_bstr_t moduleName("Module");
IDispatchPtr moduleDisp = pControl->FindMeAnInterface(moduleName);
IModulePtr pModule(moduleDisp );
LONG res = pModule->testMethod(42,23);
This all works indeed, but I am not sure if this is the way to do it. Did I miss something about reference counting? Will the plugin DLL be loaded two times? First time through my plugin mechanism and second time through CoCreateInstance? Something else I should note?
Thanks for your help!
I could not find my code so far. But I did check one of my favorite websites, The Code Project. It used to be popular especially with older technologies like COM (yes, it is). I hope you're already convinced that you have to use COM instead of new WFC or another technology.
Please check good documentation and sample code # ATL COM EXE doc. I believe I used this web page as a start of my past project.
Good luck and have fun.

Ambiguous reference in WCF and client application

I've managed to reproduce one of the errors in a test project with a similar structure to my production code. It consists of three simple projects:
Common (class library):
namespace Common
{
public enum PrimaryColor
{
Red,
Green,
Blue
};
}
Library (WCF service library), which has a reference to Common:
using Common;
namespace Library
{
[ServiceContract]
public interface ILibrary
{
[OperationContract]
PrimaryColor GetColor();
}
public class Library : ILibrary
{
public PrimaryColor GetColor()
{
return PrimaryColor.Red;
}
}
}
ClientApp (console application), which has a reference to Common, and a service reference to Library called "LibraryServiceReference":
using Common;
using ClientApp.LibraryServiceReference;
namespace ClientApp
{
class Program
{
static void Main(string[] args)
{
LibraryClient client = new LibraryClient("WSHttpBinding_ILibrary");
PrimaryColor color = client.GetColor();
}
}
}
The app.config files in ClientApp and Library are auto-generated and I have not modified them, and I have not changed the default configuration for the LibraryServiceReference in ClientApp.
When I compile this solution, I get the following errors in the ClientApp project:
Error 1
'PrimaryColor' is an ambiguous reference between 'Common.PrimaryColor' and 'ClientApp.LibraryServiceReference.PrimaryColor'
Error 2
Cannot implicitly convert type 'ClientApp.LibraryServiceReference.PrimaryColor' to 'Common.PrimaryColor'. An explicit conversion exists (are you missing a cast?)
please help me to fix this.
Make sure that 'Reuse types in all referenced assemblies' is selected in the Advanced options of Add service reference or Configure Service Reference.
it's because you're building x64 not "AnyCpu". I am running across this right now, and am trying to figure out if it's a bug, or if it's expected behavior.
Decorate your enum like this:
namespace Common
{
[DataContract]
public enum PrimaryColor
{
[EnumMember]
Red,
[EnumMember]
Green,
[EnumMember]
Blue
};
}
Update Your service reference (with checking reuse types just like Mark stated).
Rebuild your client code.
I have had this issue arise in innocuous, unpredictable manners so many times! I thought I'd share how I "fixed" it this last time.
I am using Visual Studio 2013 - but have had the issue down rev.
The ambiguous reference seems to come on by itself. I did nothing of note to cause it. In the latest instance I was debugging some code behind and suddenly I had 7, then 22 then 49 errors - all of the same nature.
I deleted the service reference altogether and re-added it. Simply modifying the re-use type did nothing. My solution has a WCF service, Class Library, UI and a Control Library. I also removed the using - in some code behind, of the class library.
This is an exceptionally troublesome issue which thankfully only occurs about every few weeks. Why this worked? Beyond my pay grade. I feel your pain! Hope this helps. In this case, the error came on, again, when I opened some code behind on a xaml page.
It sounds like you control both the client and the server code. Why do you want to create a service reference, is there a specific reason or is it just deemed easier?
In projects where you control both sides of the client server application you are better of creating a "contract assembly" (which is probably your common assembly). This contains the interfaces and objects that are involved with the contract and should be referenced by both your client and your server. In order to communicate with the service the client creates a proxy class using the ChannelFactory, there is no need to have a dedicated WCF client.
Example:
ChannelFactory<ISampleService> factory = new ChannelFactory<ISampleService>("Binding_from_config");
ISampleService sampleService = factory.CreateChannel();
sampleService.SomeCall();
factory.Close();
The factory pattern also makes it an ideal candidate for injecting your proxy in via IoC.
The benefits of referencing a common assembly over creating a service reference are:
No ambiguous reference as there will be no need for auto generated classes.
You will not have to update your service reference every time you change the contract.
For what it's worth, I was running in to this same error after moving my data contracts to a separate library. Updated the service references multiple times and tried all combinations of the settings for assembly reuse, to no avail.
What eventually fixed it for me was to 1) restart Visual Studio and 2) update the service reference. The auto-generated code in Reference.cs in the service definition looked very different and did not duplicate my data contract class. It used the proper reference from my library. So something must be getting cached in the IDE.
Hopefully someone else finds this useful.
I was able to fix this by right-clicking on the Service Reference and then changing from "Reuse types in all referenced assemblies" to "Reuse types in specified referenced assemblies" and then checking the specific common assembly.
Just remove the reference to Common project from your ClientApp project and the error should go away. When you're creating a proxy for your service, all dependent code from the service must be injected into the proxy. If you want your types to be same as those on the service side, just enable the 'Reuse types' option while generating the proxy code (otherwise they will be put under a different namespace).
The problem here is that PrimaryColor exists in both Common and ClientApp.LibraryServiceReference and you are referencing both namespaces in your class.
To overcome this issue, either explicitly reference the instance that you require, i.e.
Common.PrimaryColor color = ....
or set up an alias:
using Service = ClientLibraryServiceReference;
...
Service.PrimaryColor color = ......
When making the service reference aren't there some options that say something like: "inlcude common types in generated service contract" ?
I have the idea that in your service reference the classes are "copied" and that's why you get this error. Inspect the generated service files, remove then and add them again with "Add Service Reference" and see what options you have there.
EDIT
Although I'm almost sure that the Type PrimaryColor is defined twice. One time in the common project and one time in your service reference, you can also try this in your clientApp (to more explicitely specify the PrimaryColor Type):
Common.PrimaryColor color = client.GetColor();

How to create a WCF web service within an ASP.NET application that can return instances of an interface as a transparent proxy

My use-case:
I already have a working ASP.NET application
I would like to implement a new Web Service as part of that application
I am supposed to use a WCF service (*.svc), not an ASP.NET web service (*.asmx)
The service needs to have one operation, let’s call it GetInterface(), which returns instance of an interface. This instance must reside on the server, not be serialized to the client; methods called on that interface must execute on the server.
Here’s what I tried (please tell me where I went wrong):
For the purpose of testing this, I created a new ASP.NET Web Application project called ServiceSide.
Within that project, I added a WCF Service using “Add → New Item”. I called it MainService. This created both a MainService class as well as an IMainService interface.
Now I created a new Class library project called ServiceWorkLibrary to contain only the interface declaration that is to be shared between the client and server, nothing else:
[ServiceContract]
public interface IWorkInterface
{
[OperationContract]
int GetInt();
}
Back in ServiceSide, I replaced the default DoWork() method in the IMainService interface as well as its implementation in the MainService class, and I also added a simple implementation for the shared IWorkInterface. They now look like this:
[ServiceContract]
public interface IMainService
{
[OperationContract]
IWorkInterface GetInterface();
}
public class MainService : IMainService
{
public IWorkInterface GetInterface()
{
return new WorkInterfaceImpl();
}
}
public class WorkInterfaceImpl : MarshalByRefObject, IWorkInterface
{
public int GetInt() { return 47; }
}
Now running this application “works” in the sense that it gives me the default web-service page in the browser which says:
You have created a service.
To test this service, you will need to create a client and use it to
call the service. You can do this using the svcutil.exe tool from the
command line with the following syntax:
svcutil.exe http://localhost:59958/MainService.svc?wsdl
This will generate a configuration file and a code file that contains
the client class. Add the two files to your client application and use
the generated client class to call the Service. For example:
So on to the client then. In a separate Visual Studio, I created a new Console Application project called ClientSide with a new solution. I added the ServiceWorkLibrary project and added the reference to it from ClientSide.
Then I ran the above svcutil.exe call. This generated a MainService.cs and an output.config, which I added to the ClientSide project.
Finally, I added the following code to the Main method:
using (var client = new MainServiceClient())
{
var workInterface = client.GetInterface();
Console.WriteLine(workInterface.GetType().FullName);
}
This already fails with a cryptic exception in the constructor call. I managed to fix this by renaming output.config to App.config.
I notice that the return type of GetInterface() is object instead of IWorkInterface. Anyone know why? But let’s move on...
Now when I run this, I get a CommunicationException when calling GetInterface():
The underlying connection was closed: The connection was closed unexpectedly.
How do I fix this so that I get the IWorkInterface transparent proxy that I expect?
Things I’ve tried
I tried adding [KnownType(typeof(WorkInterfaceImpl))] to the declaration of WorkInterfaceImpl. If I do this, I get a different exception in the same place. It is now a NetDispatcherFaultException with the message:
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:GetInterfaceResult. The InnerException message was 'Error in line 1 position 491. Element 'http://tempuri.org/:GetInterfaceResult' contains data from a type that maps to the name 'http://schemas.datacontract.org/2004/07/ServiceSide:WorkInterfaceImpl'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'WorkInterfaceImpl' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.
The InnerException mentioned is a SerializationException with the message:
Error in line 1 position 491. Element 'http://tempuri.org/:GetInterfaceResult' contains data from a type that maps to the name 'http://schemas.datacontract.org/2004/07/ServiceSide:WorkInterfaceImpl'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'WorkInterfaceImpl' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.
Notice how this seems to indicate that the system is trying to serialize the type. It is not supposed to do that. It is supposed to generate a transparent proxy instead. How do I tell it to stop trying to serialize it?
I tried adding an attribute, [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)], to the WorkInterfaceImpl class. No effect.
I tried changing the attribute [ServiceContract] on the IWorkInterface interface (declared in the shared library ServiceWorkLibrary) to [ServiceContract(SessionMode = SessionMode.Required)]. Also no effect.
I also tried adding the following magic system.diagnostics element to the Web.config in ServerSide:
<system.diagnostics>
<!-- This logging is great when WCF does not work. -->
<sources>
<source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
<listeners>
<add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
This does generate the c:\traces.svclog file as promised, but I’m not sure I can make any sense of its contents. I’ve posted the generated file to pastebin here. You can view this information in a more friendly UI by using svctraceviewer.exe. I did that, but frankly, all that stuff doesn’t tell me anything...
What am I doing wrong?
The use-case I am describing is not directly supported by WCF.
The accepted work-around is to return an instance of EndpointAddress10 which points to the service for the “other” interface. The client must then manually create a Channel to access the remote object. WCF doesn’t properly encapsulate this process.
An example that demonstrates this is linked to from the MSDN article “From .NET Remoting to the Windows Communication Foundation (WCF)” (find the text that says “Click here to download the code sample for this article”). This example code demonstrates both .NET Remoting as well as WCF. It defines an interface that looks like this:
[ServiceContract]
public interface IRemoteFactory
{
IMySessionBoundObject GetInstance();
[OperationContract]
EndpointAddress10 GetInstanceAddress();
}
Notice that the interface-returning method is not part of the contract, only the one that returns an EndpointAddress10 is marked with [OperationContract]. The example calls the first method via Remoting, where it correctly creates a remote proxy as one would expect — but when using WCF it resorts to the second method and then instantiates a separate ChannelFactory with the new endpoint address to access the new object.
What is MainServiceClient()? It is the class marshaling the client messages to the server.
You should take a look at a related SO post on returning interfaces as parameters in WCF. ServiceKnownTypeAttribute may be helpful.
Sessions may also be what you're looking for MarshalByRef as it relates to .NET Remoting behaviors.
Another approach (as mentioned on MSDN Forums) is to return the EndpointAddress of the service interface instead of the interface itself.
WCF does serialize everything - regardless of the binding. The best approach you should take if you need to communicate with the service on the same system is to use IPC transport binding (net.pipe).
What you are trying to do is a direct violation of the SOA Tenet: "Services share schema and contract, not class". What this means it that you don't actually pass implementation code from the service to its consumers, just the return values that are specified in the contract itself.
The main focus of WCF and SOA in general is interoperability, meaning services should be accessible to clients of any platform. How would a Java or C++ consumer be able to use this service you are designing? Short answer is that it couldn't, which is why you will find it difficult if not impossible to serialize this code over messaging standards like SOAP.
A more appropriate way to structure this code would be to host each implementation of IWorkerInterface as its own service (it has been defined as a service contract, after all), and expose each service on a different endpoint. Instead of MainService behaving as remote factory for proxies to an IWorkerInterface, it could act a as an endpoint factory to the different services you have set up. Endpoint metadata could easily be serialized and provided to the client by IMainService. The client could then take that metadata and construct a proxy to the remote implementation, either through some custom IServiceProxy implementation, or even through the objects already provided to you by WCF (such as the ChannelFactory).

Unable to get WCF Test client to test WCF Service Library

I am attempting to replace a WSE service with the WCF equivalent where the WSDL is provided externally.
First, I used svcutil and wsdl to generate all the service and client classes (ATP, I'm only concerned with the service implementation.) I generated an empty WCF Service Library project and replaced/renamed the IService1.cs with a class named for the interface ServiceContractAttribute generated. I then renamed the implementation class Service1.cs with the name of the implementation-class JINDEXWcfListener.cs. I removed the generated code from this class and created class definition JINDEXWcfListener:[interface name].
The tool auto-generated the implementation of the interface. I used the single method adorned with [OperationContractAttribute] to put my local implementation code. I modified the default app.config generated to adjust the contract and service names as required.
When I start debug, I can see that the service is starting in the WTC. However, when the single operation is exposed, the is a red dot with a yellow question mark in front of the operation name. When I RC on the op name, I get "This operation is not supported in WCF Test client" with no additional information. What is wrong?
WCFTestClient has quite a few limitations. I have fought "problems" for several hours that later turned out to be just WCFTestClient problems. Complex objects can give you a lot of grief, also any custom lists, etc such as a custom implementation of the IList interface. Try out WcfStorm. I think they have a free version and a trial version.

WCF service reference stopped generating code for one project

I have references to two different WCF services in a project. I updated the reference for one of the services, and now no code is generated for it. The references.cs file just has the "this is genrated code" comment at the top. Updating that same service in other projects and updating the other service both work fine. It's only that one service reference in this one project that's causing the problem, and I'm getting no information from Visual Studio (it just says it failed to generate code and I should look at the other errors, which provide no information).
If I uncheck the "reuse types in referenced assemblies", code is generated, but I don't want to have this one project be different from the others. I'd like to solve the problem. Re-checking the reuse type option produces an empty references.cs file, again. The collection type doesn't seem to matter, either.
How can I diagnose and solve this problem?
Update:
It seems I was mistaken. Updating the service reference does seem to break the generation in other projects as well. I did also notice these warnings, as well:
Custom tool warning: Cannot import wsdl:portType
Detail: An exception was thrown while running a WSDL import extension: System.ServiceModel.Description.DataContractSerializerMessageContractImporter
Error: ISerializable type with data contract name 'Exception' in namespace 'http://schemas.datacontract.org/2004/07/System' cannot be imported. The data contract namespace cannot be customized for ISerializable types and the generated namespace 'TheDefaultNamespaceOfTheProject.ServiceReferenceName' does not match the required CLR namespace 'System'. Check if the required namespace has been mapped to a different data contract namespace and consider mapping it explicitly using the namespaces collection.
Obviously I changed the namespace there, but it seems like it's trying to map System.Exception to ThatNamespace.Exception? Why would it do that, and how can I correct it? I think this is the key to the whole thing.
I had a similar error in a Silverlight application making WCF calls. I created a WCF method that passed an Exception object as a parameter. It turns out that Exception objects are not serializable in Silverlight because:
http://blogs.msdn.com/b/suwatch/archive/2009/01/21/wcf-silverlight-exception-and-serialization.aspx
Here's the relevant excerpt:
WCF’s DataContractSerializer serialize s Exception class via
ISerializable (Exception in .Net Framework implements ISerializable).
However, in Silverlight, there is no ISerializable interface.
Therefore, Serialization information of Exception transferred over the
wire will not be set into the Exception class. This does not only
apply to Exception but also any types implementing ISerializable on
the .Net Framework serialized to Silverlight.