Hi it might be a duplicate but writing here since i was unable to fix the issue from the posts i have seen so far.
I am having DataContracts in my WCF services and on my client I want to consume my services as DataContract objects only, but when i am creating a Service reference my WCF services generating the message contracts for all the methods.
[ServiceContract]
public interface IUserService
{
[OperationContract]
UserVO GetUser(int Id);
}
[DataContract]
public Class UserVO
{
[DataMember]
public int Id{get;set;};
}
I have un-checked the "Always generate message contracts" and checked reuse types in referenced libraries where entities are available(Data Contract).
My reference.cs is having a message contract like
System.ServiceModel.MessageContractAttribute(WrapperName="GetUser", WrapperNamespace="http://tempuri.org/", IsWrapped=true)]
public partial class GetUserRequest {
}
EDIT 1:
my Reference.svcmap has client configuration like this
<ClientOptions>
<GenerateAsynchronousMethods>false</GenerateAsynchronousMethods>
<EnableDataBinding>true</EnableDataBinding>
<ExcludedTypes />
<ImportXmlTypes>false</ImportXmlTypes>
<GenerateInternalTypes>false</GenerateInternalTypes>
<GenerateMessageContracts>false</GenerateMessageContracts>
<NamespaceMappings />
<CollectionMappings>
<CollectionMapping TypeName="System.Collections.Generic.List`1" Category="List" />
</CollectionMappings>
<GenerateSerializableTypes>true</GenerateSerializableTypes>
<Serializer>Auto</Serializer>
<UseSerializerForFaults>true</UseSerializerForFaults>
<ReferenceAllAssemblies>true</ReferenceAllAssemblies>
<ReferencedAssemblies />
<ReferencedDataContractTypes />
<ServiceContractMappings />
EDIT 2:
I am trying to achieve something like below
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IUserService/GetUserDetails", ReplyAction="http://tempuri.org/IUserService/GetUserDetailsResponse")]
[System.ServiceModel.FaultContractAttribute(typeof(UserServiceFaultContract), Action="http://tempuri.org/IUserService/GetUserDetailsUserServiceFaultContractFault", Name="UserServiceFaultContract", Namespace="http://schemas.datacontract.org/2004/07/mynamespace")]
MyEntities.UserVO GetUserDetails(int id);
By default, WCF uses the DataContractSerializer class to serialize data types. If your scenario requires the use of the XmlSerializer, instead, then you can manually switch to the XmlSerializer by applying the XmlSerializerFormatAttribute attribute to your service
The following MSDN article describes the process:
https://msdn.microsoft.com/en-us/library/ms733901(v=vs.110).aspx
Recommend careful consideration of the security notes before switching serialization classes.
Then share the assembly with the client! Put the service interface and all the DataContracts in one assembly. Then the client can use the channel channelfactory "pattern" to connect to the WCF service.
Related
Is possible to know which contract has been called in a multiple contract service? In this, case, in the constructor.
The implementing class of the service is like this:
public class Service : IContract1, IContract2
{
public Service()
{
//Identify if constructor was called from IContract1 or IContract2
}
}
I think what you want to implement is a WCF Message Inspector. A MessageInspector is a "message filter" that can intercept and inspect the messages coming in or going out of the service layer infrastructure.
On the server, you would implement the IDispatchMessageInspector Interface.
Here is a pretty good example:
http://www.aspnet4you.com/wcf/index.php/2013/01/30/message-interception-auditing-and-logging-at-wcf-pipeline/
I am using C# Visual Studio 2012 to create a wcf service.
I had the WSCF.blue tool generate the wsdl from the xsd-s. Then I generated the web service code using the same tool. WSCF.blue does not create a Service Contract and a Data Contract. It creates an interface and a .svc file that contains a class that implements the interface.
When generating the web service code I selected the option to create the abstract classes because I want to be able to keep the implementation of these classes in a separate file.
The abstract class looks like this:
[KnownType(typeof(WebMobileImplementation))]
public abstract class WebMobile : IWebMobile
{
public abstract PutLocationsResponse PutLocations(PutLocationsRequest request);
}
The implementing class (in a different file) looks like this (for now):
public class WebMobileImplementation : WebMobile
{
public override PutLocationsResponse PutLocations(PutLocationsRequest request)
{
PutLocationsResponse response = new PutLocationsResponse();
return response;
}
}
When trying to browse the service I get the message: "Service implementation type is an interface or abstract class and no implementation object was provided"
I thought that adding the knowntype to the implementing class will do the trick but it seems that the implementation is not 'seen' when running the service. What else can I do to 'connect' them?
In WCF 4.0, you can define virtual service activation endpoints that map to your service types in Web.config. This makes it possible to activate WCF services without having to maintain physical .svc files.
<serviceHostingEnvironment>
<serviceActivations>
<add relativeAddress="WebMobile.svc"
service="WebMobileNamespace.WebMobileImplementation"/>
</serviceActivations>
</serviceHostingEnvironment>
like the title says, I want to keep my logic in a separate project to the service contract(s) so this can stay separate and hidden. I've seen it said that this can be done, but I can't find any examples as to how.
I moved all the necessary code out to a different project, but when I test it only the types are visible to the client, not the methods.
All the methods are marked as [OperationContract] in the interface.
I'm guessing there must be a way of specifically connecting the implementation logic to the contract other than just Class : IInterface, otherwise, what would happen if there were 2 similar classes, e.g.: Class1 : IInterface and Class2 : IInterface? How would WCF know which class to use?
I've done it this way (sorry for bad names, that's just for concept):
1) Created separate project for implementation
2) Created separate project for service contract (to avoid circular references)
3) Added service contract project as reference to implementation project
4) Added contract and implementation project to host project
5) Updated Service.svc with full type name
Service.svc body:
<%# ServiceHost Language="C#" Debug="true" Service="Implementation.ServiceImplementation" %>
How would WCF know which class to use?
Because you tell it, in the various configuration files.
I can heartily recommend WCF the Manual Way…the Right Way for motivation and a complete walkthrough for what you are trying to do - what I have here is just the pertinent points of such an implementation.
You have three assemblies: Service, Client, ServiceContracts (interfaces only). Service and Client both reference ServiceContracts. Service contains classes implementing the interfaces. Client has proxy classes:
using System.ServiceModel;
using ServiceContracts;
public class ExampleServiceProxy : ClientBase<IExampleService>, IExampleService
{
public string ExampleMethod()
{
return Channel.ExampleMethod();
}
}
The client's config file contains an entry pointing at the service's svc file; the service's svc file looks like this:
<%# ServiceHost Language="C#" Debug="true" Service="Service.ExampleService"
CodeBehind="ExampleService.svc.cs" %>
And the service .svc.cs file looks like:
using ServiceContracts;
public class ExampleService : IExampleService
{
public string ExampleMethod()
{
return string.Empty;
}
}
That's it!
My goal is to load an external class in a running application environment (like a plugin model). Creating an instances of the class in an running environment is not the problem (the classes using an Interface). The problem is to get the class which must be available from a central WCF services.
Is it possible to transport an class or assembly to the client by using WCF?
Something like this:
[ServiceContract]
public interface ISourceData
{
[OperationContract]
xxx GetClassData { get; set; } // <-- here to get data the class to app can create an instances of this
}
I hope that you understand my situation. Thanks.
First of all, the attribute in your sample above must be OperationContract, not DataContract. The DataContract attribute is for the class that you want to return in GetClassData.
The problem in your situation is that on the client side the class itself is not replicated when you add the service reference, but a stub is generated for the properties that you define in your DataContract. So you get the data, but not the logic.
You could now create an assembly which defines the data classes to be exchanged and add them to both the service and the client, but as I understand your question, you want to dynamically load assemblies in the service and send these "implementations" to the client without the client actually having access to the DLL that implements the class. This may not be possible in an easy way.
EDIT
Re-reading your question I now understand that you do not want to "transfer an instance", but you want to transfer the class definition. One way would be to actually transfer the source code for the class and try to use Reflection.Emit to create a dynamic assembly. A sample of this can be found here.
Yes , you can .
and also you must to define the type of your class like ↓
[ServiceKnownType(typeof(xxx))]
public interface IService
I think you need the assembly on the client so you need to transfer the dll containing the assembly to the client, then have the client save it in a plugins directory for the app and have the app and load it from there.
Although I image that this is going to be a permissions nightmare to get the app to be able to use the dlls downloaded from the service.
You would mark up the classes used in your interface like this:
[ServiceContract]
public interface ISourceData
{
[OperationContract]
MyClass GetClassData();
}
[DataContract]
public class MyClass
{
[DataMember]
public string MyMember1 {get; set;} // included in transport
public int MyMember2 {get; set;} // not included
}
I know when you create a service you can create a generic DataContract:
[DataContract(Name = "Get{0}Request")
public sealed class GetItemRequest<T>
where T : class, new() { ... }
[DataContract(Name = "Get{0}Response")
public sealed class GetItemResponse<T>
where T : class, new() { ... }
[ServiceContract]
public void MyService : IMyService
{
[OperationContract]
GetItemResponse<Foo> GetItem(GetItemRequest<Foo> request);
}
This generates a GetFooRequest and GetFooResponse definition for my WSDL. Now, what I'm curious about is if it is possible to go in the other direction?
Is it possible to create a client that uses the Generic DataContracts and pass those to the server as a concrete object? I attempted this after adding a Service Reference and it didn't really work out so well. So this is more of me wondering if there is any way (even if it means not adding a Service Reference) to do this?
Ultimately, WCF is going to look at the contract class. If that is generated from WSDL/MEX it won't have this (since this isn't how it is expressed in the metadata) - but if your client has the code as above, then sure it should work fine.
If you add a library reference (i.e. a dll / project reference) to your DTO dll from the client, and ensure WCF has shared-assemblies enabled, it should work. If it still baulks, then cheat: use a service reference just to get the config data. Then delete the service reference but keep the configuration (those config files are a pain otherwise). Then it should locate the type from the library.