I'm looking to call a .NET 4.6 service inside my .NET Core RC2 app.
I have tested the service within the WCF Test Client supplied by Microsoft and it works fine, I would like to now consume it inside my .NET Core application but am unsure on how to do that.
I have tried using the svcutil to generate the service reference file but I'm guessing this isn't really designed for the new .NET framework as it uses IExtensibleDataObject which doesn't exist in Core and the namespace System.Runtime.Serialization which now seems to have split into Xml, Primitives and Json.
DOes anybody have a example how I could simply consume an external (Not within my project) WCF.
Many Thanks
Microsoft released "WCF Connected Service for .NET Core RC2 and ASP.NET Core RC2". It should do the job.
I used it to generate client code for my service and:
it uses these attributes on DataContract classes:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "0.2.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="Person", Namespace="http://schemas.datacontract.org/2004/07/Mock")]
public partial class Person : object
It uses [System.Runtime.Serialization.DataMemberAttribute()] for DataContract properties
It uses these attributes to define service contract:
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "0.2.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="Mock.IMockService")]
public interface IMockService
This is a sample opertaion definition inside the contract interface:
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IMockService/LookupPerson", ReplyAction="http://tempuri.org/IkMockService/LookupPersonResponse")]
System.Threading.Tasks.Task<Mock.LookupPersonResponse> LookupPersonAsync(Mock.LookupPersonRequest request);
To mark request and response objects it uses:
[System.ServiceModel.MessageContractAttribute(WrapperName="LookupPerson", WrapperNamespace="http://tempuri.org/", IsWrapped=true)]
public partial class LookupPersonRequest
And property of the request/response is annotated with:
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://tempuri.org/", Order=0)]
public CepikMock.PersonSearchCriteria criteria;
Finally it generates basic IClientChannel interface
public interface IMockChannel : Mock.IMockService, System.ServiceModel.IClientChannel
{
}
And a ClientBase implementation
public partial class MockServiceClient : System.ServiceModel.ClientBase<Mock.IMockService>, Mock.IMockService
Inside the client class, each service method is exposed like this:
public System.Threading.Tasks.Task<Mock.LookupPersonResponse> LookupPersonAsync(Mock.LookupPersonRequest request)
{
return base.Channel.LookupPersonAsync(request);
}
Related
I have given reference to a dll in my WCF service application. My WCF operation requires input of type class (let's say XYZ) which is present in that dll.
Now, is it possible to expose that class to the clients so that they can call the exposed wcf method?
If yes then can you please explain the idea or with some pesudo code/references ?
Thanks in advance !
Contract:
[OperationContract]
void Add(XYZ item);
Server:
public void Add(XYZ item){}
[DataContract]
class XYZ{}
Client:
var item = new XYZ();
client.Add(item);
Dll containing 'XYZ' should be referenced by both Server and Client.
Class 'XYZ' should have 'DataContract' attribute.
Implementation is more or less similar to FaultContracts in WCF.
I have three projects in my Visual Studio Solution:
“Core” contains a bunch of types.
"WCF Service” uses all of the types in “Core” in service methods.
“Test Client” is a test client app and just has a bunch of test
code.
When I consume my WCF Service in my Test Client, everything looks and works great. The proxy for the service methods are generated so I can pass parameters with the correct type like Core.BusinessObj. However, when I consume that same WCF Service from Core, the proxy being generated requires those same service methods to pass like this: ServiceProxy.BusinessObj. This is causing a problem since I want to create object of type Core.BusinessObj and pass them to my service no matter where that service is being consumed. I am sure this has something to do with referencing my WCF Service within the same project where all the types are defined, but can’t figure out how to get the namespaces correctly identified.
Does anyone know what I am doing wrong?
You're not doing anything wrong - that's just the way WCF works!
When you build the service, you define the service methods and the parameters (and their data types) that those services will expect. This is packaged up on the server side and typically exposed via metadata exchange (MEX).
When the client comes along, and creates the client side proxy for your service, all it can rely on are the bits and pieces in the metadata - description of the service methods (names, parameters), and the description of what the XML will look like that travels between client and server.
Client and server in WCF are talking to one another via serialized (XML) messages - there is no other connection - no direct link or anything. So all the client can do is to make sure his data types that he creates based on the service metadata will serialize into the same XML as the service expects (and that he's able to deserialize the XML messages from the server).
The client creates new client-side types that will have the same "XML footprint" (the same structured in serialized XML) - but that's all he can do. That's why you get types that look very similar - but they are different (typically in a different namespace). That's also the reason why you shouldn't have any functionality (code) in your server-side data contracts - you cannot serialize functionality over XML messages .....
Now, if you control both ends of the communication wire (both the server and the client) and you write both of them in .NET, then you can take a "shortcut" to re-use the types. Basically, you need to do what you did - put all the types and interfaces into a separate assembly ("Core"). Next: before you create your WCF proxy on the client side, make sure the client project references that "Core" assembly. When you create the WCF client-side proxy with the "Core" assembly referenced, you can tell WCF to "reuse types in referenced assemblies" - if you have this option on (it's on by default), then if your referenced assemblies already contain a data type that matches the needs of the WCF client, then that type (from your "Core" assembly) will be reused (instead of a new one created).
WCF - Add Service Reference - Advanced Options
Make sure that your Core.BusinessObj is Serializable
(Example, assuming its for .NET 4)
[Serializable]
public class BusinessObj
Make sure that your service is building fine (with no errors)
Update the service reference (After successfully building of the service)
I built a solution as you described. And it passes the test without any problem.
In my solution there are 3 projects now
Core
WCFService
TestClient
Project Core has one class "BusinessObj"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Core
{
[Serializable]
public class BusinessObj
{
public int id { get; set; }
}
}
Project WCFService has a WebService named "Service1"
(reference to Core has been added)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WCFService
{
public class Service1 : IService1
{
public Core.BusinessObj GetBusinessObj()
{
return new Core.BusinessObj()
{
id = 1
};
}
}
}
Test project, TestClient has one unit test "UnitTest1"
(reference to Core has been added)
(service reference to Service1 has been added)
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestClient.ServiceReference;
using Core;
namespace TestClient
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Service1Client ServiceProxy = new Service1Client();
BusinessObj x = ServiceProxy.GetBusinessObj();
Assert.IsTrue(x.id == 1, "Something's wrong dude!!!");
}
}
}
I think "using Core;" is missing from your TestClient
We have already Business logic layer available in our application. It has lots of classes. and this is in separate library(.Dll). Now we want to use this in to our WCF Service. For that We create new project and gave reference to that .Dll. But we are not able to see our class .. I verify that class is public..
Could you please let me know what should I do?
Here I am attaching my code what I need to do
My Business Layer class
namespace BusinessLayer
{
public class MessageContext : Dictionary<string, object>
{ ....}
}
Now I am reference this Project to my WCF project and tried to expose this class into WCF client. So I Create one MessageContextHelper class which inherit from MessageContext the code is following
namespace WCFService
{
public class MessageContextHelper : MessageContext
{ ...... }
}
On client I am not able to get MessageContextHelper class.
Thanks
JK
WCF doesn't send business logic classes to the client. If you're using the SOAP version of WCF (BasicHttpBinding for example) then what WCF will expose is methods that are in your service contract. Your client can call those.
So if you have methods in a business logic class that you want exposed, create methods in your WCF service that will in turn call the business layer methods.
A very rudimentary (and not complete) version would look something like this:
namespace WCFService
{
public class MyService: IMyService
[OperationContract]
public String DoSomeStuff() {
return MessageContext.DoSomething();
}
}
You absolutely cannot (and should not) use your business layer from your client code. As the previous reply message, WCF does not send your business class to the client. Think about how long it will take to send. The business layer (your dll) should be used on the server only. Your WCF should only accept modified/new data from the client, pass the data to the business layer, and then return the results to the client.
I have a plugin that I will instantiate at runtime and I want to pass it a WCF service from the application host. The application host is responsible for creating the connection to the service. The reason for this is that a single service can be used by multiple plugins, but the plugins should only know about its interface since there may be several implementation of IMyPluginServices. For instance, the Run method of the plugin instance would be:
public void Run(IMyPluginServices services)
{
services.DoSomething();
}
The problem I am running into is that I don't know how to create a service of type IMyPluginServices and pass it to the Run function. The service reference generated by VS 2010 doesn't seem to create an object of type IMyPluginServices that I can pass to it. Any help would be greatly appreciated. Thanks.
When you add a service reference in VS 2010 for a service it generates an interface named IMyService which contains methods for each OperationContract in your service. It also generates a concrete class named MyServiceClient, which can be constructed and then used to invoke your service.
Now, the problem that you're running into, I believe, is that MyServiceClient is a subclass of ClientBase<IMyService>, and does not implement the generated IMyService interface (which is a real pain).
To get around this problem I ended up making a new interface:
public interface IMyServiceClient : IMyService, IDisposable, ICommunicationObject
{
}
(Note: IDisposable and ICommunicationObject are only required if you want your module to be able to detect/react to faulted channels and other such things).
I then extend MyServiceClient with a partial class (in the assembly that contains my WCF Service reference):
public partial class MyServiceClient : IMyServiceClient
{
}
Now in my modules I can accept an IMyServiceClient instead of an IMyService, and still execute all of the methods that I need to. The application in control of the modules can still create instances of MyServiceClient as it always did.
The beauty of this is that your new interface and partial class don't need any actual code - the definitions suffice to get the job done.
I have a seperate assembly ( reference by WebService) in which I have created a class ( Let's say ABC ) and a collection of that class ( ABCCollection : IList where T:ABC ). Now when I build the proxy files (output.config and Service1.cs) then the defienation of these two classes are not exposed. Instead the ABCCollection is exposed in Servic1.cs is like ABCCollection4IP3 .
Please let me know the possible cause for this issues..
They are not meant to be the same type. This is by design. Consider how it would work if your service were in .NET and your client in Java. They would clearly be two different types.
A best practice when designing a WCF service is to split up your project into seperate assemblies:
Assembly SomeProject.ServiceContract
This assembly contains your service contract (just the interfaces).
Example:
[ServiceContract (...)]
public interface ICan {
[ServiceOperation (...)]
void EatCandies (MyListOfCandies candies);
}
Assembly SomeProject.DataObjects
This assembly contains all your data objects which is used by your service contract.
Example:
[DataObject]
public class MyListOfCandies : List<Candy> {
...
}
In your project, which is consuming your web service reference the assembly "SomeProject.DataObjects" and then add your web service. You'll see that Visual Studio will no longer generate any stub objects but will use your implementation.
You can do the same with the ServiceContract assembly. This way you still can use web services, but you will get compile errors when you change your interface.