Implementing IOrganizationService - wcf

I've been working on implementing the IOrganizationService interface in the CRM 2011 SDK - At first I wrote a simple Windows Service wrapper and this was throwing serialization exceptions any time i tried connecting to it. So I wrote a simple host for IIS. At first it seemed to work but any time there is a Fault in the service it throws the same error when trying to connect to the service after the first attempt.
The formatter threw an exception while trying to deserialize the message: There was an error whi
trying to deserialize parameter http://schemas.microsoft.com/xrm/2011/Contracts/Services:request. The InnerException
message was 'Error in line 1 position 497. Element 'http://schemas.microsoft.com/xrm/2011/Contracts/Services:request
contains data from a type that maps to the name 'http://schemas.microsoft.com/crm/2011/Contracts:WhoAmIRequest'. The
deserializer has no knowledge of any type that maps to this name. Consider changing the implementation of the
ResolveName method on your DataContractResolver to return a non-null value for name 'WhoAmIRequest' and namespace
'http://schemas.microsoft.com/crm/2011/Contracts'.'.
I am at a bit of a loss here - it works fine - throws a fault somwhere - attempt to reconnect and throws this error. After which I must re-compile and deploy the DLL to the IIS site bin dir again. I can provide some small code samples of if needed but keep in mind that I am inheriting the interface directly from the SDK assembly.
EDIT:
And I am unable to change the program the connects to the WCF Service as it is a third-party tool. When using the traditional web-services it is fine.
EDIT (Implementation Code - Excluding the implemented methods ..>):
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(
ConcurrencyMode = ConcurrencyMode.Multiple,
MaxItemsInObjectGraph = int.MaxValue,
Name = "OrganizationServiceImplementation",
Namespace = "http://schemas.microsoft.com/xrm/2011/Contracts")]
public class OrganizationServiceImplementation : IOrganizationService
{
}

Related

Problem accessing wcf data service inside class library referenced by my web app

Getting resource error when accessing a cloud data service through a vb.net class from my Web App.
I have written a vb.net class library (call it MYAPPIF) referencing a wcf data service with common functions that work on these. For example I may want to save a transaction, I will do it through this class library. This class library is then referenced by my web app and with "Imports MYAPPIF" I can see the common functions and I can see the cloud service reference.
dim oMyAppIF = new MyAppIF.class
dim oCloudContext = oMyAppIF.GetWCFConnection() ' a function in class
oQueryList = (From seldata In oCloudContext.vwContractList
Order By seldata.cnname
Select seldata).ToList()
The web site compiles fine but when I run it I get the following error :
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.Services.Client.DataServiceClientException: Resource not found for the segment 'vwContractList'.
Stack Trace:
[DataServiceClientException: Resource not found for the segment 'vwContractList'.]
System.Data.Services.Client.QueryResult.ExecuteQuery() +487
System.Data.Services.Client.DataServiceRequest.Execute(DataServiceContext context, QueryComponents queryComponents) +186
Do not invoke the service by adding a service reference in the class library project, because the class library will use the WebConfig file of the current Web APP project instead of the configuration of the class library. You can copy the configuration under servicemodel into the current project, or use the channel factory call to write the configuration dynamically.
public string Invocation()
{
//ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
//return client.GetData(34);
ChannelFactory<IService1> factory = new ChannelFactory<IService1>(new BasicHttpBinding(), new EndpointAddress("http://10.157.18.36:12000/service1.svc"));
IService1 sv = factory.CreateChannel();
return sv.GetData(46);
}
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-the-channelfactory
Feel free to let me know if there is anything I can help with.

WCF RIA services and WSDL generation

Need help on an issue I am having. I inherited this WCF RIA project and am trying to understand a couple of things.
When I publish the project, how does the WSDL get generated and put on the URL that I published to?
And I want to incorporate FaultException handling so as to transmit the exceptions to the client side. I read some stuff regarding the FaultException on the web and was able to get a small sample working with the regular WCF service.
I thought it would be similar within my actual project. But unfortunately I am running into some issues(probably due to my lack of WCF + RIA services knowledge).
So in my actual project my Context class derives off of LinqToEntitiesDomainService.
I created a new ContextFaultException class which had some methods to capture some custom error messaging.
Then I applied the [FaultContract(typeof(ContextFaultException))] to some of the methods in my Context class. Everything compiles and all is fine. But when I published to a website and then when I added this service reference to the client, I don't see my new ContextFaultException in the Reference.cs file that's generated.
I thought may be moving it within the Context class will solve the issue. So I made my ContextFaultException class as an inner class of this Context class but I am running into some other issues. Before I try to figure out these issues, I just want to know if this the right approach?
Any suggestions/pointers??
TIA
The URL must be formatted to get to the namespace wdsl
for example:
namespace My.Namespace.Services
{
[EnableClientAccess()]
public partial class MyClassName : LinqToEntitiesDomainService<XXX>
{
....
}
}
Then use the following pattern for the url
http://YOURHOST/APP/Services/My-Namespace-Services-MyClassName.svc?wsdl
Use "-" for the "."

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).

Error when writing C++ wrapper for 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...

WCF service contract not working with Microsoft Chart control as param

I have the following service contract:
using System.Windows.Forms.DataVisualization.Charting;
...
[ServiceContract]
public interface IMyService
{
[OperationContract]
bool Print(Chart chart);
}
When I run attempt to host the service (in Visual Studio under the WCFTestClient) I get the following exception:
Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata.
It seems to be an issue with the Chart type itself as changing this to something else works fine.
Any ideas?
Most likely this is due to the Chart type not being serializable.
Try sending over an object containing the chart data instead.
You can also check out the Chart Serializer
http://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.chartserializer(VS.100).aspx
It helps handle the serialization for you, which I suspect is probably the reason why you may be getting the message posted.