简体   繁体   中英

Host WCF service using NetTcp binding and configuration in code hosted in IIS

UPDATE The below problems might be due to net.tcp not useable on IIS express. Good answers (preferably examples) are still very welcome.

I'm trying to host a WCF service in a IIS without using the web.config file ( msdn documentation on the basics on that ). I want to use sessions and the NetTcpBinding, but I seem to run into problems getting the metadata to work. I've tried quite a few things. Here is my current code:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class InternalInternalESensService : IInternalESensService
{
    public static void Configure(System.ServiceModel.ServiceConfiguration config)
    {
        NetTcpBinding wsBind = new NetTcpBinding(SecurityMode.Transport);
        config.AddServiceEndpoint(typeof(IInternalESensService), wsBind, "net.tcp://localhost:42893/ESens/ESensInternalService.svc");
        // config.AddServiceEndpoint(typeof(IInternalESensService), basic, "basic");
        // config.Description.Endpoints.Add(new ServiceMetadataEndpoint(MetadataExchangeBindings.CreateMexHttpBinding(), new EndpointAddress(config.BaseAddresses[0])));
        config.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true, HttpGetBinding = MetadataExchangeBindings.CreateMexHttpBinding()});
        //config.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
        config.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });
    }

    public string Test(string input)
    {
        return "Hello " + input;
    }

The uncommented code shows some of my desperate tries that didn't work. It implements the interface:

[ServiceContract(Name = "ESensInternalService", Namespace = Constants.WebserviceNameSpace + "/ESensService", SessionMode = SessionMode.Required)]
public interface IInternalESensService
{
    [OperationContract]
    string Test(string input);

There are some more methods in the interface and class implementation, but they are not relevant for the question/problem.

To host it in IIS I use a svc file. The content looks something like this:

<%@ ServiceHost Language="C#" Debug="true" Service="Esens.Integration.WebService.InternalInternalESensService" %>

I've gotten a lot of different exceptions depending on what I did.

I found the answer myself. First of all I found that you cannot use net.tcp binding in IIS express . Also it needs to be (normal) enabled on the IIS .

Then it can be configured the following way:

    public static void Configure(System.ServiceModel.ServiceConfiguration config)
    {
        Uri netTcpAddress = config.BaseAddresses.FirstOrDefault(x => x.Scheme == Uri.UriSchemeNetTcp);
        if (netTcpAddress == null)
        {
            throw new InvalidOperationException("No base address matches the endpoint binding net.tcp");
        }

        Uri metaAddress = config.BaseAddresses.FirstOrDefault(x => x.Scheme == Uri.UriSchemeHttp);
        if (metaAddress == null)
        {
            throw new InvalidOperationException("No base address matches the endpoint binding http used for metadata");
        }

        config.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });

        NetTcpBinding wsBind = new NetTcpBinding(SecurityMode.Transport);
        ServiceEndpoint endpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IInternalESensService)), wsBind, new EndpointAddress(netTcpAddress));
        config.AddServiceEndpoint(endpoint);

        Binding mexBinding = MetadataExchangeBindings.CreateMexHttpBinding();
        ContractDescription contractDescription = ContractDescription.GetContract(typeof(IMetadataExchange));
        contractDescription.Behaviors.Add(new ServiceMetadataContractBehavior(true));
        ServiceEndpoint mexEndpoint = new ServiceEndpoint(contractDescription, mexBinding, new EndpointAddress(metaAddress));
        mexEndpoint.Name = "mexTest";
        config.AddServiceEndpoint(mexEndpoint);

        config.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });
    }

It seems there isn't much documentation on this. I had to look at some of Microsoft's source code in order to find the special part about the meta data bindings behaviour.

If you want to do the same in web.config it would look something like this:

   <service behaviorConfiguration="StandardBehaviour" name="Mercell.Esens.Integration.WebService.InternalInternalESensService">
    <endpoint binding="netTcpBinding" 
     name="test" contract="Mercell.Esens.Integration.WebService.IInternalESensService" />
    <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
     name="Metadata" contract="IMetadataExchange" />
   </service>

With the behaviour:

<behavior name="StandardBehaviour">
 <serviceMetadata httpGetEnabled="true" />
</behavior>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM