Use WCF without referencing services, and manually write the client proxy class

Source: Internet
Author: User
Tags wsdl

I wrote a chat program developed using WCF. You can read the previous blog.

In that chat program, I directly use WCF without referencing the service. I didn't talk about this knowledge point before. For Beginners, I may not know what's going on.

The reason why we say that WCF is much more powerful than general web services is that it is much more flexible than general web services, and it can not only run on IIS servers, in fact, it can be run in many ways, even a console application.

Now, you can recall the aforementioned "legendary WCF". Most of my examples above are of the console application type. We should regard WCF as a communication technology, not just a service. In the previous example, I told you to add service references to the client project after the server end is completed. In this way, the client proxy class is generated, we can use it like the common type.

In fact, according to the method we mentioned above, it is enough to complete many practical tasks. Do you want to expand it? Some may ask: will it be difficult to expand? Don't worry, it won't be difficult. Believe me, old Zhou never talks about what everyone can't understand.

Now let's try to write the proxy class that calls the service by ourselves without adding service references to the client. To achieve this, we must first make it clear that the service agreement we have compiled is used on both servers and clients, if you have checked the code generated by the tool when adding a service reference, you will find that it also generates the service agreement code on the client. Therefore, this is also required when we manually compile the code for calling the service. Therefore, there are two ways to share the service agreement between the server and the client, one is to copy and paste the code to the client. In another way, we can create a new class library and write the service agreement to this class library, finally, you can reference this class library on both the server side and the client side. For example, an agreement is defined as follows:

    [ServiceContract]    public interface ITest    {        [OperationContract]        int Add(int a, int b);        [OperationContract]        int GetRandmon();        [OperationContract]        int Multiply(int a, int b);    }

 

Then, we implement the protocol on the server side. Note: The interface can be implemented on the server side, and the client does not need it.

// Implement the public class myservice: commonlib. itest {random m_rand = NULL; // constructor public myservice () {m_rand = new random ();} public int add (int A, int B) {return a + B;} public int getrandmon () {return m_rand.next ();} public int multiply (int A, int B) {return a * B ;}}

Then, as before, create a service host and listen for client calls.

