2

I am having an issue with JSON deserialization of string values into C# properties of type object, they end up as an array of strings.

The value of foo.Bar in the Get and Post method is string[1]{"test"}, but I am expecting string "test".

I have tried attributing Foo with DataContract / DataMember, and JsonObject / JsonProperty attributes and get the same result.

Any idea why this is happening?

Here is my code from a empty Asp.net MVC3 Project. I installed the Microsoft.AspNet.WebApi RC nuget package version 4.0.20505.0 and jquery v 1.7.2

Update Updated code to include Get action and contentType: "application/json"

Global.asax

using System;
using System.Collections.Generic;
public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }

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

        routes.MapHttpRoute(
            name: "WebApi",
            routeTemplate: "api/{controller}"
        );

        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", 
                                       id = UrlParameter.Optional }
        );
    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);            
    }
}

My Test Controller

using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebApiRCTest.Controllers
{
    public class TestController : System.Web.Http.ApiController
    {
        public IEnumerable<string> Get([System.Web.Http.FromUri]Foo foo)
        {
            return new List<string>();
        }
        public void Post([System.Web.Http.FromBody]Foo foo)
        {
            object bar = foo.Bar;
        }
    }
    public class Foo
    {
        public object Bar { get; set; }
    }
}

My JavaScript

function post() {
    $.ajax({
        url: "http://localhost:55700/api/ApiTest/",
        type: "GET",
        dataType: "json",
        accept: "application/json",
        contentType: "application/json",
        data: { Bar: "test" }
    })
    $.ajax({
        url: "http://localhost:55700/api/Test/",
        type: "POST",
        dataType: "json",
        accept: "application/json",
        contentType: "application/json",
        data: { Bar: "test" }
    })
}   

2 Answers 2

3

This is actually sending 'application/x-www-form-urlencoded', not JSON. Try:

    $.ajax({
    url: "http://localhost:55700/api/Test/",
    type: "POST",
    dataType: 'json',
    contentType: 'application/json',
    accept: "application/json",
    data: JSON.stringify({ Bar: "test" })
Sign up to request clarification or add additional context in comments.

3 Comments

Adding the content type causes the Foo to be null in the Post Action and has no effect on the Get Action, which also gets a string array into foo.Bar
For JSON, you need to call JSON.stringify(). Otherwise jQuery will serialize it to form-urlencoded ("Bar=test")
Web API uses different formatters for JSON and form-urlencoded (application/x-www-form-urlencoded). I'm not sure why the form-urlencoded case deserializes the Bar property into an array. The JSON formatter can handle anonymous types. Also, for a GET request, the data is encoded into the URI query string, so it's not JSON, and having a content type doesn't make sense in that case. The URI will be "/api/Test/?Bar=test".
0

I ran into this problem too - I created a simple attribute called JsonFromUri that does basically what it says. You can get it from nuget or check it out yourself here:

https://github.com/itsdrewmiller/JsonFromUri

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.