Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET核心MVC:如何将原始JSON绑定到没有类型的字符串?_C#_Asp.net Mvc_Asp.net Web Api_Asp.net Core Mvc - Fatal编程技术网

C# ASP.NET核心MVC:如何将原始JSON绑定到没有类型的字符串?

C# ASP.NET核心MVC:如何将原始JSON绑定到没有类型的字符串?,c#,asp.net-mvc,asp.net-web-api,asp.net-core-mvc,C#,Asp.net Mvc,Asp.net Web Api,Asp.net Core Mvc,与以前关于ASP.NET版本的老问题类似,我希望将HTTP POST的请求主体绑定到字符串。似乎该方法已绑定,但当ASP.NET调用我的控制器方法时,value为空: namespace Demo.Controllers { [Route("[controller]")] public class WebApiDemoController : Controller { ... // POST api/values [HttpPost]

与以前关于ASP.NET版本的老问题类似,我希望将HTTP POST的请求主体绑定到字符串。似乎该方法已绑定,但当ASP.NET调用我的控制器方法时,
value
为空:

namespace Demo.Controllers
{

    [Route("[controller]")]
    public class WebApiDemoController : Controller
    {
    ...

    // POST api/values
    [HttpPost]
    public System.Net.Http.HttpResponseMessage Post([FromBody]string value)
    {
       // expected: value = json string, actual: json = null.
    }
我还要去小溪里抓尸体吗?还是应该这样做?在测试上述方法时,我使用了以下http头:

Accept: Application/json
Content-Type: Application/json;charset=UTF-8
我在正文中传递以下内容:
{“a”:1}

我不想绑定到名为a的字符串变量。我想绑定我得到的任何JSON,然后我想在我的方法中使用JSON内容,任何任意内容

如果我理解了文档,那么
[FromBody]
属性应该已经实现了我想要的功能,但是我猜ASP.NET核心MVC绑定机制不会将json绑定到“字符串值”,但也许我可以做一些其他的事情来获得同等的灵活性

类似的问题让我想到,也许我应该编写
[FromBody]动态数据
,而不是使用
[FromBody]字符串值


更新:在做之前应该考虑这种技巧,因为如果您想让.NETCore框架为您处理JSON和XML编码,您只需取消该功能。某些类型的REST服务器可以而且经常需要同时支持XML和JSON内容类型,至少我遇到过有标准文档的内容类型。

您需要一个类型来绑定数据。例如:

public class Person
{
   public string Name {get; set;}
}

对于数据
{“Name”:“James”}

如果要接收字符串,则需要将其作为字符串传递。您的
JSON
应该用引号括起来:

'{ "a": 1 }'

以下内容适用于.NETCore1.x,但不适用于.NETCore2.x

正如我所评论的,解决方案是使用
[FromBody]动态数据
作为我的参数列表,使用
动态
而不是
字符串
,我将收到一个
作业对象

警告:如果您的体系结构要求单个WebApi服务器能够同样流畅地生成XML和JSON,这取决于内容类型头条目,那么这种直接JSON使用策略可能会适得其反。(在同一个服务上同时支持XML和JSON是有可能的,只要做足够的工作,但随后您将把MVC资产管道上的东西向下移动到您的控制器方法中,这与MVC的精神背道而驰,在MVC中,模型已经被解析为POCO了。)

在方法内转换为字符串后,将传入的
JObject
(用于JSON的Newtonsoft.JSON内存中数据类型)转换为字符串

在找到

示例代码,感谢Jeson Martajaya:

使用动态:

[HttpPost]
public System.Net.Http.HttpResponseMessage Post([FromBody]dynamic value)
{
   //...
}
JObject的示例代码:

[HttpPost]
public System.Net.Http.HttpResponseMessage Post([FromBody]Newtonsoft.Json.Linq.JObject value)
{
   //...
}

或者,您也可以只接受一个
JObject
,如果您真的需要字符串,您甚至可以直接使用Linq to Json ot
ToString()

我看到Sam已经因为说了几乎相同的话而被否决了,但是在使用Postman进行测试时,我发现如果我将请求主体设置为一个简单的双引号字符串,ASP就可以使用默认的“[FromBody]string value”参数将其绑定

"just send your string like this without any curly braces"

不确定应用程序/json是否应该接受此格式的数据。希望通过发布这篇文章,有见识的人会滔滔不绝地说明这是否有效。

我发现最干净的选择是添加您自己的简单InputFormatter:

public class RawJsonBodyInputFormatter : InputFormatter
{
    public RawJsonBodyInputFormatter()
    {
        this.SupportedMediaTypes.Add("application/json");
    }

