开发者

How to pass a TimeSpan object to a WCF method using JSON

I'm trying to find a way to call a WCF method using JSON and pass a TimeSpan as parameter but I always receive a "Bad request" response from the service.

Here is a snippet code service interface:

 [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
    TimeSpan GetTimeSpan(TimeSpan value);

Service call:

  String method = "GetTimeSpan";
  String result = null;

  HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + method);
  request.KeepAlive = false;
  request.Method = WebRequestMethods.Http.Post;
  request.ContentType = "application/json";

  JsonSerializer serializer = new JsonSerializer();

  TimeSpan ts = new TimeSpan(23, 59, 59);
  String jsonString = JsonConvert.SerializeObject(ts);


  String data = jsonString;      //jsonString = "23:59:59"
  //I have already tryed with {"value": "23:59:59"} and the result is the same, bad request.
  request.ContentLength = data.Length;

  StreamWriter writer = new StreamWriter(request.GetRequestStream());
  writer.Write(data);
  writer.Close();

  WebResponse response = request.GetResponse();
  StreamReader reader = new StreamReader(response.GetResponseStream());
  result = reader.ReadToEnd();
  response.Close();

This is just an example. When calling a service without TimeSpan everything开发者_JS百科 works fine. I need to put it work in order do keep compatibility with other clients that are consuming the service in the typical way.

Response:

The remote server returned an error: (400) Bad Request.

Am I passing the wrong TimeSpan json representation? Or is there a way to define how to deserialize the TimeSpan when the service handles the request?

Thanks in advance


The format for TimeSpan used by WCF is not the same one used by the Newtonsoft JSON serializer (JSON.NET) . You can serialize one TimeSpan instance using the DataContractJsonSerializer (DCJS), and that will be the format required by a WCF REST service.

The code below will print out the formats of some TimeSpan values as serialized by both JSON.NET and DCJS:

public class StackOverflow_7178839
{
    public static void Test()
    {
        foreach (var ts in new TimeSpan[] { new TimeSpan(23, 59, 59), new TimeSpan(3, 4, 5, 6), new TimeSpan(-4, 3, 4, 5, 333) })
        {
            Console.WriteLine("For TimeSpan value: {0}", ts);
            Console.WriteLine("  {0}", Newtonsoft.Json.JsonConvert.SerializeObject(ts));
            DataContractJsonSerializer dcjs = new DataContractJsonSerializer(typeof(TimeSpan));
            MemoryStream ms = new MemoryStream();
            dcjs.WriteObject(ms, ts);
            Console.WriteLine("  {0}", Encoding.UTF8.GetString(ms.ToArray()));
        }
    }
}


You can form the json as mentioned below and pass

{"value":"PT19H"} => Passing 19 Hrs as timespan value

{"value":"PT19H15"} => Passing 19 Hrs, 15 Secs as timespan value

{"value":"23H59M59S"} => Passing 23 Hrs, 59 Mins and 59 Secs as timespan value


For anyone who still have a problem with WCF serializer, I have found the solution like this : use your own formatter but make sure clearing all formatter.

private void RegisterRoute() {
            var config = new WebApiConfiguration() { EnableHelpPage = true, EnableTestClient = true };
            config.Formatters.Clear();
            config.Formatters.Add(new JsonNetMediaTypeFormatter());
            config.MaxReceivedMessageSize = 2097151;
            config.MaxBufferSize = 2097151;
            RouteTable.Routes.SetDefaultHttpConfiguration(config);
            RouteTable.Routes.MapServiceRoute("sys", config);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