Alex Gordon
Alex Gordon

Reputation: 60691

How to return an object and format it as json?

I'm attempting to return JSON objects with the following controller:

    public async Task<IHttpActionResult> Get(string query)
    {
        var client = new HttpClient(new HttpClientHandler()
        {
            Credentials = new NetworkCredential("myuser", "NotSoSecret#1", "mydomain"),
        });
        var ipAddress = Dns.GetHostAddresses("myorgetc.com").ToList()[0];
        client.BaseAddress = new Uri(string.Format("http://{0}/myorg/api/data/v8.1/", ipAddress.ToString()));

        HttpResponseMessage response = await client.GetAsync(client.BaseAddress +"accounts"+ query);
        object result;

        if (response.IsSuccessStatusCode)
        {
            result = await response.Content.ReadAsAsync<object>();
            return Ok(result);
        }

        return NotFound();
    }      

And it's returning the following exception:

This XML file does not appear to have any style information associated with it. The document tree is shown below. An error has occurred. Type 'Newtonsoft.Json.Linq.JToken' is a recursive collection data contract which is not supported. Consider modifying the definition of collection 'Newtonsoft.Json.Linq.JToken' to remove references to itself. System.Runtime.Serialization.InvalidDataContractException at System.Runtime.Serialization.DataContract.ValidatePreviousCollectionTypes(Type collectionType, Type itemType, Dictionary2 previousCollectionTypes) at System.Runtime.Serialization.DataContract.GetNonDCTypeStableName(Type type, Dictionary2 previousCollectionTypes) at System.Runtime.Serialization.DataContract.GetStableName(Type type, Dictionary2 previousCollectionTypes, Boolean& hasDataContract) at System.Runtime.Serialization.DataContract.GetDefaultStableLocalName(Type type) at System.Runtime.Serialization.DataContract.GetDCTypeStableName(Type type, DataContractAttribute dataContractAttribute) at System.Runtime.Serialization.DataContract.GetStableName(Type type, Dictionary2 previousCollectionTypes, Boolean& hasDataContract) at System.Runtime.Serialization.DataContract.GetCollectionStableName(Type type, Type itemType, Dictionary`2 previousCollectionTypes, CollectionDataContractAttribute& collectionContractAttribute) at System.Runtime.Serialization.CollectionDataContract.CollectionDataContractCriticalHelper..ctor(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, String serializationExceptionMessage, String deserializationExceptionMessage) at System.Runtime.Serialization.CollectionDataContract.CollectionDataContractCriticalHelper..ctor(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo addMethod, ConstructorInfo constructor) at System.Runtime.Serialization.CollectionDataContract..ctor(Type type, CollectionKind kind, Type itemType, MethodInfo getEnumeratorMethod, MethodInfo addMethod, ConstructorInfo constructor, Boolean isConstructorCheckRequired) at System.Runtime.Serialization.CollectionDataContract.IsCollectionOrTryCreate(Type type, Boolean tryCreate, DataContract& dataContract, Type& itemType, Boolean constructorRequired, Boolean skipIfReadOnlyContract) at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) at System.Runtime.Serialization.DataContractSerializer.GetDataContract(DataContract declaredTypeContract, Type declaredType, Type objectType) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph) at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content) at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Owin.HttpMessageHandlerAdapter.d__13.MoveNext()

What am I doing wrong? How do I return a JSON object without knowing the exact structure at dev time?

Here is my startup:

public static class Startup
    {
        // This code configures Web API. The Startup class is specified as a type
        // parameter in the WebApp.Start method.

        public static void ConfigureApp(IAppBuilder appBuilder)
        {
            // Configure Web API for self-host. 
            HttpConfiguration config = new HttpConfiguration();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            var container = new UnityContainer();
            container.RegisterType<IAccountsRepository, AccountsRepository>(new HierarchicalLifetimeManager());
            container.RegisterType<IAccountService, AccountService>(new HierarchicalLifetimeManager());
            config.DependencyResolver = new UnityResolver(container);

            appBuilder.UseWebApi(config);
        }


    }

Upvotes: 1

Views: 886

Answers (1)

jegtugado
jegtugado

Reputation: 5141

Add this to your WebApiConfig.

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

If you are still encountering the same exception, take a look at this answer and see if it helps.

As it turned out, the error was caused by the fact that I had a Microsoft Web API package installed from NuGet, which included Json.NET. After uninstalling this, it works fine.

This may be the answer for you - if not, look at which other packages you have installed (that you don't need) and remove them.

Upvotes: 1

Related Questions