Reputation:
I have the following WebInvoke Attribute:
[OperationContract]
[WebInvoke(
Method = "POST",
UriTemplate = "",
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
I would like the UriTemplate value to be set based on a runtime value. Is there any way to set the UriTemplate in the service implementation at runtime?
Upvotes: 1
Views: 1961
Reputation: 87238
Yes, you can do that, if you use an endpoint behavior which is added before the WebHttpBehavior
. This behavior can change the properties of the WebGetAttribute
/WebInvokeAttribute
. The code below shows an example of a behavior which changes the UriTemplate
property of a [WebGet]
, but it would work just as well for [WebInvoke]
.
public class StackOverflow_7590279
{
[ServiceContract]
public class Service
{
[WebGet(UriTemplate = "/Add?x={x}&y={y}", ResponseFormat = WebMessageFormat.Json)]
public int Add(int x, int y)
{
return x + y;
}
}
public class MyBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
foreach (OperationDescription od in endpoint.Contract.Operations)
{
if (od.Name == "Add")
{
WebGetAttribute wga = od.Behaviors.Find<WebGetAttribute>();
if (wga != null)
{
wga.UriTemplate = "/Add?first={x}&second={y}";
}
}
}
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
var endpoint = host.AddServiceEndpoint(typeof(Service), new WebHttpBinding(), "");
// This has to go BEFORE WebHttpBehavior
endpoint.Behaviors.Add(new MyBehavior());
endpoint.Behaviors.Add(new WebHttpBehavior());
host.Open();
Console.WriteLine("Host opened");
WebClient c = new WebClient();
Console.WriteLine("Using the original template (values won't be received)");
Console.WriteLine(c.DownloadString(baseAddress + "/Add?x=45&y=67"));
c = new WebClient();
Console.WriteLine("Using the modified template (will work out fine)");
Console.WriteLine(c.DownloadString(baseAddress + "/Add?first=45&second=67"));
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
Upvotes: 5