wcfoptional-parametersuritemplate

Optional parameter in UriTemplate in WCF


I've used the hint in this thread and provided a default value, so that when a user doesnät specify the virutal sub-directory, I'm making the assumption that he meant all the stuff to be listed. It works.

[OperationContract]
[WebInvoke(UriTemplate = "GetStuff/{type=all}", ...]
IEnumerable<Stuff> GetStuff(String type);

However, it would be nicer to specify a default value, instead. However, default(String) is null and I'd like to sent in an actual value. Particularly, I've set my heart on String.Empty. However, I noticed that the following doesn't work. The condition on server side doesn't recognize the empty string (...where 'type' in (ColName, '', 'all')).

[OperationContract]
[WebInvoke(UriTemplate = "GetStuff/{type=String.Empty}", ...]
IEnumerable<Stuff> GetStuff(String type);

What to do?


Solution

  • You can't really have an empty default value in an UriTemplate, but you can have something which will mean a default value, and at the operation you can replace that with the actual default value you want, as shown below.

    public class StackOverflow_17251719
    {
        const string DefaultValueMarker = "___DEFAULT_VALUE___";
        const string ActualDefaultValue = "";
        [ServiceContract]
        public class Service
        {
            [WebInvoke(UriTemplate = "GetStuff/{type=" + DefaultValueMarker + "}", ResponseFormat = WebMessageFormat.Json)]
            public IEnumerable<string> GetStuff(String type)
            {
                if (type == DefaultValueMarker)
                {
                    type = ActualDefaultValue;
                }
    
                yield return type;
            }
        }
        public static void SendBodylessPostRequest(string uri)
        {
            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
            req.Method = "POST";
            req.ContentType = "application/json";
            req.GetRequestStream().Close(); // no request body
    
            HttpWebResponse resp;
            try
            {
                resp = (HttpWebResponse)req.GetResponse();
            }
            catch (WebException e)
            {
                resp = (HttpWebResponse)e.Response;
            }
    
            Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
            foreach (string headerName in resp.Headers.AllKeys)
            {
                Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]);
            }
    
            Console.WriteLine();
            Stream respStream = resp.GetResponseStream();
            Console.WriteLine(new StreamReader(respStream).ReadToEnd());
    
            Console.WriteLine();
            Console.WriteLine("  *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*  ");
            Console.WriteLine();
        }
        public static void Test()
        {
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
            WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
            host.Open();
            Console.WriteLine("Host opened");
    
            SendBodylessPostRequest(baseAddress + "/GetStuff/nonDefault");
            SendBodylessPostRequest(baseAddress + "/GetStuff");
    
            Console.Write("Press ENTER to close the host");
            Console.ReadLine();
            host.Close();
        }
    }