【问题标题】:IdentityServer4.Models.Client as httppost parameter always null in aspnet core 2.xIdentityServer4.Models.Client 作为 httppost 参数在 aspnet core 2.x 中始终为空
【发布时间】:2018-07-10 03:58:58
【问题描述】:

我通过 C# 控制台应用程序将 IdentityServer4.Models.Client 类型的 httpPost 参数“client”发送到 C# web api,client 始终为 null

如果我使用相同的代码发送不同的对象,则可以正常接收参数。这似乎是 Identity Server 4 特有的问题,我不知道发生了什么。

服务器代码:

[HttpPost]        
public JsonResult Post(IdentityServer4.Models.Client client){   

    return Json(new { result = true });
}

客户端代码:

private static async Task Register(string clientName){

        var controllerName = "BasicClient";             
        var basicClientApi = string.Format("http://localhost:5100/api/{0}", controllerName);
        using (var httpClient = new HttpClient()){

            var clientData = new IdentityServer4.Models.Client();
            var client = new { client = clientData };
            client.client.ClientName = clientName;

            var json = JsonConvert.SerializeObject(client);
            var content = new StringContent(json, Encoding.UTF8, "application/json");
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");


            var response = await httpClient.PostAsync(basicClientApi, content);

            if (!response.IsSuccessStatusCode)
            {
                Console.WriteLine(response.StatusCode);
            }
            else
            {
                var rawResponse = await response.Content.ReadAsStringAsync();

                JObject o = JObject.Parse(rawResponse);
                Console.WriteLine(o.ToString());
            }
        }
    }

编辑 应用 [FromBody] 并解包对象后,我仍然在接收 Web API 中为客户端获取 null。不过,有一件事引起了我对控制台应用程序调试屏幕的注意。请参见下图:

实际的客户端变量在控制台应用程序中为空,但 JsonConvert 能够将其序列化为某种东西。这是关于什么的?

【问题讨论】:

  • client = new { client = clientData }; - 为什么要将模型包装在匿名对象中?您只需序列化您的 Client 对象,无需任何包装。
  • @FedericoDipuma 我完全错过了。包装将是一个问题。你应该把它作为答案。

标签: c# asp.net-core identityserver4 asp.net-core-webapi


【解决方案1】:

您将模型包装在一个匿名对象中,这会将其 JSON 表示转换为与您原来的 Client 类没有任何共同之处的东西。

这个:

var clientData = new IdentityServer4.Models.Client();
var client = new { client = clientData };
client.client.ClientName = clientName;

var json = JsonConvert.SerializeObject(client);

将产生类似于以下内容的 JSON:

{
    "client": { 
        "clientName": "foo",
        "anotherProperty": "bar",
        // other properties omitted for brevity
    }
}

但你真正想要的只是 Client 对象:

{ 
    "clientName": "foo",
    "anotherProperty": "bar",
    // other properties omitted for brevity
}

不要包装你的clientData,直接序列化它以遵循你的MVC动作方法中的模型:

var clientData = new IdentityServer4.Models.Client();
clientData.ClientName = clientName;

var json = JsonConvert.SerializeObject(clientData);

为了让一切正常工作,您必须明确告诉模型绑定器在哪里期望数据。

在模型上使用[FromBody] 属性。

[FromBody]:使用配置的格式化程序绑定请求正文中的数据。根据请求的内容类型选择格式化程序。

[HttpPost]        
public IActionResult Post([FromBody]IdentityServer4.Models.Client client) {

    return Json(new { result = true });
}

参考Model Binding in ASP.NET Core

【讨论】:

  • 我已经应用了上述更改,但我仍然遇到问题。客户端为空。我也会附上一些屏幕截图。
  • 我刚刚发现我的包引用版本不匹配...
  • 我已经让两个项目都使用 2.2.0 版本,我运行了 nuget locals all -clear 和 dotnet restore...但是当我在类型上按 f12 时,它仍然显示旧的被引用我的网络 API。为什么不引用较新版本的 IS4?
  • 我不相信 nuget 版本会改变您的场景中的任何东西。另外,我不明白您的调试窗口,您如何在 ASP.NET Core 控制器中获取 json 变量?
  • 这是控制台应用程序项目中的监视窗口,而不是带有 web api Controller 的项目。在这一点上,我几乎可以肯定它与跨项目的不同版本的 Client.cs 有关,因为我遵循了上述建议,但我仍然遇到问题。看起来 Web API 项目包含一个 EF 项目作为参考,而 EF 项目使用 IdentityServer4.EntityFramework,我认为这是旧 Client.cs 所在的位置
【解决方案2】:

您不会相信这一点,但最终 IdentityServer.Models.Client 在 Web Api post 参数中为空的原因是因为该类是用 [DebuggerDisplay("{ClientId}")] 装饰的,而我做到了没有在我的测试应用程序中提供 ClientId,所以它总是显示为 null,而实际上它实际上一直都在那里。我很高兴这个问题已经过去了,但我对这个“功能”感到非常愤怒。

【讨论】:

    猜你喜欢
    • 2019-09-09
    • 2019-09-30
    • 2020-02-28
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 2014-12-09
    • 2016-11-22
    • 2017-06-07
    相关资源
    最近更新 更多