2

I would like to accept a post from a 3rd party tool which posts a complex json object. For this question we can assume an object like this:

{
   a: "a value",
   b: "b value",
   c: "c value",
   d: {
     a: [1,2,3]
  }
}

my .net code looks like

asmx:

[WebMethod]
public bool AcceptPush(ABCObject ObjectName) { ... }

class.cs

public class ABCObject 
{
  public string a;
  public string b;
  public string c;       
  ABCSubObject d;
}
public class ABCSubObject 
{
  public int[] a;
}

This all works perfectly if I pass the object when it is wrapped and named "ObjectName":

{
  ObjectName:
  {
     a: "a value",
     b: "b value",
     c: "c value",
     d: {
       a: [1,2,3]
     }
  }
}

But fails without the object wrapped in an named object. Which is what is posted.

{
   a: "a value",
   b: "b value",
   c: "c value",
   d: {
     a: [1,2,3]
   }
}

I can accept this or any post with a Handler (ashx), but is this possible using a vanilla .Net Webservice (asmx)?

I also tried combinations of:

    [WebMethod(EnableSession = false)]
    [WebInvoke(
        Method = "POST",
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json, 
        BodyStyle = WebMessageBodyStyle.Bare, 
        UriTemplate="{ObjectName}")]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]

I suspect UriTemplate or some missing BodyTemplate would work.

user1529413
  • 458
  • 8
  • 19
  • I dunno if it works on webservice but in mvc you can use the [FromBody] annotation like that AcceptPush([FromBody] ABCObject ObjectName) – Milton Filho Jun 07 '17 at 15:56
  • Thanks, from your suggestion I found this https://stackoverflow.com/questions/42765459/frombody-in-webservice which seems related. – user1529413 Jun 07 '17 at 17:53

1 Answers1

3

You mignt need to remove WebMethod's parameter, and map json string to ABCObject manually.

[WebMethod]
public bool AcceptPush() 
{
    ABCObject ObjectName = null;

    string contentType = HttpContext.Current.Request.ContentType;

    if (false == contentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) return false;

    using (System.IO.Stream stream = HttpContext.Current.Request.InputStream)
    using (System.IO.StreamReader reader = new System.IO.StreamReader(stream))
    {
        stream.Seek(0, System.IO.SeekOrigin.Begin);

        string bodyText = reader.ReadToEnd(); bodyText = bodyText == "" ? "{}" : bodyText;

        var json = Newtonsoft.Json.Linq.JObject.Parse(bodyText);

        ObjectName = Newtonsoft.Json.JsonConvert.DeserializeObject<ABCObject>(json.ToString());
    }

    return true;                
}

Hope this helps.

Takeo Nishioka
  • 369
  • 2
  • 11
  • 1
    Based on your answer it seems that Microsoft fails to handle this simple request and a 3rd party tool is needed – user1529413 Oct 31 '19 at 11:07