How do I export metadata for a single contract with svcutil.exe? - wcf

I have two ServiceContracts implemented as interfaces. I want to export the metadata for only one of them. The trick is that both interfaces are implemented by the same class. Therefore, I don't think that I can use /excludeTypes. Please include example syntax when answering. Thanks!
EDIT: A co-worker recently asked me why this is necessary. The reason why is that the first ServiceContract is for a REST service, which it doesn't make sense to export metadata for. So I get two wsdl and xsd files generated, distinguishable only because the second filename is appended with "1". This makes tooling difficult, and adds more clutter to the output directory.
I've added a bounty to try and generate interest in this question.

I created a Service Contract class implementing 2 Interfaces like you described.
namespace NS
{
[ServiceContract]
public interface IREST
{
[OperationContract]
string WorldHello(string name);
}
[ServiceContract]
public interface IInterface
{
[OperationContract]
string HelloWorld(string name);
}
public class CI2 : IREST, IInterface
{
public string WorldHello(string name)
{
return "World Hello: " + name;
}
public string HelloWorld(string name)
{
return "Hello World: " + name;
}
}
}
when running svcutil normally, I get a wsdl with methods from the 2 interfaces
when I run svcutil with /excludeType:IREST for example, I get only IInterface methods.
svcutil /excludeType:NS.IREST ci2service.exe
are you using the same configuration? In that case /excludeType works.

Related

Questions on WCF regarding Class lirbary and also reg. DataContract

URL: http://wcftutorial.net/Introduction-to-WCF.aspx
Question 1:
Above tutorial mentions a Tip:-
a. Define the service in Class library and refer the class library in Host project. Don’t use service class in host project.
b. Always create the service with Interface->Implementation format, mention the contract in Interface.
c. Define the service in Class library and refer the class library in Host project. Don’t use service class in host project.
Question: Does the good practice suggest to create another class library rather then the existing IService1.cs and Service1.svc? Can anyone here give me an example of what author is trying to say in the above points?
Question 2:
When I create a new WCF application it has got IService1.cs and Service1.svc. All the implementation I have coded under Service1.svc.cs
Under the IService1.cs there is Service and Operation Contract, data contract (What is purpose of data contract here? can I delete it off?).
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
// TODO: Add your service operations here
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
First of all, I would like to suggest you reading the basics of WCF in a book "Learning WCF" from Michele Leroux Bustamante, if you have an option to get it - the tutorial you are linking to was too chaotic by my opinion (I was reading it some time ago too)
Question 1: The thing is, that you should define 2 projects - 1 will contain host of the service and second will contain definition/implementation of that service. See picture below:
In ServiceHost, I ussualy have only main entry point, which launches the host. In ServiceLibrary (you can choose whatever name suits you) I have the service interface and implementation. Also, please notice that in ServiceHost, I have referenced ServiceLibrary.
Question2: Simply said: DataContracts are used when you are working with your custom objects over WCF. Lets say you want to get information about "Person" from you service. You can either define for example 3 OperationContracs - first would return name (string), second one age of that person (int) and third one telephone number (int).
But this is not the way you should proceed - you should return Person object from service (in your case, you have "CompositeType"). For that, you need to mark the class with [DataContract] attribute and all the information you want to exchange with [DataMember] attribute.
Of course you dont need to have the definition of "CompositeType" in IService - you can create new class in your project, name it "CompositeType" and mark it as [DataContract].
Is it more clear?
Answer of Question 1
Yes you need to create a separate class library for your service and a separate host project.See the following
You need to create something like this. Add Reference of AngService in AngServiceHost Application.
AngServiceHost Application is WCF Application. Delete the Service1.cs and IService1.cs
Add following lines in Service1.svc in AngServiceHost
<%# ServiceHost Language="C#" Debug="true" Service="AngService.ILogin" %>
Answer of Question 2
Whatever you have coded in .svc.cs file should go in the service class library, not in the host application.
Understand that the .svc file is used for hosting. You can reference the source of the service in this .svc file. In my example the dll of AngService (the class library) is added in AngServiceHost(the host application). This dll contains the actual code. You need to do something similar to this.

WCF DataContract centralization

