Rainie999 发表于 2015-8-15 08:52:13

how to host a WCF service in IIS

  

IIS Hosting

The main advantage of hosting a service in the Microsoft
Internet Information Server (IIS) web server is that the host process is
launched automatically upon the first client request, and you rely on IIS to
manage the life cycle of the host process. The main disadvantage of IIS hosting
is that you can only use HTTP. With IIS5, you are further restricted to having
all services use the same port number.
Hosting in IIS is very similar to hosting a classic ASMX web
service. You need to create a virtual directory under IIS and supply a .svc file. The .svc file
functions similar to an .asmx file, and is used
to identify the service code behind the file and class. Example 1-2 shows the syntax for the .svc file.
  


Example 1-2. A .svc file
  




<%@ ServiceHost
Language   = "C#"
Debug      = "true"
CodeBehind = "~/App_Code/MyService.cs"
Service    = "MyService"
%>

    





When you use IIS hosting, the base address used for the service
always has to be the same as the address of the .svc file.
  

1.5.1.1. Using Visual Studio
2005
  
You can use Visual Studio 2005 to generate a boilerplate
IIS-hosted service. From the File menu, select New
Website and then select WCF Service from the New Web Site dialog box. This
causes Visual Studio 2005 to create a new web site, service code, and matching
.svc file. You can also use the Add New Item
dialog to add another service later on.
  

1.5.1.2. The Web.Config file
  
The web site config file (Web.Config) must list the types you want to expose as
services. You need to use fully qualified type names, including the assembly
name, if the service type comes from an unreferenced assembly:

<system.serviceModel>
   <services>
      <service name = "MyNamespace.MyService">
         ...
      </service>
   </services>
</system.serviceModel>

  


1.5.2. Self-Hosting
  
Self-hosting is the name for the technique used when the
developer is responsible for providing and managing the life cycle of the host
process. Self-hosting is used both in the case of wanting a process (or machine)
boundary between the client and the service, and when using the service
in-procthat is, in the same process as the client. The process you need to
provide can be any Windows process, such as a Windows Forms application, a
Console application, or a Windows NT Service. Note that the process must be
running before the client calls the service, which typically means you have to
pre-launch it. This is not an issue for NT Services or in-proc. Providing a host
can be done with only a few lines of code, and it does offer a few advantage
over IIS hosting.
Similar to IIS hosting, the hosting application config file
(App.Config) must list the types of the services
you wish to host and expose to the world:

<system.serviceModel>
   <services>
      <service name = "MyNamespace.MyService">
         ...
      </service>
   </services>
</system.serviceModel>

  
In addition, the host process must explicitly register the
service types at runtime and open the host for client calls, which is why the
host process must be running before the client calls arrive. Creating the host
is typically done in the Main( ) method using the class
ServiceHost, defined in Example 1-3.
  

Example 1-3. The ServiceHost
class
  




public interface ICommunicationObject
{
   void Open( );
   void Close( );
   //More members
}
public abstract class CommunicationObject : ICommunicationObject
{...}
public abstract class ServiceHostBase : CommunicationObject,IDisposable,...
{...}
public class ServiceHost : ServiceHostBase,...
{
   public ServiceHost(Type serviceType,params Uri[] baseAddresses);
   //More members
}






You need to provide the constructor of ServiceHost
with the service type, and optionally with default base addresses. The set of
base addresses can be an empty set. Even if you provide base addresses, the
service can be configured to use different base addresses. Having a set of base
addresses enables the service to accept calls on multiple addresses and
protocols, and to use only a relative URI. Note that each ServiceHost
instance is associated with a particular service type, and if the host process
needs to host multiple types of services, you will need a matching number of
ServiceHost instances. By calling the Open( ) method on the
host, you allow calls in, and by calling the Close( ) method, you
gracefully exit the host instance, allowing calls in progress to complete, and
yet refusing future client calls even if the host process is still running.
Closing is typically done on host process shutdown. For example, to host this
service in a Windows Forms application:


interface IMyContract
{...}
class MyService : IMyContract
{...}

  
you would have the following hosting code:

public static void Main( )
{
   Uri baseAddress = new Uri("http://localhost:8000/");
   ServiceHost host = new ServiceHost(typeof(MyService),baseAddress);
   host.Open( );
   //Can do blocking calls:
   Application.Run(new MyForm( ));
   host.Close( );
}

  
Opening a host loads the WCF runtime and launches worker
threads to monitor incoming requests. Since worker threads are involved, you can
perform blocking operations after opening the host. Having explicit control over
opening and closing the host provides for a nice feature not easily accomplished
with IIS hosting: you can build a custom application control applet where the
administrator explicitly opens and closes the host at will, without ever
shutting down the host.
  

1.5.2.1. Using Visual Studio
2005
  
