9

If have the following Api Controller ... using StrutureMap for the DI ...

using System;
using System.Dynamic;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using IdentityService.Domain;
using IdentityService.Domain.Contracts;
using IdentityService.Domain.Models;

namespace IdentityService.Controllers
{
    public class AccountController : ApiController
    {
        private readonly IRepository<Client> _clientRepository;
        private readonly IRepository<RelyingParty> _relyingPartyRepository;
        private readonly IRepository<Token> _tokenRepository;

        public AccountController(
            IRepository<Client> clientRepository,
            IRepository<RelyingParty> relyingPartyRepository,
            IRepository<Token> tokenRepository)
        {
            _clientRepository = clientRepository;
            _relyingPartyRepository = relyingPartyRepository;
            _tokenRepository = tokenRepository;
        }

        public HttpResponseMessage Post(
            [FromBody] dynamic data)
        {
            dynamic result = new ExpandoObject();

            try
            {
                var clientAuthenticator = new ClientAuthenticator(
                    _clientRepository,
                    _relyingPartyRepository,
                    _tokenRepository);

                Token token;
                clientAuthenticator.Authenticate(
                    data.Key,
                    data.ChecksumValue,
                    data.Checksum,
                    data.Name,
                    data.Password,
                    out token);

                result.Token = token;
            }
            catch (Exception ex)
            {
                result.ErrorCode = ex.GetType().ToString();
                result.ErrorMessage = ex.GetBaseException().Message;
            }

            return this.Request.CreateResponse(HttpStatusCode.OK, (ExpandoObject)result);
        }
    }
}

Using Fiddler, I am make the following post:

POST http://localhost:54029/api/account HTTP/1.1
User-Agent: Fiddler
Host: localhost:54029
Content-Type: "application/json"
Content-Length: 218

{
    "Key": "7d42276d3c3954716c672543385b575836472f5d543d7776205627413a",
    "ChecksumValue": "127.0.0.1",
    "Checksum": "ao4Ei77BaX1/iMZMTAJxWzt4fxc=",
    "Name": "USER_NAME",
    "Password": "PASSWORD"
}

Any idea why my data would be null? I have tried switching to JObject, with no success. All the examples I have found makes me think this should work.

Here is the complete response:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcY29kZS1tYXR0cnVtYVx0YWxrLWF1dGhlbnRpY2F0aW9uLXNlcnZlclxJZGVudGl0eVNlcnZpY2VcYXBpXGFjY291bnQ=?=
X-Powered-By: ASP.NET
Date: Mon, 27 May 2013 13:59:45 GMT
Content-Length: 137

{"ErrorCode":"Microsoft.CSharp.RuntimeBinder.RuntimeBinderException","ErrorMessage":"Cannot perform runtime binding on a null reference"}

Any help would be much appreciated!

Update

I tried just a simple example, like:

public async Task<dynamic> Post(dynamic data)
{
     var body = await Request.Content.ReadAsStringAsync();

     return data;
}

The parameter data is still null, but I can see the values in body.

9
  • 2
    JObject should work. Dynamic won't. Commented May 27, 2013 at 14:14
  • Switching to JObject doesn't work either ... same error message. Commented May 27, 2013 at 14:24
  • 1
    Are you setting the content-type header to application/json on the client? Commented May 27, 2013 at 14:26
  • Yes ... updated my question with what else I am sending over ... Commented May 27, 2013 at 14:28
  • Where exactly does the error occur? The data property is coming through for me, but your CreateResponse probably won't work because I don't think JSON.NET can serialize an expando. Commented May 27, 2013 at 14:34

5 Answers 5

13

Remove the quotes from "application/json".

Content-Type: application/json
Sign up to request clarification or add additional context in comments.

3 Comments

I also found had to use JObject as the input type. Then just do string prop = (string)myJObject["propName"];
Won't this cause you to lose XML deserialization as a result?
The post data is in json format so the content type should reflect that. If the post data was xml data then the content type would be xml.
4

In an MVC 6 controller (which extends from Controller and not ApiController) the following does work (with report being JSON) :

    [HttpPost("[action]")]
    public void RunReport([FromBody]dynamic report)
    {
        ....
    }

Updated: For MVC 5 this is what I use

    [HttpPost]
    public async Task<HttpResponseMessage> FBLogin(Newtonsoft.Json.Linq.JObject jObject)
    {
        dynamic data = (dynamic)jObject;

        string accessToken = data.accessToken;
        ...
     }

Where the JSON payload is :

 '{accessToken: "EAAJF9eVIKOsBABdKVNOLJyfyCnnkrl8mlW2crgZC1NYsDqgq9ZBIZC......" }'

2 Comments

I can't speak for previous MVC versions if this works
This worked for me. After that you should the following: var email = report.email.ToString();
1

if you make the param from [FromBody] to dynamic, and if its a JSON object (made with JSON.stringify) then you can just use .ToString() to get the string value and you should be OK

   public void Post(string token, [FromBody]dynamic value)
    {
        int userID = db.GetUserIdByToken(token);
        db.InsertJson(userID, value.ToString());
    }

other definitions is headers: {'Content-Type': 'application/json'},

Comments

0

I had same problem. In my case i had success doing this:

Used dynamic as parameter type and used JsonConvert.DeserializeObject.

[Route("webhook")]
public class WebhookController : Controller
{
    [HttpPost]
    [Route("v1/cobranca")]
    public async Task<ActionResult<IStatusCodeHttpResult>> Post([FromBody] dynamic retornoCobranca)
    {
 
        dynamic retornoObj = JsonConvert.DeserializeObject<dynamic>(retornoCobranca.ToString());

        var id = ((JValue)retornoObj.payment.id).Value;
        
        ...
    }
}

In my case, the request body is something like this:

{
    "payment": {
        "id": "123456"
    }
}

Comments

-4

remove [FromBody] attribute and it should work

1 Comment

I tried public HttpResponseMessage Post(dynamic data) and it still is showing data as null.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.