Static void main (string [] ARGs) {servicehost host = new servicehost (typeof (myservice); // HTTP wshttpbinding httpbinding = new wshttpbinding (securitymode. none); host. addserviceendpoint (typeof (commonlib. itest), httpbinding, "http: // localhost: 8900/"); // TCP nettcpbinding tcpbinding = new nettcpbinding (securitymode. none); host. addserviceendpoint (typeof (commonlib. itest), tcpbinding, "net. TCP: // L Ocalhost: 1700/"); // open the host. open (); console. writeline (" the service has been started. "); Console. Read (); host. Close ();}

Let's take a closer look at what is different from the previous code? Let's take a look.

1. In the past, we specified an HTTP base address when creating servicehost, but this is not required here. The base address is convenient for tools to generate proxy classes. Since we have to manually write it, you do not need to generate code or base address.

2. In the past, we added a servicemetadatabehavior object in the servicehost. description. behaviors collection to provide WSDL and help the rib tool to generate code. Now we have all manually written them, and of course we don't need to provide the WSDL.

Think about it, see? If you are interested, you can also get a base address for servicehost, but do not add servicemetadatabehavior, and then add reference to the client project, you will find ...... Oh, you know.

How can I call the service on the client now? When using the channel, some friends may see the ichannel interface and derive many interfaces, but none seem to be a class. Do you want to write the channel yourself? No, of course, it is another thing to extend the channel layer. Generally, we do not need to extend the channel, because the existing one is sufficient. We cannot see the available classes related to the channel in the "Object Browser", because. NET is implemented internally, but it is not defined as public, it is internal.

We don't have to worry about how to find the channel. It's like we're sitting in a fully automated navigation car or a car driven by a professional driver, and the driver knows how to go, we do not have to worry about how to proceed. Similarly, we can directly operate on the channel. Why? Because every service agreement we define can be considered as a channel.

As we have defined above, itest is a channel, and it has already been converted into a channel by using WCF. If you don't believe it, let's look at the example later.

We already know that the written service agreement can be operated as a channel. Therefore, to manually write code to call the service on the client, follow these steps, if you are interested, you can back it up, but it is useless to tell you.

1. Create a binding matching with the server, so you don't have to worry about it. If you sign a contract with someone else, it must be in two copies. The other party holds one copy and you take one copy, you certainly won't take a blank sheet of white paper home to save it.

2. Create a channel. Use the channelfactory <tchannel> class to create a channel. Because it is a "Factory", the factory is certainly used for production, however, the channelfactory is not used to produce rat medicines, nor to produce mines. It specifically produces channels. This tchannel can be written into the interface of your defined service agreement, as shown in the above itest.

3. The channel obtained is itest, and then the service can be called. For example, to add two numbers, call itest. Add.

4. Close the channel and forcibly convert itest to iclientchannel. You can call the close method to close the channel.

You may have questions about these steps. It doesn't matter. You may want to doubt them first. Continue.

When we first defined the service host, we used two endpoints: HTTP and TCP. So we also need to use these two methods here. I didn't say I had to call these two methods. I just wrote one more demo.

On the client, first declare the two endpoints, that is, the two addresses we have defined on the server.

        EndpointAddress edpHttp = new EndpointAddress("http://localhost:8900/");        EndpointAddress edpTcp = new EndpointAddress("net.tcp://localhost:1700/");

Then, the two binding methods are used to call the service.

Private void btnhttp_click (Object sender, eventargs e) {// create binding wshttpbinding httpbinding = new wshttpbinding (securitymode. none); // create channel channelfactory <commonlib. itest> factory = new channelfactory <commonlib. itest> (httpbinding); commonlib. itest channel = factory. createchannel (edphttp); // call int resadd = channel. add (Int. parse (txtnum11.text), Int. parse (txtnum12.text); txtresadd. TEXT = resadd. tostring (); int resmult = channel. multiply (Int. parse (txtnum21.text), Int. parse (txtnum22.text); txtresmulti. TEXT = resmult. tostring (); int Rand = channel. getrandmon (); txtrand. TEXT = Rand. tostring (); // closes the channel (iclientchannel) channel ). close ();} private void btntcp_click (Object sender, eventargs e) {// create binding nettcpbinding tcpbinding = new nettcpbinding (securitymode. none); // create channel channelfactory <commonlib. itest> factory = new channelfactory <commonlib. itest> (tcpbinding); commonlib. itest channel = factory. createchannel (edptcp); // call txtresadd. TEXT = channel. add (Int. parse (txtnum11.text), Int. parse (txtnum12.text )). tostring (); txtresmulti. TEXT = channel. multiply (Int. parse (txtnum21.text), Int. parse (txtnum22.text )). tostring (); txtrand. TEXT = channel. getrandmon (). tostring (); // closes the channel (iclientchannel) channel ). close ();}

You may ask, isn't itest an interface? How can it be called? Don't forget, we have already implemented it on the server side, and WCF will help us find the associated classes.

Now, let's take a look at the results with excitement. Remember, the server needs to run as an administrator. I have said this three thousand five hundred times.

 

Hey, at first glance, it seems that you can call it, but is it not concise? In addition, we cannot use it as a human. Each call must be produced through channelfactory, Which is troublesome. More importantly, if a server callback protocol exists, it cannot be used.

Therefore, do we consider an encapsulation of the above client code? Here we can fully consider using the clientbase <tchannel> class, which further encapsulates the channel and related operations. Of course, it is an abstract class and cannot be used directly. A class must be first generated.

/// <Summary> /// class used to call the service /// </Summary> public class myclient: clientbase <commonlib. itest>, commonlib. itest {public myclient (system. servicemodel. channels. binding binding, endpointaddress edpaddr): Base (binding, edpaddr) {} public int add (int A, int B) {return base. channel. add (a, B);} public int getrandmon () {return base. channel. getrandmon ();} public int multiply (int A, int B) {return base. channel. multiply (a, B );}}

Some people may ask, why do I need to implement the commonlib. itest interface again from clientbase <commonlib. itest>? Of course, it doesn't matter if you don't implement it. Implement the commonlib. itest interface again to make the public methods of this class the same as the itest method, so that it is convenient to call.

By accessing base. Channel, you can get a reference to itest. You do not need to create a channel by yourself, because the default implementation is already included in the base class.

Now, I want to change the previous call code. Is it concise?

        private void btnHTTP_Click(object sender, EventArgs e)        {            MyClient client = new MyClient(new WSHttpBinding(SecurityMode.None), edpHttp);            txtResAdd.Text = client.Add(int.Parse(txtNum11.Text), int.Parse(txtNum12.Text)).ToString();            txtResMulti.Text = client.Multiply(int.Parse(txtNum21.Text), int.Parse(txtNum22.Text)).ToString();            txtRand.Text = client.GetRandmon().ToString();        }        private void btnTCP_Click(object sender, EventArgs e)        {            MyClient client = new MyClient(new NetTcpBinding(SecurityMode.None), edpTcp);            txtResAdd.Text = client.Add(int.Parse(txtNum11.Text), int.Parse(txtNum12.Text)).ToString();            txtResMulti.Text = client.Multiply(int.Parse(txtNum21.Text), int.Parse(txtNum22.Text)).ToString();            txtRand.Text = client.GetRandmon().ToString();        }

Now let's take a look at the code we have written. Is it close to the code generated by? In addition, the configuration file is saved.

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.