Een REST-service aanroepen vanuit een WCF-service
Wanneer u een REST-service aanroept vanuit een reguliere WCF-service (SOAP), overschrijft de bewerkingscontext op de servicemethode (die informatie over de binnenkomende aanvraag bevat) de context die door de uitgaande aanvraag moet worden gebruikt. Dit zorgt ervoor dat HTTP GET-aanvragen worden gewijzigd in HTTP POST-aanvragen. Als u wilt afdwingen dat de WCF-service de juiste context gebruikt voor het aanroepen van de REST-service, maakt u een nieuwe OperationContextScope service en roept u de REST-service aan vanuit het contextbereik van de bewerking. In dit onderwerp wordt beschreven hoe u een eenvoudig voorbeeld maakt dat deze techniek illustreert.
Het REST-servicecontract definiëren
Definieer een eenvoudig REST-servicecontract:
[ServiceContract]
public interface IRestInterface
{
[OperationContract, WebGet]
int Add(int x, int y);
[OperationContract, WebGet]
string Echo(string input);
}
Het REST-servicecontract implementeren
Implementeer het REST-servicecontract:
public class RestService : IRestInterface
{
public int Add(int x, int y)
{
return x + y;
}
public string Echo(string input)
{
return input;
}
}
Het WCF-servicecontract definiëren
Definieer een WCF-servicecontract dat wordt gebruikt om de REST-stijlservice aan te roepen:
[ServiceContract]
public interface INormalInterface
{
[OperationContract]
int CallAdd(int x, int y);
[OperationContract]
string CallEcho(string input);
}
Het WCF-servicecontract implementeren
Implementeer het WCF-servicecontract:
public class NormalService : INormalInterface
{
static MyRestClient client = new MyRestClient(RestServiceBaseAddress);
public int CallAdd(int x, int y)
{
return client.Add(x, y);
}
public string CallEcho(string input)
{
return client.Echo(input);
}
}
De clientproxy maken voor de REST-service
Gebruiken ClientBase<TChannel> om de clientproxy te implementeren. Voor elke aangeroepen methode wordt een nieuwe OperationContextScope gemaakt en gebruikt om de bewerking aan te roepen.
public class MyRestClient : ClientBase<IRestInterface>, IRestInterface
{
public MyRestClient(string address)
: base(new WebHttpBinding(), new EndpointAddress(address))
{
this.Endpoint.Behaviors.Add(new WebHttpBehavior());
}
public int Add(int x, int y)
{
using (new OperationContextScope(this.InnerChannel))
{
return base.Channel.Add(x, y);
}
}
public string Echo(string input)
{
using (new OperationContextScope(this.InnerChannel))
{
return base.Channel.Echo(input);
}
}
}
De services hosten en aanroepen
Host beide services in een console-app, waarbij de benodigde eindpunten en gedrag worden toegevoegd. En roep vervolgens de reguliere WCF-service aan:
public static void Main()
{
ServiceHost restHost = new ServiceHost(typeof(RestService), new Uri(RestServiceBaseAddress));
restHost.AddServiceEndpoint(typeof(IRestInterface), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
restHost.Open();
ServiceHost normalHost = new ServiceHost(typeof(NormalService), new Uri(NormalServiceBaseAddress));
normalHost.AddServiceEndpoint(typeof(INormalInterface), new BasicHttpBinding(), "");
normalHost.Open();
Console.WriteLine("Hosts opened");
ChannelFactory<INormalInterface> factory = new ChannelFactory<INormalInterface>(new BasicHttpBinding(), new EndpointAddress(NormalServiceBaseAddress));
INormalInterface proxy = factory.CreateChannel();
Console.WriteLine(proxy.CallAdd(123, 456));
Console.WriteLine(proxy.CallEcho("Hello world"));
}
Volledige codevermelding
Hier volgt een volledige lijst van het voorbeeld dat in dit onderwerp is geïmplementeerd:
public class CallingRESTSample
{
static readonly string RestServiceBaseAddress = "http://" + Environment.MachineName + ":8008/Service";
static readonly string NormalServiceBaseAddress = "http://" + Environment.MachineName + ":8000/Service";
[ServiceContract]
public interface IRestInterface
{
[OperationContract, WebGet]
int Add(int x, int y);
[OperationContract, WebGet]
string Echo(string input);
}
[ServiceContract]
public interface INormalInterface
{
[OperationContract]
int CallAdd(int x, int y);
[OperationContract]
string CallEcho(string input);
}
public class RestService : IRestInterface
{
public int Add(int x, int y)
{
return x + y;
}
public string Echo(string input)
{
return input;
}
}
public class MyRestClient : ClientBase<IRestInterface>, IRestInterface
{
public MyRestClient(string address)
: base(new WebHttpBinding(), new EndpointAddress(address))
{
this.Endpoint.Behaviors.Add(new WebHttpBehavior());
}
public int Add(int x, int y)
{
using (new OperationContextScope(this.InnerChannel))
{
return base.Channel.Add(x, y);
}
}
public string Echo(string input)
{
using (new OperationContextScope(this.InnerChannel))
{
return base.Channel.Echo(input);
}
}
}
public class NormalService : INormalInterface
{
static MyRestClient client = new MyRestClient(RestServiceBaseAddress);
public int CallAdd(int x, int y)
{
return client.Add(x, y);
}
public string CallEcho(string input)
{
return client.Echo(input);
}
}
public static void Main()
{
ServiceHost restHost = new ServiceHost(typeof(RestService), new Uri(RestServiceBaseAddress));
restHost.AddServiceEndpoint(typeof(IRestInterface), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
restHost.Open();
ServiceHost normalHost = new ServiceHost(typeof(NormalService), new Uri(NormalServiceBaseAddress));
normalHost.AddServiceEndpoint(typeof(INormalInterface), new BasicHttpBinding(), "");
normalHost.Open();
Console.WriteLine("Hosts opened");
ChannelFactory<INormalInterface> factory = new ChannelFactory<INormalInterface>(new BasicHttpBinding(), new EndpointAddress(NormalServiceBaseAddress));
INormalInterface proxy = factory.CreateChannel();
Console.WriteLine(proxy.CallAdd(123, 456));
Console.WriteLine(proxy.CallEcho("Hello world"));
}
}