Search code examples
wcfvisual-studio-2010asp.net-mvc-2wsdl

WCF, MVC2, obtaining access to auto generated WSDL and working through default endpoint not found issues


I’m trying to run a very basic web service on the same IIS7 website that runs a MVC2 application. This is presenting a couple of different issues, and I believe it has to do with my system.serviceModel, but obviously I don’t know for sure (or I would fix it). On the server side I can run my service just fine, the help operation works like a charm. I can execute the default WCF operation GetData and supply a value through the FireFox address bar.

http://localhost/services/service1/getdata?value=3 (example)

The first problem I’m having is that when I navigate to the base service URI it will display the message below. While this isn’t the end of the world because I can still execute code by manipulating the address; I do expect something else to be displayed. I expect the standard new web service message explaining that by appending “?wsdl” to the address you will receive the auto generated WSDL. I cannot access my auto generated WSDL.

“Endpoint not found. Please see the service help page for constructing valid requests to the service.”

Problem number two is in regard to client applications connecting to my web service. I created a console application in separate Visual Studio solution and added a web service reference to Service1. In the Visual Studio tool I can see and use the two methods that exist in my service, but when I run the code I get the following exception.

InvalidOperationException Could not find default endpoint element that references contract 'ServiceReference1.IService1' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.

Before I post my code (I’m sure readers are tired of reading about my struggles) I do want to mention that I’ve been able to run a WCF Service Library and Console application in the same solution flawlessly. There seems to be very few resources explaining WCF, WCF configuration, and working with MVC. I’ve read through several articles and either they were out-of-date or they were so simplistic they were nearly useless (e.g. click button receive web service named “Service1”).

To summarize; why am I not able to access the auto generated WSDL and how can I successfully connect my client and use the web service? Now the best part; the code.

Global.asax

    //Services section
    routes.Add(new ServiceRoute("services/service1", new WebServiceHostFactory(), typeof(Service1)));

Web.Config

  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
      <standardEndpoints>
        <webHttpEndpoint>
          <standardEndpoint name="DefaultEndpoint" helpEnabled="true" automaticFormatSelectionEnabled="true" />
        </webHttpEndpoint>
        <mexEndpoint />
    </standardEndpoints>
    <services>
      <service name="Project.Services.Service1" behaviorConfiguration="MetadataBehavior">
        <!-- Service Endpoints -->
        <!-- Unless fully qualified, address is relative to base address supplied above -->
        <endpoint endpointConfiguration="DefaultEndpoint" kind="webHttpEndpoint" binding="webHttpBinding" contract="Project.Services.IService1" />
        <!-- Metadata Endpoints -->
        <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
        <!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MetadataBehavior">
          <!-- To avoid disclosing metadata information, 
          set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="false" /> <!-- httpGetEnabled="true" does not solve the problem either -->
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="True"  />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

IService1

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [WebInvoke(Method = "GET")]
    string GetData(int value);

    [OperationContract]
    CompositeType GetDataUsingDataContract(CompositeType composite);

    // TODO: Add your service operations here
}

Service1

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{

    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }

    public CompositeType GetDataUsingDataContract(CompositeType composite)
    {
        if (composite == null)
        {
            throw new ArgumentNullException("composite");
        }
        if (composite.BoolValue)
        {
            composite.StringValue += "Suffix";
        }
        return composite;
    }
}

Client Program

class Program
{
    static void Main(string[] args) {
        Service1Client client = new Service1Client();
        client.GetData(2);
    }
}

Solution

  • Thanks for the help! The problem was inside of my Global.asax.cs.

    Original:

    routes.Add(new ServiceRoute("services/service1", new WebServiceHostFactory(), typeof(Service1)));
    

    New:

    routes.Add(new ServiceRoute("services/service1", new ServiceHostFactory(), typeof(Service1)));
    

    The difference was chaing the host factory from "WebServiceHostFactory" to "ServiceHostFactory".

    The second part of my question regarding client connections is because configuration settings are not being generated. I have to manually type them for each client. Yikes!

    To avoid manually typing client configuration I had to change my endpoint

    Original

    <endpoint endpointConfiguration="DefaultEndpoint" kind="webHttpEndpoint" binding="webHttpBinding" contract="Project.Services.IService1" /> 
    

    New

    <endpoint binding="wsHttpBinding" contract="Project.Services.IService1" />
    

    After making this change the service and client are working flawlessly.