    public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
    {
        var request = context.HttpContext.Request;
        using (var reader = new StreamReader(request.Body))
        {
            var content = await reader.ReadToEndAsync();
            return await InputFormatterResult.SuccessAsync(content);
        }
    }

    protected override bool CanReadType(Type type)
    {
        return type == typeof(string);
    }
}
这将让您获得控制器中的原始JSON负载:

[HttpPost]
public IActionResult Post([FromBody]string value)
{
    // value will be the request json payload
}

以下两种方法在ASP.NET core 2中用于读取原始json字符串

1) 这个有更好的性能

    [HttpPost]
    public async Task<ActionResult<int>> Process()
    {
        string jsonString;
        using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
        {
            jsonString = await reader.ReadToEndAsync();
        }
[HttpPost]
公共异步任务进程()
{
字符串jsonString;
使用(StreamReader=newstreamreader(Request.Body,Encoding.UTF8))
{
jsonString=await reader.ReadToEndAsync();
}
(二)

[HttpPost]
公共异步任务进程([FromBody]JToken jsonbody)
{
var jsonString=jsonBody.ToString();

基于以上Saeb Amini的出色回答,这扩展了他的解决方案,也适用于纯文本。这里唯一的更改是添加
“text/plain”
mime类型,并使用
s添加
名称空间
和必需的

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Formatters;

namespace AspExtensions // or whatever
{
    // see: https://stackoverflow.com/a/47807117/264031
    public class RawStringBodyInputFormatter : InputFormatter
    {
        public RawStringBodyInputFormatter()
        {
            this.SupportedMediaTypes.Add("text/plain");
            this.SupportedMediaTypes.Add("application/json");
        }

        public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
        {
            var request = context.HttpContext.Request;
            using(var reader = new StreamReader(request.Body)) {
                string content = await reader.ReadToEndAsync();
                return await InputFormatterResult.SuccessAsync(content);
            }
        }

        protected override bool CanReadType(Type type)
        {
            return type == typeof(string);
        }
    }
}
使用系统;
使用System.IO;
使用System.Threading.Tasks;
使用Microsoft.AspNetCore.Mvc.Formatters;
名称空间AspExtensions//或其他名称空间
{
//见:https://stackoverflow.com/a/47807117/264031
公共类RawStringBodyInputFormatter:InputFormatter
{
公共RawStringBodyInputFormatter()
{
此.SupportedMediaTypes.Add(“text/plain”);
this.SupportedMediaTypes.Add(“application/json”);
}
公共重写异步任务ReadRequestBodyAsync(InputFormatterContext上下文)
{
var request=context.HttpContext.request;
使用(var reader=newstreamreader(request.Body)){
string content=wait reader.ReadToEndAsync();
返回等待InputFormatterResult.SuccessAsync(内容);
}
}
受保护的覆盖布尔CanReadType(类型)
{
返回类型==typeof(字符串);
}
}
}

找到了ASP.NET Core 3.1 Web API的解决方案

如下所示:

public async Task<IActionResult> PutAsync([FromBody] System.Text.Json.JsonElement entity)
{ 
    // your code here
}
public async Task PutAsync([FromBody]System.Text.Json.JsonElement entity)
{ 
//你的代码在这里
}

如果您不放弃automagic绑定,可以将其直接放置在控制器上的Http处理程序中:

using StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8);
var value = reader.ReadToEndAsync().GetAwaiter().GetResult();

您是否已检查请求正文中是否确实传递了任何内容?Fiddler?刚刚检查了Fiddler,正文内容很好。您传递的名称/对值
a:1
,因此参数必须是
字符串a
(假设您的
public async Task<IActionResult> PutAsync([FromBody] System.Text.Json.JsonElement entity)
{ 
    // your code here
}
using StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8);
var value = reader.ReadToEndAsync().GetAwaiter().GetResult();