Visual Studio 2005 allows you to add a WCF service to any
application project by selecting WCF Service from the Add New Item dialog box.
The service added this way is, of course, in-proc toward the host process, but
can be accessed by out-of-proc clients as well.
  

1.5.2.2. Self-hosting and base
addresses

You can launch a service host without providing any base
address by omitting the base addresses altogether:

public static void Main( )
{
   ServiceHost host = new ServiceHost(typeof(MyService));
   host.Open( );
   Application.Run(new MyForm( ));
   host.Close( );
}

  
  







http://www.iyunv.com/mqsuper/admin/images/warning_yellow.jpg

Do not provide a null instead of an empty list, because that
will throw an exception:

ServiceHost host;
host = new ServiceHost(typeof(MyService),null);










  
You can also register multiple base addresses separated by a
comma, as long as the addresses do not use the same transport schema, as in the
following snippet (note the use of the params qualifier in Example 1-3):

Uri tcpBaseAddress= new Uri("net.tcp://localhost:8001/");
Uri httpBaseAddress = new Uri("http://localhost:8002/");
ServiceHost host = new ServiceHost(typeof(MyService),
                                 tcpBaseAddress,httpBaseAddress);

  
WCF lets you also list the base addresses in the host config
file:

<system.serviceModel>
   <services>
      <service name = "MyNamespace.MyService">
         <host>
            <baseAddresses>
               <add baseAddress = "net.tcp://localhost:8001/"/>
               <add baseAddress = "http://localhost:8002/"/>
            </baseAddresses>
         </host>
         ...
      </service>
   </services>
</system.serviceModel>

  
When you create the host, it will use whichever base address it
finds in the config file, plus any base address you provide programmatically.
Take extra care to ensure the configured base addresses and the programmatic
ones do not overlap in the schema.
You can even register multiple hosts for the same type as long
as the hosts use different base addresses:

Uri baseAddress1= new Uri("net.tcp://localhost:8001/");
ServiceHost host1 = new ServiceHost(typeof(MyService),baseAddress1);
host1.Open( );
Uri baseAddress2= new Uri("net.tcp://localhost:8002/");
ServiceHost host2 = new ServiceHost(typeof(MyService),baseAddress2);
host2.Open( );

  
However, with the exception of some threading issues discussed
in Chapter
8, opening multiple hosts this way offers no real advantage. In addition,
opening multiple hosts for the same type does not work with base addresses
supplied in the config file and requires use of the ServiceHost
constructor.
  

1.5.2.3. Advanced hosting
features
  
The ICommunicationObject interface supported by
ServiceHost offers some advanced features, listed in Example 1-4.
  

Example 1-4. The
ICommunicationObject interface
  




public interface ICommunicationObject
{
   void Open( );
   void Close( );
   void Abort( );
   event EventHandler Closed;
   event EventHandler Closing;
   event EventHandler Faulted;
   event EventHandler Opened;
   event EventHandler Opening;
   IAsyncResult BeginClose(AsyncCallback callback,object state);
   IAsyncResult BeginOpen(AsyncCallback callback,object state);
   void EndClose(IAsyncResult result);
   void EndOpen(IAsyncResult result);
   CommunicationState State
   {get;}
//More members
}
public enum CommunicationState
{
   Created,
   Opening,
   Opened,
   Closing,
   Closed,
   Faulted
}






If opening or closing the host is a lengthy operation, you can
do so asynchronously with the BeginOpen( ) and BeginClose( )
methods. You can subscribe to hosting events such as state changes or faults,
and you can use the State property to query for the host status.
Finally, the ServiceHost class also implements the Abort( )
method. Abort( ) is an ungraceful exitwhen called, it immediately
aborts all service calls in progress and shuts down the host. Active clients
will get an exception.
  

1.5.2.4. The ServiceHost<T>
class

You can improve on the WCF-provided ServiceHost class
by defining the ServiceHost<T> class, as shown in Example 1-5.
  

Example 1-5. The
ServiceHost<T> class
  




public class ServiceHost<T> : ServiceHost
{
   public ServiceHost( ) : base(typeof(T))
   {}
   public ServiceHost(params string[] baseAddresses) :
                                 base(typeof(T),Convert(baseAddresses))
   {}
   public ServiceHost(params Uri[] baseAddresses) :
                                          base(typeof(T),baseAddresses)
   {}
   static Uri[] Convert(string[] baseAddresses)
   {
      Converter<string,Uri> convert =delegate(string address)
                                       {
                                          return new Uri(address);
                                       };
      return Array.ConvertAll(baseAddresses,convert);
   }
}






ServiceHost<T> provides simple constructors that
do not require the service type as a construction parameter, and can operate on
raw strings instead of the cumbersome Uri. I'll add quite a few
extensions, features, and capabilities to ServiceHost<T> in the
rest of the book.
页: [1]
查看完整版本: how to host a WCF service in IIS