I have several WCF services that use the same dataContracts to interchange data between them.
Can I have a sort of Metadata Endpoint for centralizing the management of all this schemas?
When creating a new WCF service, how can i make it to load the schemas from the Metadata Endpoint (instead of redefining them) to use inside its operationContracts?
Thanks!
As I said in the comment, I'm not sure I understand your question (at least with regards to wanting a metadata endpoint), but it sounds like you want to have the ability to reuse existing data contracts in multiple different services.
The easiest way to do that is to put the data contracts in a separate assembly (class library - DLL), and then have the services reference that assembly - they don't have to be defined inside the service itself.
Here's a trivial example (code is for illustration only, not intended to actually do anything or be a complete sample):
MyDataContracts assembly
namespace MyDataContracts
{
[DataContract]
public class DataContract1
{
}
[DataContract]
public class DataContract2
{
}
}
MyService1 assembly
using MyDataContracts;
namespace MyService1
{
[ServiceContract]
public interface IMyService1
{
[OperationContract]
DataContract1 GetSomeData(string someParm);
}
}
MyService2 assembly
using MyDataContracts;
namespace MyService2
{
[ServiceContract]
public interface IMyService2
{
[OperationContract]
void SendSomeData(DataContract1 dc);
[OperationContract]
DataContract2 GetSomeOtherData(int parm);
}
}
Of course, each of the WCF service projects will need to include a reference to the MyDataContracts assembly as well.
Now whenever you create a new service, you simply add a reference to the MyDataContracts.dll and you can reuse your data contracts in it.

Extension methods in a data contract

Can we two WCF services where one service contract derives from another and have an extension method inside the derived contract. what will be the result of accessing this contract from the WCF Client. I.e. what will happen if IDServiceis accessed
E.g.
[ServiceContract]
public interface IBaseService
{
public void A();
...
}
[ServiceContract]
public interface IDService: IBaseService
{
public static void B(this IBaseService S);
....
}
You can't define static methods in an interface (nor the access modifier public which you've specified above either).
A good question - got me to a lot of head scratching.
Extension method is meaningless to WCF - and WSDL for that matter.
If you use Service Reference to generated the client, you would not see the extension method (since WSDL would not know anything about the extension method) so you cannot use it.
If you use DLL/Project reference, your code will be called locally and not through the proxy.

WCF client proxy exception - "Type cannot be added to list of known types"

I am having problems creating WCF client proxy for service code like in this example:
// data classes
[KnownType(typeof(ClassA))]
[KnownType(typeof(ClassB))]
public abstract class BaseClass : Dictionary<string, ITest>
{
}
public class ClassA : BaseClass
{
}
public class ClassB : BaseClass
{
}
public interface ITest
{
}
// service
[ServiceContract]
public interface IService1
{
[OperationContract]
BaseClass Method();
}
public class Service1 : IService1
{
public BaseClass Method()
{
...
}
}
Whenever I try to create a WCF proxy using "Add Service Reference" in VS it fails and trace log says
Type 'WcfProxyTest.ClassA' cannot be added to list of known types since another type 'WcfProxyTest.ClassB' with the same data contract name 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:ArrayOfKeyValueOfstringanyType' is already present. If there are different collections of a particular type - for example, List<Test> and Test[], they cannot both be added as known types. Consider specifying only one of these types for addition to the known types list.
I can see what the error message is saying, but is there any other way around this (other than refactoring the classes). I am dealing with a legacy system which has classes written in the same manner as in my example and rewriting them is not an option as this stuff sits in the very core of the system :S
Any ideas? Thanks!
I decided to refactor the code in such a way that I don't have to provide two KnownTypes which gets me around the problem. About 300 syntax errors later that worked. I would be interested in any other ways of doing it though...
Try adding:
[KnownType(typeof(Dictionary<string, ITest>))]

Run WCF ServiceHost with multiple contracts

