12

I need to pass a dynamic JSON object to my Web API controller so that I can process it depending on what type it is. I have tried using the JSON.NET example that can be seen here but when I use Fiddler, I can see that the passed in JObect is always null.

This is an exert from the example pasted into Fiddler:

POST http://localhost:9185/api/Auto/PostSavePage/  HTTP/1.1
User-Agent: Fiddler
Content-type: application/json
Host: localhost
Content-Length: 88

{AlbumName: "Dirty Deeds",Songs:[ { SongName: "Problem Child"},{ SongName:  
"Squealer"}]}

Ans here is my very simple Web API controller method:

 [HttpPost]
 public JObject PostSavePage(JObject jObject)
 {        
     dynamic testObject = jObject;         
     // other stuff here
 }

I am new to this and I have a couple of questions around this area:

Am I doing something wrong in this particular example?

Arguably, more importantly, is there a better way to pass in a dynamic JSON object (from an JavaScript AJAX post)?

tereško
  • 58,060
  • 25
  • 98
  • 150
davy
  • 4,474
  • 10
  • 48
  • 71
  • 2
    You should stringify your JavaScript object before posting it to the server. The data shown (currently) in your question does not represent valid JSON. – Perception Dec 28 '12 at 15:29
  • I was not able to repro your issue in a newly created MVC4 Web.API project. I send a request with fiddler with the exact same values and the `jObject` parameter is properly filled with data. Maybe something is wrong with your routing, do you have any custom routes? – nemesv Dec 28 '12 at 17:36
  • Thanks nemesv. I also tried a new project and you're right, the jObject is fine. I do have custom routes so will have a look there. – davy Jan 01 '13 at 22:49

2 Answers2

16

As per Perception's comment your JSON doesn't look valid. Run it through JSONLint and you get:

Parse error on line 1:
{    AlbumName: "Dirty De
-----^
Expecting 'STRING', '}'

Change it to have " around the field names:

{
    "AlbumName": "Dirty Deeds",
    "Songs": [
        {
            "SongName": "Problem Child"
        },
        {
            "SongName": "Squealer"
        }
    ]
}

Also have you tried swapping out your JObject for either a JToken or a Dynamic object (e.g. here)?

[HttpPost]
 public JObject PostSavePage(JToken testObject)
 {                
     // other stuff here
 }

OR

 [HttpPost]
 public JObject PostSavePage(dynamic testObject)
 {                
     // other stuff here
 }
Mark Jones
  • 12,156
  • 2
  • 50
  • 62
  • Thanks, none of these suggestions is working for me. See nemesv's comment above. I think it must be something to do with my custom routes. – davy Dec 31 '12 at 12:25
  • @davy sorry to hear that. If you are able to see that testObject is null then your routes should be OK... can you get a breakpoint inside PostDavePage? I will try take another stab at answering if you have your route config to share. – Mark Jones Jan 02 '13 at 11:06
  • Thanks a lot. Something strange is going. I'm in th eprocess of copying files into my basic working solution. Hopefully then, it will work or I'll be able to pinpoint the problem. I think the project may be corrupted in some way as I'm getting some other weird errors that I wont go into yet as I don't get them in the new app. I will update when I find anything. Thanks again. – davy Jan 02 '13 at 12:36
4

Thanks to everyone who helped here. Unfortunately, I never got to the bottom of what was wrong.

I ported the project over piece by piece to a new project and it works fine.

For info, I have a RouteConfig class, which is quite simple at the moment:

public class RouteConfig
{       
    private static string ControllerAction = "ApiControllerAction";

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapHttpRoute(
            name: ControllerAction,
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

My call into the API now uses JSON.Stringify:

$.ajax("http://localhost:54997/api/values/PostSavePage/", {
    data:  JSON.stringify(jObject),                               
    contentType: 'application/json',
    type: 'POST'
});

The original API action works.

Note, that I'm only playing with this at the moment so the code is not the best but I thought it may be useful in basic form in case someone else has a similar issue.

davy
  • 4,474
  • 10
  • 48
  • 71
  • are you sure of your controller in the first app ? http://localhost:9185/api/Auto/PostSavePage/ it must be AutoController – riadh gomri Dec 06 '13 at 16:57