Search code examples
c#asp.netwcfwebformsiis-8

Deploying a WebForms with WCF inside to IIS 8, doesn't start WCF


I have a VisualStudio solution with WebForms (called EDWMS) & WCF projects (called EDWMS.SYNC) inside. WCF is added as Service Reference to WebForms project by using Discover function. When running it locally in "release" mode, the WCF gets called correctly from app & works fine (though I need to run VS as Administrator for it to work). But when publishing the webforms project to IIS 8 both via Web Deploy Package & FTP Publish, WCF doesn't seem to get published.

I tried to create WCF as a separate Site in IIS, then setting WCF project as "Startup project" in VS & publishing it to new site slot, also adding it's port to the site bindings. In this case I can browse .svc file & see that it's set up You have created a service. To test this service, you will need.... But when I call it from WebForms app it still fails to respond with this error:

There was no endpoint listening at http://localhost:8733/Design_Time_Addresses/ED_WMS.SYNC/Sync/ that could accept the message. This is often caused by an incorrect address or SOAP action.
The remote server returned an error: (404) Not Found. 

This is code from WebForms app which calls WCF:

var client = new SyncClient("BasicHttpBinding_ISync");
client.InnerChannel.OperationTimeout = new TimeSpan(2, 00, 0);
var message = string.Empty;
try
{
    var syncResult = new SyncResult();
    syncResult = client.GetInventory(1, 2, 3);
    message += $"Sync Result<hr/>Added: {syncResult.ItemsAdded}<br/>Updated: {syncResult.ItemsUpdated}<br/>Duration: {syncResult.Duration}";
    ((ICommunicationObject)client).Close();
}
catch (System.Exception ex)
{
    (client as ICommunicationObject)?.Abort();
    message += $"Error<hr/>{ex?.Message ?? "null"}<hr/>{ex?.InnerException?.Message ?? "null"}";
}
inventoryItemsLbl.Text = message;

This is my WebForms Web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>...</connectionStrings>
  <appSettings>...</appSettings>
  <system.web>
    <authentication mode="Forms">
      <forms loginUrl="Login.aspx" timeout="2880" />
    </authentication>
    <compilation targetFramework="4.5.2" />
    <httpRuntime targetFramework="4.5.2" executionTimeout="900" />
    <pages>...</pages>
  </system.web>
  <system.webServer><modules>...</modules></system.webServer>
  <runtime>...</runtime>
  <system.codedom><compilers>...</compilers></system.codedom>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
  <system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true">
    </serviceHostingEnvironment>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_ISync" />
      </basicHttpBinding>
    </bindings>
    <client>
<endpoint address="http://localhost:8733/Design_Time_Addresses/ED_WMS.SYNC/Sync/" 
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ISync" 
contract="ServiceReferenceWMS.ISync" name="BasicHttpBinding_ISync" />
    </client>
  </system.serviceModel>
</configuration>

This is my WCF App.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>...</configSections>
  <entityFramework>...</entityFramework>
  <runtime>...</runtime>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
  </startup>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="MobilityBeanSoapBinding" closeTimeout="02:00:00" openTimeout="02:00:00"
            receiveTimeout="02:00:00" sendTimeout="02:00:00" maxReceivedMessageSize="100000000"
            maxBufferSize="100000000" maxBufferPoolSize="100000000">
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://warehouse:8080/wmwebservice_ejb/MobilityBean" binding="basicHttpBinding" bindingConfiguration="MobilityBeanSoapBinding" contract="EdWmsReference.MobilityBean" name="MobilityRemotePort" />
    </client>
    <services>
      <service name="ED_WMS.SYNC.Sync" behaviorConfiguration="MyServiceTypeBehaviors">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8733/Design_Time_Addresses/ED_WMS.SYNC/Sync/" />
          </baseAddresses>
        </host>
        <endpoint name="basicHttpEndpoint" address="" binding="basicHttpBinding" contract="ED_WMS.SYNC.ISync" bindingConfiguration="MobilityBeanSoapBinding"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyServiceTypeBehaviors" >
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Solution

  • When you move from DEV -> Production( when the WCF app is now hosted in IIS), the design time URL changes, you would need to set the correct designTime URL in your webforms app now.

    A few options are available, but they all point to changing the URI that is associated with the service

    client.Endpoint.Address = new EndpointAddress(Server.IsLiveServer() ?
        @"LiveUrl" : @"TestURl"); 
    

    Where the TestURI is the designTime URL, and the LiveURL is the production URL. The IsLiveServer is just a boolean to check if you are in dev or production.

    The other way you can go about it is to just to create a Realease vs a Debug webconfig, the release will have the URL of the deployed App, then set the client Endpoint using an appSetting or something similar

    The third option would require using the IIS Administration DLL to query the hosted website and findout the URL of the WCF service and use that in your webforms.