Search code examples
wcfwcf-data-services

How to get data via a DTO from a WCF Service when called from a test console


I am new to .net and WCF. I am trying to build a WCF Service prototype that will get data from a database table and based on the data will send emails using a SMTP exchange.
For the prototype I created an Interface and Service and have hosted the WCF Service in IIS 5.1. For my test console I have referenced this Service. Now I am getting error messages from the console when I run my app.

This is what the code looks like:

namespace MyWcfConsoleApp
{
class Program
{
    static void Main(string[] args)
    {
        // Create a proxy object and connect to the service
        EmailServiceClient proxy = new EmailServiceClient();

        // Test the operations in the service
        Console.WriteLine("Test1");
        //BulkEmailDTOList EmailInfo = proxy.GetBulkEmailInfo(1);

        EmailService.IEmailService EmailInfo = ServiceLocator.Resolve<IEmailService>();
        BulkEmailDTOList result = new BulkEmailDTOList();
        result = EmailInfo.GetBulkEmailInfo(1);

This is what I have in my App.Config in the console app:

    <configuration>
    <configSections>
    <section name="Dependency" type="WW.EnterpriseLibrary.Dependency.ServiceLocatorConfigurationSection, WW.EnterpriseLibrary"/>
  </configSections>
  <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IEmailService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
                  <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/>
                    <message clientCredentialType="UserName" algorithmSuite="Default"/>
                  </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
        <endpoint address="http://localhost/WCFEmailService/BulkEmailService.svc/EmailService" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IEmailService" contract="EmailService.IEmailService" name="BasicHttpBinding_IEmailService"/>
        </client>
    </system.serviceModel>
  <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
  <Dependency>
    <dependencies>
      <add name="IEmailService" type="C:\BulkEmailPrototype\TestWcfEmailService\TestWcfEmailServiceLibrary.WW.Common.Service.Impl.EmailService, C:\BulkEmailPrototype\TestWcfEmailService\TestWcfEmailServiceLibrary.WW.Common.Service.Impl" />
    </dependencies>
  </Dependency>
</configuration>

Please let me know what am I doing wrong. Is there any simple way to call the DTO to retrieve my data? As I said I am new to this and so having tough time..

Here is my Implementation:

using BulkEmailDac = WW.Common.DataAccess.Impl.BulkEmailDac;

namespace WW.Common.Service.Impl
{
public class EmailService : IEmailService
{

    private BulkEmailDac emailDac;
    ErrorMsg err_msg = new ErrorMsg();


    public EmailService()
    {
        emailDac = new BulkEmailDac();
    }

                 public BulkEmailDTOList GetBulkEmailInfo(int recordLimit)
         {

             try
             {

                 return emailDac.GetBulkEmailInfo(recordLimit);
             }
             catch (Exception ex)
             {
                 if (ex is FaultException<OperationFault>)
                 {
                     throw;
                 }
                 else
                 {

                     //LOG AND THROW AN UNKNOWN EXCEPTION
                     ApplicationLog.WriteError(DateTime.Now.ToString() + "|"
                                               + "GetBulkEmailInfo" + "|"
                                               + ex.Message + "|"
                                               + ex.StackTrace);
                     throw new FaultException<OperationFault>(new OperationFault(ex.Message, ErrorMessages.Unknown_Error_Code));
                 }
             }

And this is the contract:

namespace WW.Common.Service.Contract
{
   [ServiceContract]
    public interface IEmailService
    {

     [OperationContract]
     double Add(double n1, double n2);

     [OperationContract]
     double Subtract(double n1, double n2);

     [OperationContract]
     double Multiply(double n1, double n2);

     [OperationContract]
     double Divide(double n1, double n2);

     [OperationContract]
     [FaultContractAttribute(typeof(OperationFault))]
     BulkEmailDTOList GetBulkEmailInfo(int recordLimit);

     [OperationContract]
     string Abc(string s1);

    }

This is the Web.Config file in my Service:

 <configuration>
  <configSections>
    <section name="Dependency" type="WW.EnterpriseLibrary.Dependency.ServiceLocatorConfigurationSection, WW.EnterpriseLibrary"/>
  </configSections>
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel.MessageLogging" switchValue="Warning, ActivityTracing">
        <listeners>
          <add type="System.Diagnostics.DefaultTraceListener" name="Default">
            <filter type="" />
          </add>
          <add name="ServiceModelMessageLoggingListener">
            <filter type="" />
          </add>
        </listeners>
      </source>
      <source name="System.ServiceModel" switchValue="Warning,ActivityTracing"
        propagateActivity="true">
        <listeners>
          <add type="System.Diagnostics.DefaultTraceListener" name="Default">
            <filter type="" />
          </add>
          <add name="ServiceModelTraceListener">
            <filter type="" />
          </add>
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add initializeData="c:\bulkemailprototype\testwcfemailservice\wcfemailservice\web_messages.svclog"
        type="System.Diagnostics.XmlWriterTraceListener, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        name="ServiceModelMessageLoggingListener" traceOutputOptions="Timestamp">
        <filter type="" />
      </add>
      <add initializeData="c:\bulkemailprototype\testwcfemailservice\wcfemailservice\web_tracelog.svclog"
        type="System.Diagnostics.XmlWriterTraceListener, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        name="ServiceModelTraceListener" traceOutputOptions="Timestamp">
        <filter type="" />
      </add>
    </sharedListeners>
  </system.diagnostics>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <connectionStrings>
    <add name="WWDbConnect"
         connectionString="Data Source=(labdev0320);USER ID = wwsa; Password = trex777sa;Max Pool Size=200;"
         providerName="System.Data.OracleClient" />
  </connectionStrings>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBindingWithNoSecurity" maxBufferPoolSize="524288" maxReceivedMessageSize="500000">
          <security mode="Transport">
            <transport clientCredentialType="Certificate" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client/>
    <services>
        <service name="WW.Common.Service.Impl.EmailService" behaviorConfiguration="EmailService">
          <host>
            <baseAddresses>
              <add baseAddress="http://localhost:8270/Design_Time_Addresses/TestWcfEmailServiceLibrary/EmailService/"   />
            </baseAddresses>
          </host>
          <endpoint address="EmailService" binding="basicHttpBinding" contract="WW.Common.Service.Contract.IEmailService" />
          <endpoint address="mex" binding="basicHttpBinding"
                    name="mexEndpoint" contract="IMetadataExchange" />
        </service>
      </services>
      <behaviors>
      <serviceBehaviors>
          <behavior name="EmailService">
            <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
            <serviceMetadata httpGetEnabled="true" />
            <serviceSecurityAudit auditLogLocation="Application"
               suppressAuditFailure="true"
               serviceAuthorizationAuditLevel="Success"
               messageAuthenticationAuditLevel="Success" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <diagnostics>
      <messageLogging logEntireMessage="true" logMalformedMessages="false"
        logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true"
        maxMessagesToLog="3000" />
    </diagnostics>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
  <Dependency>
    <dependencies>
      <add name="IEmailService" type="WW.Common.Service.Impl.EmailService, WW.Common.Service.Impl" />
    </dependencies>
  </Dependency>
</configuration>

Solution

  • First of all, your endpoint looks incorrect.

    In the web config for the service, what is the value for relativeAddress in <serviceActivations>. That is the true path you should be hitting from your client application.

    Also, a quick and dirty way of testing WCF services is by using the WCFTestClient located in VISUAL_STUDIO_INSTALL_PATH\Common7\IDE . Once you know your true endpoint you can test it from this app.