Export (0) Print
Expand All

How to: Use the HTTP Transport

.NET Framework 3.5

You can use the HTTP transport to create applications on a device that will connect to a Windows Communication Foundation (WCF) service on the desktop.

This topic describes how to configure the WCF service to handle connecting devices and how to create the client application. It explains the differences in WCF service configuration and client-side coding that you must consider to enable mobile devices to connect to the service. For additional information about how to create WCF applications for the desktop, see the Getting Started Tutorial in the WCF documentation.

To create the WCF service for the desktop

  1. Create a new Web service project.

  2. Modify the Web.config file as shown in the following example. Modify the following elements and attributes in the file:

    • Change the <endpoint> binding attribute value to "basicHttpBinding". The .NET Compact Framework supports text encoding, but not binary encoding.

    • Change the behaviorConfiguration attribute to refer to the new behavior name.

    • Replace the <behavior> element as shown in the example.

    • If you need to register the HTTP service handler in the Web.config file, add a new <system.WebServer> element with the information shown in the example.

    <?xml version="1.0"?>
    
    <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
      <system.serviceModel>
        <services>
          <service name="CalculatorService" behaviorConfiguration="MyServiceTypeBehaviors">
            <endpoint contract="ICalculatorService" binding="basicHttpBinding"/>
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="MyServiceTypeBehaviors">
              <serviceMetadata httpGetEnabled="true" />
              <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    
      <system.web>
        <compilation debug="true"/>
      </system.web>
      
      <system.webServer>
        <handlers>
          <add name="HttpSvcHandler" path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" resourceType="Unspecified" />
        </handlers>
      </system.webServer>
    
    </configuration>
    
  3. In the source code for the WCF service, remove any parameters specified in the ServiceContract and OperationContract attributes from your code.

    NoteNote:

    This sample does not implement support for parameters specified in contracts such as ServiceContract and OperationContract. If you need parameter support for these contracts, you can use the WCF .NET Compact Framework ServiceModel Utility tool (NetCFSvcUtil.exe) to generate client code. This tool builds support for many of these parameters into applications that are based on the .NET Compact Framework. NetCFSvcUtil.exe is available in the Power Toys for .NET Compact Framework. For more information, see Power Toys for .NET Compact Framework.

    The following example shows the WCF service source code for a simplified calculator application.

    [ServiceContract()]
    public interface ICalculatorService
    {
        [OperationContract]
        double Add(double n1, double n2);
        [OperationContract]
        double Subtract(double n1, double n2);
    }
    
    public class CalculatorService : ICalculatorService
    {
        public double Add(double n1, double n2) { return n1 + n2; }
        public double Subtract(double n1, double n2) { return n1 - n2; }
    }
    
  4. Set the WCF service to a specific port on your Web server.

    Use any port number between 10000 and 650000. This example uses port 50505.

  5. Start the Web server.

    If you want to view Web Services Description Language (WSDL) output and run the service on localhost, browse to http://localhost:50505/CalculatorService/Service.svc?wsdl. Use the same port number and Web project name that you specified for the WCF service.

  6. If you are planning to connect to the Web server from a remote computer or device, set up a virtual directory to point to the directory that contains the Web project.

    NoteNote:

    The ASP.NET Development Server in Visual Studio responds only to requests from your local development machine. We recommend that you use Internet Information Services (IIS) to specify a virtual directory. This enables you to connect to the Web server from a remote device as long as the server is reachable.

  7. Verify that you can access the directory from a desktop browser and a device browser.

