question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Duplicate registration exception when using different ports

See original GitHub issue

I’m trying to migrate an existing .NET Framework application to using CoreWCF.

There are multiple services in the application, with each service binding to a different port. This works fine using the original WCF libraries (using a ServiceHost instead of ASP.NET Core), but using CoreWCF I run into issues.

Without using UseNetTcp, adding multiple TCP service endpoints on different ports works fine. However, these ports are not actually opened.

With UseNetTcp, adding one TCP service endpoint for one service works fine, but as soon as I try to add another service with its own TCP service endpoint (on a different port), I get an exception saying a registration already exists for URI 'net.tcp://localhost:8051/MyService1/svc'.

Creating the web host builder:

IWebHost webHost = WebHost.CreateDefaultBuilder( ).UseStartup< Startup >( ).UseNetTcp( ).Build( );
webHost.Run( );

A simplified version of the Startup class:

public class Startup
{
    public void ConfigureServices(
        IServiceCollection services )
    {
        services.AddServiceModelServices( ).AddServiceModelMetadata( );
    }

    public void Configure(
        IApplicationBuilder app,
        IHostingEnvironment env )
    {
        app.UseServiceModel(
            builder =>
            {
                foreach ( EServiceType serviceType in new[ ]
                                                        {
                                                            EServiceType.One,
                                                            EServiceType.Two,
                                                        } )
                {
                    string hostName = Properties.Host;
                    string servicePath = Properties.UriPath( serviceType );
                    int tcpPort = Properties.TcpPort( serviceType );
                    SecurityMode = Properties.TcpSecurityMode( serviceType );
                    int maxResponseSize = Properties.MaxResponseSize( serviceType ) );

                    Type implementation = Type.GetType( Properties.ServiceImplementation( serviceType ), false );
                    Type contractType = Type.GetType( Properties.ServiceContract( serviceType ), false );

                    Uri tcpAddress = new Uri( $"net.tcp://{hostName}:{tcpPort}/{servicePath}/svc" );

                    builder.AddService( implementation );

                    builder.AddServiceEndpoint(
                        implementation,
                        contractType,
                        new NetTcpBinding( tcpSecurityMode )
                        {
                            MaxBufferPoolSize = maxResponseSize,
                            MaxBufferSize = maxResponseSize,
                            MaxReceivedMessageSize = maxResponseSize,
                            ReaderQuotas = new XmlDictionaryReaderQuotas
                                           {
                                               MaxStringContentLength = maxResponseSize,
                                               MaxBytesPerRead = maxResponseSize,
                                               MaxArrayLength = maxResponseSize,
                                               MaxDepth = 64
                                           },
                            OpenTimeout = Properties.OpenTimeout,
                            CloseTimeout = Properties.CloseTimeout,
                            SendTimeout = Properties.SendTimeout,
                            ReceiveTimeout = Properties.ReceiveTimeout
                        },
                        tcpAddress,
                        tcpAddress );
                        } );
    }
}

The exception stacktrace:

System.InvalidOperationException: A registration already exists for URI 'net.tcp://localhost:8051/MyService/svc'.
   at CoreWCF.Channels.UriPrefixTable`1.RegisterUri(Uri uri, HostNameComparisonMode hostNameComparisonMode, TItem item)
   at CoreWCF.Channels.Framing.NetMessageFramingConnectionHandler.BuildAddressTable(IServiceProvider services)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at System.EventHandler.Invoke(Object sender, EventArgs e)
   at CoreWCF.Channels.CommunicationObject.OnOpened()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at CoreWCF.Configuration.WrappingIServer.<StartAsync>d__9`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.<StartAsync>d__26.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.<RunAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.<RunAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host)

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
mconnewcommented, Jul 14, 2022

For now the fastest path to a solution is to run multiple ASP.NET Core instances in the same app, one per port. This is similar to running a separate ServiceHost instance per port. I don’t know how well that will interact with UseWindowsService though. You might be able to have just one Host instance be the one that manages it being a Windows Service. I don’t know anything about that feature or how it interacts with Windows, but I presume it handles shutting down of the service gracefully when the service is stopped. You could use the IApplicationLifetime hook of the “primary” service to then trigger cleanly shutting down the others.

0reactions
mconnewcommented, Mar 20, 2023

Each service endpoint needs a unique url. When you connect to net.tcp://localhost:8068/mrs, it doesn’t know whether you are connecting to the endpoint for ICalculate or ICalculate2 as they’ve both been registered for the same url. Under the hood, it’s looking up the EndpointDispatcher in a filter table, and it does this by using the endpoint url the client sends on connection. It found two matching endpoints and has no info to pick one over the other.
If you want ICalculate and ICalculate2 to appear at the same endpoint address, you can create a new interface with no methods which derives from both of them.

[ServiceContract]
public interface ICalc : ICalculate, ICalculate2
{
}

Then have a single AddServiceEndpoint call with this new interface at a single address. On the client side you can use just ICalculate or just ICalculate2 and the service will look like it only implements that one interface.

Otherwise, use mrs and mrs2 as the url’s for the 2 endpoints so they are unique.

Read more comments on GitHub >

github_iconTop Results From Across the Web

"Duplicate value: http" error when it is declared in service. ...
I want to declare other web port, instead of 8080, because I am not using it. Basically I would like to redefine the...
Read more >
Why and how to fix? IIS Express "The specified port is in use"
Try switching to port other than 10360 and higher than 1024. Stop the application that is using port 10360. I can fix it...
Read more >
Windows client firewall and port settings - Configuration ...
Select Windows Firewall and port settings for clients in Configuration Manager.
Read more >
K17333: Overview of port lockdown behavior (12.x - 17.x)
A video explaining how to monitor login attempts is available. Port lockdown exceptions. TCP mirroring ports: The BIG-IP system maintains a ...
Read more >
Exemptions & Exclusions: Vehicles, Vessels, Aircraft - CDTFA
Exemptions & Exclusions: Vehicles, Vessels, Aircraft – Frequently Asked Questions (FAQs). How do I apply for a CDTFA-111, Certificate of Use Tax Clearance?...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found