Search code examples
c#kestrel-http-serverkestrelcorewcf

How do I prevent CoreWCF base address from being overriden by Kestrel?


I am initializing a CoreWCF service using Kestrel as a host. The code goes as follows:

var builder = WebApplication.CreateBuilder();
builder.Services.AddServiceModelServices();
builder.WebHost.UseNetTcp(System.Net.IPAddress.Parse(address), int.Parse(port));
builder.WebHost.UseUrls(string.Format("net.tcp://{0}:{1}", address, port));
builder.Logging.AddConsole().AddDebug();

service = builder.Build();

service.UseServiceModel(builder =>
{
    builder.AddService<ServiceImpl>();
    builder.AddServiceEndpoint<ServiceImpl, IService>(binding, endpoint);
});

Task startupTask = service.StartAsync();
startupTask.Wait();

The binding is a NetTcpBinding. The address is "127.0.0.1" and the port is "8001". endpoint is "/endpoint". The intention is to have a service that listens at "net.tcp://127.0.0.1:8001/endpoint".

Note: this is supposed to be a quick-and-dirty prototype designed for understanding how WCF services can be migrated to CoreWCF & Kestrel as a host.

During start up, the console output reads:

warn: Microsoft.AspNetCore.Server.Kestrel[0]
      Overriding address(es) 'net.tcp://127.0.0.1:8001'. Binding to > endpoints defined via IConfiguration and/or UseKestrel() instead.
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://127.0.0.1:8001

There is no configuration file in this application, no json, etc. The code presented contains the configuration. Why is the URI I specified via UseUrls being overriden and how do I fix it?


Solution

  • I am also going through the same migration exercise, trying to get some old WCF .NET Framework services running on .NET 7 with CoreWCF.

    It seems that using either .UseKestrel() or .UseNetTcp() causes the override. You can let this happen and then specify a fully qualified address later when you call .AddServiceEndpoint() for the NetTcp endpoint. I have an HTTP endpoint for publishing the metadata which the WCF Test Client tool can pick up.

    var builder = WebApplication.CreateBuilder();
    
    WebSettings webSettings = new WebSettings();
    
    builder.Configuration.GetSection("WebSettings").Bind(webSettings);
    
    NetTcpBinding netTcpBinding = new NetTcpBinding();
    netTcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
    netTcpBinding.Security.Message.ClientCredentialType = MessageCredentialType.None;
    netTcpBinding.Security.Mode = SecurityMode.None;
    
    builder.WebHost
        .UseKestrel(options =>
        {
            options.ListenAnyIP(webSettings.HttpPort);
        })
        .UseNetTcp(webSettings.NetTcpPort);
    
    builder
        .Services.AddServiceModelServices()
        .AddServiceModelMetadata()
        .AddSingleton<IServiceBehavior, UseRequestHeadersForMetadataAddressBehavior>();
    
    // The fully qualified NetTcp endpoint
    string netTcpEndpoint = $"net.tcp://{webSettings.BaseAddressHost}:{webSettings.NetTcpPort}/nettcp";
    
    var app = builder
        .Build()
        .UseServiceModel(sb =>
        {
            sb.AddService<EmailWebService>((serviceOptions) =>
            {
                serviceOptions.BaseAddresses.Add(new Uri($"http://{webSettings.BaseAddressHost}/EmailWebService"));
            })
            .AddServiceEndpoint<EmailWebService, IDataFeedEmailCollectionService>(new BasicHttpBinding(), "/basicHttp")
            .AddServiceEndpoint<EmailWebService, IDataFeedEmailCollectionService>(netTcpBinding, netTcpEndpoint);
        });
    
    var serviceMetadataBehavior = app.Services.GetRequiredService<CoreWCF.Description.ServiceMetadataBehavior>();
    serviceMetadataBehavior.HttpGetEnabled = serviceMetadataBehavior.HttpsGetEnabled = true;
    
    app.Run();
    

    Sample code

    Despite the console output saying Now listening on: http://0.0.0.0:9000 the endpoint is up and running on the fully qualified endpoint as shown by the config output of the test tool.

    Debug output