To create the .NET Compact Framework client

  1. While the service is running, open a command line and navigate to the directory where the WCF service is located.

  2. From the command line, run the WCF ServiceModel Desktop Utility tool (SvcUtil.exe) to generate a WCF client proxy. Here is an example of the command-line invocation for SvcUtil in which the service is hosted on localhost:

    svcutil.exe /language:c# http://localhost:50505/CalculatorService/Service.svc
    

    The following example shows a client proxy generated by SvcUtil that is based on the simple calculator example.

    //------------------------------------------------------------------------------ 
    // <auto-generated> 
    //     This code was generated by a tool. 
    //     Runtime Version:2.0.50727.42 
    // 
    //     Changes to this file may cause incorrect behavior and will be lost if 
    //     the code is regenerated. 
    // </auto-generated> 
    //------------------------------------------------------------------------------
    
    
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName="ICalculatorService")]
    public interface ICalculatorService
    {
    
        [System.ServiceModel.OperationContractAttribute(Action="http://fabrikam.com/ICalculatorService/Add", ReplyAction="http://fabrikam.com/ICalculatorService/AddResponse")]
        double Add(double n1, double n2);
    
        [System.ServiceModel.OperationContractAttribute(Action="http://fabrikam.com/ICalculatorService/Subtract", ReplyAction="http://fabrikam.com/ICalculatorService/SubtractResponse")]
        double Subtract(double n1, double n2);
    }
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    public interface ICalculatorServiceChannel : ICalculatorService, System.ServiceModel.IClientChannel
    {
    }
    
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    public partial class CalculatorServiceClient : System.ServiceModel.ClientBase<ICalculatorService>, ICalculatorService
    {
    
        public CalculatorServiceClient()
        {
        }
    
        public CalculatorServiceClient(string endpointConfigurationName) : 
                base(endpointConfigurationName)
        {
        }
    
        public CalculatorServiceClient(string endpointConfigurationName, string remoteAddress) : 
                base(endpointConfigurationName, remoteAddress)
        {
        }
    
        public CalculatorServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(endpointConfigurationName, remoteAddress)
        {
        }
    
        public CalculatorServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(binding, remoteAddress)
        {
        }
    
        public double Add(double n1, double n2)
        {
            return base.Channel.Add(n1, n2);
        }
    
        public double Subtract(double n1, double n2)
        {
            return base.Channel.Subtract(n1, n2);
        }
    }
    
  3. Remove unsupported attributes and elements from the generated client proxy code, including the following:

    • All System.ServiceModel attributes.

    • References to the IClientChannel class.

    • References to <endpoint> configuration names.

    • Method implementations that call methods of the ServiceContract interface on the internal channel.

    The following example shows the code after these modifications.

    //------------------------------------------------------------------------------ 
    // <auto-generated> 
    //     This code was generated by a tool. 
    //     Runtime Version:2.0.50727.42 
    // 
    //     Changes to this file may cause incorrect behavior and will be lost if 
    //     the code is regenerated. 
    // </auto-generated> 
    //------------------------------------------------------------------------------ 
    
    
    public interface ICalculatorService
    {
    
        double Add(double n1, double n2);
    
        double Subtract(double n1, double n2);
    }
    
    public partial class CalculatorServiceClient : System.ServiceModel.ClientBase<ICalculatorService>, ICalculatorService
    {
    
        // Add a variable to specify the server address. 
        public static System.ServiceModel.EndpointAddress ServiceEndPoint = new System.ServiceModel.EndpointAddress("http://fabrikam.com/CalcService/CalculatorService/Service.svc");
    
        public CalculatorServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(binding, remoteAddress)
        {
        }
    
        public double Add(double n1, double n2)
        {
            return base.Channel.Add(n1, n2);
        }
    
        public double Subtract(double n1, double n2)
        {
            return base.Channel.Subtract(n1, n2);
        }
    }
    
  4. Create a client project.

  5. Add the generated client proxy to the project.

  6. In the generated proxy code, change the fully-qualified reference to ClientBase<TChannel> to the user-defined ClientBase class.

  7. In the generated proxy code, add method implementations by invoking the Call method in the user-defined ClientBase class.

    public double Add(double n1, double n2)
    {
        return (double)base.Call("Add", "http://fabrikam.com/CalcService/ICalculatorService/Add", new string[] { "n1", "n2" }, new object[] { n1, n2 }, typeof(double));
    }
    
  8. Add the base class for the proxy to the project. This class is named ClientBase.

    Change the base class reference of your client proxy to point to your implementation of ClientBase.

    NoteNote:

    In this example, the CustomBodyWriter class in ClientBase supports only primitive types. To support non-primitive types, you have to extend the OnWriteBodyContents method. For example, you could call a custom serializer to serialize message data. In this case, you would translate code attributes in the generated client proxy to attributes that the XML serializer could consume. In this scenario, you must first add the following switch when you run SvcUtil: /serializer:xmlserializer http://endpoint.

    The following code shows an example of the ClientBase class.

    public class ClientBase<TChannel>
        where TChannel : class
    {
        private IRequestChannel requestChannel;
        private MessageVersion messageVersion;
    
        public ClientBase(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress)
        {
            //this.remoteAddress = remoteAddress; 
            this.messageVersion = binding.MessageVersion;
    
            IChannelFactory<IRequestChannel> channelFactory = binding.BuildChannelFactory<IRequestChannel>(
                new BindingParameterCollection());
            channelFactory.Open();
            this.requestChannel = channelFactory.CreateChannel(remoteAddress);
        }
    
        public object Call(string op, string action, string[] varnames, object[] varvals, Type returntype)
        {
            requestChannel.Open(TimeSpan.MaxValue);
    
            //Message msg = 					 
            //Message.CreateMessage(MessageVersion.<FromBinding>, 
            //      action, 
            //      new CustomBodyWriter(op, varnames, varvals, 				 
            //"<ns passed in from Proxy>"));
    
            Message msg = 					
            Message.CreateMessage(this.messageVersion, action,
                  new CustomBodyWriter(op, varnames, varvals, 				
            "<ns passed in from Proxy>"));
    
            Message reply = requestChannel.Request(msg, TimeSpan.MaxValue);
            XmlDictionaryReader reader = reply.GetReaderAtBodyContents();
            reader.ReadToFollowing(op + "Result");
            return reader.ReadElementContentAs(returntype, null);
        }
    
    }
    
    internal class CustomBodyWriter : BodyWriter
    {
        private string op;
        private string[] varnames;
        private object[] varvals;
        private string ns;
    
        public CustomBodyWriter(string op, string[] varnames, object[] varvals, string ns)
            : base(true)
        {
            this.op = op;
            this.varnames = varnames;
            this.varvals = varvals;
            this.ns = ns;
        }
    
        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
        {
            writer.WriteStartElement(op, ns);
            for (int i = 0; i < varnames.Length; i++)
                writer.WriteElementString(varnames[i], varvals[i].ToString());
            writer.WriteEndElement();
        }
    }
    
  9. Add a class to instantiate and use the client proxy.

    The following example shows code that invokes the client proxy.

    static void Main()
    {
        string serverAddress = CalculatorServiceClient.ServiceEndPoint.Uri.AbsoluteUri;
        // Using basic http connection. WS binding should be also available.
        ICalculatorService proxy = new CalculatorServiceClient(new BasicHttpBinding(), new EndpointAddress(serverAddress));
    
    
        MessageBox.Show("Add 3 + 6...");
        MessageBox.Show((proxy.Add(3, 6)).ToString());
        MessageBox.Show("Subtract 8 - 3...");        
        MessageBox.Show((proxy.Subtract(8, 3)).ToString());
    
    }
    
  10. Build the client application and deploy it to your device.

  11. When the WCF service is running and your device is connected to the network, start the client application on the device.

The source code for the WCF service requires references to the following namespaces:

The source code for the ClientBase class requires references to the following namespaces:

The source code for the class that contains the Main method in the client application requires references to the following namespaces:

This example does not implement any WCF security features. For more information about supported security features, see Messaging in the .NET Compact Framework.

Community Additions

ADD
Show:
© 2014 Microsoft