Running a ServiceHost with a single contract is working fine like this:
servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.Open();
Now I'd like to add a second (3rd, 4th, ...) contract. My first guess would be to just add more endpoints like this:
servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();
But of course this does not work, since in the creation of ServiceHost I can either pass MyService1 as parameter or MyService2 - so I can add a lot of endpoints to my service, but all have to use the same contract, since I only can provide one implementation?
I got the feeling I'm missing the point, here. Sure there must be some way to provide an implementation for every endpoint-contract I add, or not?
You need to implement both services (interfaces) in the same class.
servicehost = new ServiceHost(typeof(WcfEntryPoint));
servicehost.Open();
public class WcfEntryPoint : IMyService1, IMyService2
{
#region IMyService1
#endregion
#region IMyService2
#endregion
}
FYI: I frequently use partial classes to make my host class code easier to read:
// WcfEntryPoint.IMyService1.cs
public partial class WcfEntryPoint : IMyService1
{
// IMyService1 methods
}
// WcfEntryPoint.IMyService2.cs
public partial class WcfEntryPoint : IMyService2
{
// IMyService2 methods
}
I'm currently faced with the same problem, and have decided to go with the implementation below. I'm not sure if there are any performance issues with having this many service contracts, but in my final implementation I will probably have about 10 - 15 service contracts, thus about 10-15 ServiceHosts.
I am hosting all my WCF services inside a single Windows Service.
private void PublishWcfEndpoints()
{
var mappings = new Dictionary<Type, Type>
{
{typeof (IAuthenticationService), typeof (AuthenticationService)},
{typeof(IUserService), typeof(UserService)},
{typeof(IClientService), typeof(ClientService)}
};
foreach (var type in mappings)
{
Type contractType = type.Key;
Type implementationType = type.Value;
ServiceHost serviceHost = new ServiceHost(implementationType);
ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(contractType, ServiceHelper.GetDefaultBinding(),
Properties.Settings.Default.ServiceUrl + "/" + contractType.Name);
endpoint.Behaviors.Add(new ServerSessionBehavior());
ServiceDebugBehavior serviceDebugBehaviour =
serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
serviceDebugBehaviour.IncludeExceptionDetailInFaults = true;
log.DebugFormat("Published Service endpoint: {0}", Properties.Settings.Default.ServiceUrl);
serviceHost.Open();
serviceHosts.Add(serviceHost);
}
}
Feel free to comment on this type of set up, and if there are any issues with it, especially performance-related.
This answer is a further response to the comment in the accepted answer from chilltemp.
Sam, You really should determine why you need 10-50 contracts and try to find another solution. I looked over Juval Lowy's WCF Coding Standards (found on http://www.idesign.net/) and found the following references:
3 Service Contracts
[...]
Avoid contracts with one member.
Strive to have three to five members per service contract.
Do not have more than twenty members per service contract. Twelve is probably the practical limit.
He doesn't mention a limit on contract implementations (that I can find) but I can't imagine him viewing 50 contracts on a service as anything resembling a best practice. One solution I have found that works well is to use member sharing for similar functions.
For instance, if you are using the WCF service to perform mathematics on 2 values you might have 4 members on the service side: Add(x,y), Subtract(x,y), Multiply(x,y), Divide(x,y). If you combine these into a more generic member and use an object to pass the needed data you can easily reduce your member count and increase scalability. Example: PeformCalculation(obj) where obj has x, y, and action (add, subtract, multiply, divide) properties.
Hope this helps.
I found another solution to for this issue by using a the RoutingService class. Each contract must still be hosted in it's own ServiceHost, but there can be a RoutingService sitting on top of all of them - and presenting them over an unified "endpoint". I've also written a codeproject article about it. The example code is also available on Bitbucket.
chili's answer will work if you are ok with the contracts being shared by the service. If you want them to be separated try this:
host1 = new ServiceHost(typeof(MyService1));
host2 = new ServiceHost(typeof(MyService2));
host1.Open();
host2.Open();
public class MyService1 : IMyService1
{
#region IMyService1
#endregion
}
public class MyService2 : IMyService2
{
#region IMyService2
#endregion
}
Edit: As Matt posted, this would require multiple endpoints for each service/contract
No-one documented enpoints. Whe used more than one (as a group, from common url, for example http) must use the same binding instance (not more), i.e.
Your sample:
servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();
should be only one new Binding(), I tested over http.
servicehost = new ServiceHost(typeof(MyService1));
BasicHttpBinding binding = new BasicHttpBinding();
servicehost.AddServiceEndpoint(typeof(IMyService1),binding , "http://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), binding, "http://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();
I agree totally with partial class implementing few contracts in few files.
What about splitting it up with a base address and multiple services/contracts below it?
I am not behind a developmachine right now but something like:
http://myserver/myservices/serviceA
http://myserver/myservices/serviceB
http://myserver/myservices/serviceC
Each service implementing its own ServiceContract.
You can change
public class WcfEntryPoint : IMyService1, IMyService2
to
public partial class WcfEntryPoint : IMyService1
public partial class WcfEntryPoint : IMyService2
Example
Did I miss something, or is the simplest solution not mentioned here? The simplest solution is this: Don't use multiple interfaces for the Web Service.
But that doesn't mean you can still have your interfaces separated. This is why we have Interface inheritance.
[ServiceContract]
public interface IMetaSomeObjectService : ISomeObjectService1, ISomeObjectService2
{
}
The Meta interface inherits from all the other interfaces.
[ServiceContract]
public interface ISomeOjectService1
{
[OperationContract]
List<SomeOject> GetSomeObjects();
}
[ServiceContract]
public interface ISomeOjectService2
{
[OperationContract]
void DoSomethingElse();
}
Then the service just has the Meta interface.
public class SomeObjectService : IMetaSomeObjectService
{
public List<SomeOject> GetSomeObjects()
{
// code here
}
public void DoSomethingElse()
{
// code here
}
}