【问题标题】:ASP.NET WEB API not binding to dynamic object on POSTASP.NET WEB API 未绑定到 POST 上的动态对象
【发布时间】:2013-05-27 13:59:47
【问题描述】:

如果有以下 Api Controller ... 为 DI 使用 StrutureMap ...

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);
        }
    }
}

使用 Fiddler,我将发布以下帖子:

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"
}

知道为什么我的数据会为空吗?我尝试切换到JObject,但没有成功。我发现的所有示例都让我认为这应该可行。

这是完整的回复:

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"}

任何帮助将不胜感激!

更新

我只是尝试了一个简单的例子,比如:

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

     return data;
}

参数data还是null,但是我可以看到body里面的值。

【问题讨论】:

  • JObject 应该可以工作。动态不会。
  • 切换到 JObject 也不起作用...同样的错误消息。
  • 您是否在客户端将 content-type 标头设置为application/json
  • 是的...用我发送的其他内容更新了我的问题...
  • 错误到底发生在哪里?数据属性正在为我提供,但您的 CreateResponse 可能无法正常工作,因为我认为 JSON.NET 不能序列化扩展。

标签: c# asp.net-web-api


【解决方案1】:

从“application/json”中删除引号。

Content-Type: application/json

【讨论】:

  • 我还发现必须使用 JObject 作为输入类型。然后就做string prop = (string)myJObject["propName"];
  • 这不会导致您丢失 XML 反序列化结果吗?
  • 帖子数据是 json 格式,所以内容类型应该反映这一点。如果发布数据是 xml 数据,那么内容类型将是 xml。
【解决方案2】:

在 MVC 6 控制器(从 Controller 而非 ApiController 扩展)中,以下确实有效(report 为 JSON):

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

更新:对于 MVC 5,这是我使用的

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

        string accessToken = data.accessToken;
        ...
     }

JSON 负载在哪里:

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

【讨论】:

  • 如果可行的话,我不能代表以前的 MVC 版本
  • 这对我有用。之后,您应该执行以下操作: var email = report.email.ToString();
【解决方案3】:

如果您将参数从 [FromBody] 设置为动态的,并且如果它是一个 JSON 对象(使用 JSON.stringify 制作),那么您可以使用 .ToString() 来获取字符串值,您应该没问题

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

其他定义为headers: {'Content-Type': 'application/json'},

【讨论】:

    【解决方案4】:

    删除 [FromBody] 属性,它应该可以工作

    【讨论】:

    • 我尝试了公开HttpResponseMessage Post(dynamic data),但它仍然将data显示为null
    猜你喜欢
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多