Anropa en REST-tjänst från en WCF-tjänst
När du anropar en REST-tjänst från en vanlig (SOAP-baserad) WCF-tjänst åsidosätter åtgärdskontexten på tjänstmetoden (som innehåller information om den inkommande begäran) kontexten som ska användas av den utgående begäran. Detta gör att HTTP GET-begäranden ändras till HTTP POST-begäranden. Om du vill tvinga WCF-tjänsten att använda rätt kontext för att anropa TJÄNSTEN i REST-format skapar du en ny OperationContextScope och anropar REST-tjänsten inifrån åtgärdskontextomfånget. Det här avsnittet beskriver hur du skapar ett enkelt exempel som illustrerar den här tekniken.
Definiera tjänstkontraktet i REST-stil
Definiera ett enkelt SERVICE-kontrakt i REST-stil:
[ServiceContract]
public interface IRestInterface
{
[OperationContract, WebGet]
int Add(int x, int y);
[OperationContract, WebGet]
string Echo(string input);
}
Implementera tjänstkontraktet i REST-stil
Implementera tjänstkontraktet i REST-stil:
public class RestService : IRestInterface
{
public int Add(int x, int y)
{
return x + y;
}
public string Echo(string input)
{
return input;
}
}
Definiera WCF-tjänstkontraktet
Definiera ett WCF-tjänstkontrakt som ska användas för att anropa REST-tjänsten:
[ServiceContract]
public interface INormalInterface
{
[OperationContract]
int CallAdd(int x, int y);
[OperationContract]
string CallEcho(string input);
}
Implementera WCF-tjänstkontraktet
Implementera WCF-tjänstkontraktet:
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);
}
}
Skapa klientproxyn för REST-tjänsten
Använda ClientBase<TChannel> för att implementera klientproxyn. För varje metod som heter skapas en ny OperationContextScope och används för att anropa åtgärden.
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);
}
}
}
Värd och anropa tjänsterna
Var värd för båda tjänsterna i en konsolapp och lägg till de slutpunkter och beteenden som behövs. Och anropa sedan den vanliga WCF-tjänsten:
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"));
}
Fullständig kodlista
Följande är en fullständig lista över exemplet som implementeras i det här avsnittet:
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"));
}
}