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?
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();
}
}