Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you replace the naming convention for ServiceContract and OperationContract?

I have the following code:

[ServiceContract(Name = "Save{0}")]
public ISave<T> where T : BusinessObject
{
    [OperationContract(Name = "Save")]
    void Save(T obj);
}

public class SaveCustomer : ISave<Customer>
{
    public void Save(Customer obj) { ... }
}

The problem I have is that my WCF app using IIS/WAS does not like the name I gave. It doesn't automatically fill it in. I saw this stackoverflow question, which has answers as to why the names don't automatically format. Instead of waiting for Microsoft to allow for formatted names, I was seeing if I could replace the functionality that gets the name with my own.

I'm just unsure of which class I need to extend (ServiceHost, ServiceHostFactory, DataContractSerializer, etc.), or even what method I have to override to get a more friendly name. Also, since I don't even know what class I have to create, I have no idea where I could tell my app to use it (Global.asax member? svc file? attribute?).

like image 576
michael Avatar asked Mar 07 '14 15:03

michael


1 Answers

The answer seems to be that this is not really needed. It appears that service names are created by convention. If you change your code accordingly:

[ServiceContract] // No use of the 'Name' property
public ISave<T> where T : BusinessObject
{
    [OperationContract(Name="Save")]
    void Save(T obj);
}

public class SaveCustomer : ISave<Customer>
{
    public void Save(Customer obj) { /* Do stuff here */ }
}

then the resulting configuration should be similar to the following in the web.config file (assuming a basicHttpBinding):

<service name="SaveCustomer">
    <endpoint
        address="http://localhost:8001/SaveCustomer/"
        binding="basicHttpBinding"
        contract="ISave`1[[FullyQualifiedNamespaceTo.Customer, AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=....]]"
    />
</service>

I found this here in the comments to the accepted answer. Obviously, you need to provide your own Assembly Name, Version, Culture, and PublicKeyToken. If you don't have a PublicKeyToken, I believe you can leave it off.

So, it appears that by declaring the ServiceContractAttribute on your ISave<T> interface, then implementing that interface in a class called SaveCustomer results in a service named SaveCustomer (which is what I believe you were after). Though you may have to fiddle with the syntax used for generic types when specified in web.config files.

So, if you had another service class, e.g.:

public class SaveOrder : ISave<Order>
{
    public void Save(Order obj) { /* Do stuff here */ }
}

then you should end up with another service endpoint configuration:

<service name="SaveOrder">
    <endpoint
        address="http://localhost:8001/SaveOrder/"
        binding="basicHttpBinding"
        contract="ISave`1[[FullyQualifiedNamespaceTo.Order, AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=....]]"
    />
</service>

HTH.

like image 68
fourpastmidnight Avatar answered Nov 15 '22 00:11

fourpastmidnight