I am exposing a WCF service on SharePoint 2010 using a Service Factory class and cannot completly get rid of the tempuri.org namespace in the generated WSDL.
Here is what I do:
The svc file in the ISAPI folder
<%@ServiceHost
Language="C#"
Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressBasicHttpBindingServiceHostFactory, Microsoft.SharePoint.Client.ServerRuntime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
Service="MyService, [...]"
%>
The service contract
using System.ServiceModel;
namespace MyService
{
[ServiceContract(Namespace="http://myname.开发者_StackOverflowcom")]
interface IMyService
{
[OperationContract]
string GetSomeDefinition();
}
}
The service implementation
using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using Microsoft.SharePoint.Client.Services;
namespace MyService
{
[ServiceBehavior(Namespace = "http://myname.com")]
[BasicHttpBindingServiceMetadataExchangeEndpointAttribute]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
class MyService : IMyService
{
public string GetSomeDefinition()
{
// do some stuff...
return result;
}
}
}
The WSDL
<wsdl:definitions name="MyService" targetNamespace="http://myname.com" [...]>
<wsdl:import namespace="http://tempuri.org/" location="http://localhost/_vti_bin/myservice.svc/mex?wsdl=wsdl0" />
[...]
</wsdl:definitions>
The problem now is that the WSDL is split up in two. One with the correct new namespace http://myname.com and one with the default namespace http://tempuri.org. Normally you get rid of it by using a bindingNamespace attribute on the endpoint configuration. But because I am using a Service Factory I cannot do so. Trying to define a service endpoint in web.config fails with the following error: A binding instance has already been associated to listen http://localhost/...
Web.config chunk
<system.serviceModel>
<services>
<service name="MyService.MyService">
<endpoint address="http://localhost/_vti_bin/myservice.svc" binding="basicHttpBinding" contract="MyService.IMyService" bindingNamespace="http://myname.com" />
</service>
</services>
</system.serviceModel>
2010-10-07 Update: I have tried to derive the MultipleBaseAddressBasicHttpBindingServiceHostFactory and add the endpoint binding namespace when the ServiceHost is created. This does not succeed because the endpoint collection is empty at that point of time.
In general, there are three places you'll need to explicitly set the namespace to get rid of the tempuri.org default:
- ServiceContract attribute (on contract)
- ServiceBehavior attribute (on implementation)
bindingNamespace on relevant service <endpoint /> elements in the configuration file.
--larsw
I faced the exactly same problem and managed to resolve it thanks to this blogpost from Cameron Verhelst : http://cameron-verhelst.be/blog/2014/10/19/hosting-a-wcf-service-in-sharepoint-with-a-spcontext/ (Many thanks to him!)
The consumer of my service did not want the WSDL to be multipart so i had to correctly configure my service namespaces.
The key is to create his own service host and service host factory to modify the automatically created endpoints by the service host, and to reference it in the svc file.
Here is mine:
CustomMultipleBaseAddressBasicHttpBindingServiceHostFactory.cs
using System;
using System.ServiceModel;
using Microsoft.SharePoint.Client.Services;
public class CustomMultipleBaseAddressBasicHttpBindingServiceHostFactory : MultipleBaseAddressBasicHttpBindingServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new CustomMultipleBaseAddressBasicHttpBindingServiceHost(serviceType, baseAddresses);
}
}
CustomMultipleBaseAddressBasicHttpBindingServiceHostFactory.cs
using System;
using System.Linq;
using System.ServiceModel.Description;
using Microsoft.SharePoint.Client.Services;
public class CustomMultipleBaseAddressBasicHttpBindingServiceHost : MultipleBaseAddressBasicHttpBindingServiceHost
{
public CustomMultipleBaseAddressBasicHttpBindingServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
}
protected override void OnOpening()
{
base.OnOpening();
string targetNamespace = ImplementedContracts.First().Value.Namespace;
foreach (ServiceEndpoint endpoint in Description.Endpoints)
{
endpoint.Binding.Namespace = targetNamespace;
}
}
}
This service host allows to force the target namespace of the endpoint to be the same as the specified contract.
精彩评论