C# ASP.NET核心无法读取请求正文
我已经在ASP.NET核心上工作了几个星期。我试图通过这个博客实现一些东西: 我的C# ASP.NET核心无法读取请求正文,c#,asp.net-core,asp.net-core-mvc,asp.net-core-1.0,C#,Asp.net Core,Asp.net Core Mvc,Asp.net Core 1.0,我已经在ASP.NET核心上工作了几个星期。我试图通过这个博客实现一些东西: 我的project.json如下: { "version": "1.0.0-*", "compilationOptions": { "emitEntryPoint": true }, "dependencies": { "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final", "Microsoft.AspNet.Se
project.json
如下:
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
"Microsoft.AspNet.Diagnostics": "1.0.0-rc1-*",
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
"EntityFramework.Core": "7.0.0-rc1-final",
"EntityFramework.Commands": "7.0.0-rc1-final",
"EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
"EntityFramework.MicrosoftSqlServer.Design": "7.0.0-rc1-final",
"Microsoft.AspNet.Mvc.Formatters.Json": "6.0.0-rc1-final",
"Microsoft.AspNet.Mvc.Formatters.Xml": "6.0.0-rc1-final",
"System.Security.Cryptography.Algorithms": "4.0.0-beta-23516"
},
"commands": {
"web": "Microsoft.AspNet.Server.Kestrel",
"ef": "EntityFramework.Commands"
},
"frameworks": {
"dnxcore50": {
"dependencies": {
}
}
},
"exclude": [
"wwwroot",
"node_modules"
],
"publishExclude": [
"**.user",
"**.vspscc"
]
}
public void ConfigureServices(IServiceCollection services)
{
//Registering Authorization Database
AutorizationAccessRegisteration.RegisterComponents(services, Configuration);
services.AddMvcCore()
.AddJsonFormatters(a => a.ContractResolver = new CamelCasePropertyNamesContractResolver());
//Add cors built in support.
services.AddCors();
services.AddMvcCore().AddApiExplorer();
//Add MVC for supporting WebApi requests
#region MVC Add
services.AddMvc();
services.AddMvc().AddMvcOptions(options =>
{
options.RespectBrowserAcceptHeader = true;
// Input Formatters.
options.InputFormatters.Clear();
var jsonInputFormatter = new JsonInputFormatter()
{
SerializerSettings = new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
,
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
NullValueHandling = NullValueHandling.Ignore
}
};
options.InputFormatters.Add(jsonInputFormatter);
//Output formater
//as part of get/post request, set the header Accept = application/json or application/xml
var jsonOutputFormatter = new JsonOutputFormatter();
jsonOutputFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
jsonOutputFormatter.SerializerSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore;
options.OutputFormatters.Insert(0, jsonOutputFormatter);
options.OutputFormatters.Insert(1, new XmlDataContractSerializerOutputFormatter());
});
#endregion
}
[Route("api/Authorization")]
public class AuthorizationController : Controller
{
.
[HttpPost]
public void Post([FromBody]string value)
{
}
.
}
和Startup.cs
中的ConfigureServices
方法如下:
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
"Microsoft.AspNet.Diagnostics": "1.0.0-rc1-*",
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
"EntityFramework.Core": "7.0.0-rc1-final",
"EntityFramework.Commands": "7.0.0-rc1-final",
"EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
"EntityFramework.MicrosoftSqlServer.Design": "7.0.0-rc1-final",
"Microsoft.AspNet.Mvc.Formatters.Json": "6.0.0-rc1-final",
"Microsoft.AspNet.Mvc.Formatters.Xml": "6.0.0-rc1-final",
"System.Security.Cryptography.Algorithms": "4.0.0-beta-23516"
},
"commands": {
"web": "Microsoft.AspNet.Server.Kestrel",
"ef": "EntityFramework.Commands"
},
"frameworks": {
"dnxcore50": {
"dependencies": {
}
}
},
"exclude": [
"wwwroot",
"node_modules"
],
"publishExclude": [
"**.user",
"**.vspscc"
]
}
public void ConfigureServices(IServiceCollection services)
{
//Registering Authorization Database
AutorizationAccessRegisteration.RegisterComponents(services, Configuration);
services.AddMvcCore()
.AddJsonFormatters(a => a.ContractResolver = new CamelCasePropertyNamesContractResolver());
//Add cors built in support.
services.AddCors();
services.AddMvcCore().AddApiExplorer();
//Add MVC for supporting WebApi requests
#region MVC Add
services.AddMvc();
services.AddMvc().AddMvcOptions(options =>
{
options.RespectBrowserAcceptHeader = true;
// Input Formatters.
options.InputFormatters.Clear();
var jsonInputFormatter = new JsonInputFormatter()
{
SerializerSettings = new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
,
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
NullValueHandling = NullValueHandling.Ignore
}
};
options.InputFormatters.Add(jsonInputFormatter);
//Output formater
//as part of get/post request, set the header Accept = application/json or application/xml
var jsonOutputFormatter = new JsonOutputFormatter();
jsonOutputFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
jsonOutputFormatter.SerializerSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore;
options.OutputFormatters.Insert(0, jsonOutputFormatter);
options.OutputFormatters.Insert(1, new XmlDataContractSerializerOutputFormatter());
});
#endregion
}
[Route("api/Authorization")]
public class AuthorizationController : Controller
{
.
[HttpPost]
public void Post([FromBody]string value)
{
}
.
}
下面是我在Startup.cs中的confure
方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
}
else if (env.IsStaging())
{
}
else if (env.IsProduction())
{
}
app.UseIISPlatformHandler();
app.UseCors(builder =>
builder.WithOrigins("*").AllowAnyHeader().AllowAnyMethod());
//Middlewares addition to the pipelines:
/// We add the middlewares in the following fashion:
/// - Exception Handler
/// - Logger
/// - Authorization Handler
/// There is a big reason of doing that.
///
app.UseExceptionHandler();
app.UseLoggerHandler();
app.UseAuthorizationHandler();
app.UseMvc();
}
授权控制器如下所示:
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
"Microsoft.AspNet.Diagnostics": "1.0.0-rc1-*",
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
"EntityFramework.Core": "7.0.0-rc1-final",
"EntityFramework.Commands": "7.0.0-rc1-final",
"EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
"EntityFramework.MicrosoftSqlServer.Design": "7.0.0-rc1-final",
"Microsoft.AspNet.Mvc.Formatters.Json": "6.0.0-rc1-final",
"Microsoft.AspNet.Mvc.Formatters.Xml": "6.0.0-rc1-final",
"System.Security.Cryptography.Algorithms": "4.0.0-beta-23516"
},
"commands": {
"web": "Microsoft.AspNet.Server.Kestrel",
"ef": "EntityFramework.Commands"
},
"frameworks": {
"dnxcore50": {
"dependencies": {
}
}
},
"exclude": [
"wwwroot",
"node_modules"
],
"publishExclude": [
"**.user",
"**.vspscc"
]
}
public void ConfigureServices(IServiceCollection services)
{
//Registering Authorization Database
AutorizationAccessRegisteration.RegisterComponents(services, Configuration);
services.AddMvcCore()
.AddJsonFormatters(a => a.ContractResolver = new CamelCasePropertyNamesContractResolver());
//Add cors built in support.
services.AddCors();
services.AddMvcCore().AddApiExplorer();
//Add MVC for supporting WebApi requests
#region MVC Add
services.AddMvc();
services.AddMvc().AddMvcOptions(options =>
{
options.RespectBrowserAcceptHeader = true;
// Input Formatters.
options.InputFormatters.Clear();
var jsonInputFormatter = new JsonInputFormatter()
{
SerializerSettings = new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
,
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
NullValueHandling = NullValueHandling.Ignore
}
};
options.InputFormatters.Add(jsonInputFormatter);
//Output formater
//as part of get/post request, set the header Accept = application/json or application/xml
var jsonOutputFormatter = new JsonOutputFormatter();
jsonOutputFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
jsonOutputFormatter.SerializerSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore;
options.OutputFormatters.Insert(0, jsonOutputFormatter);
options.OutputFormatters.Insert(1, new XmlDataContractSerializerOutputFormatter());
});
#endregion
}
[Route("api/Authorization")]
public class AuthorizationController : Controller
{
.
[HttpPost]
public void Post([FromBody]string value)
{
}
.
}
Post
方法最初具有[FromBody]字符串[]值。我进一步简化了它,使之成为一个简单的string
类型。我正在使用Chrome上的AdvanceREST客户端发送一个HTTP请求
。当string[]
为类型时,I为正文中的以下值:
{
["value","sdjklgsdjlg"]
}
简化参数后,我尝试使用以下主体发送请求:
{"sdjklgsdjlg"}
我也试过:
{"value":"sdjklgsdjlg"}
我错过什么了吗?我以前读过,旧的WebApi在JSON映射到复杂对象和普通参数时的工作方式,它在.NETCore中的工作方式类似
我还应该详细说明,断点通常在所有中间件和控制器上被命中。但似乎没有一个中间件能够读取请求的流相关内容:
请告诉我哪里出了问题。非常感谢 [FromBody]
使用注册的格式化程序将提交的数据的整个正文解码为它应用到的单个参数-默认情况下,唯一注册的格式化程序接受JSON
在JSON中,没有有效的方法直接表示字符串-{“sdjklgsdjlg”}
不是有效的JSON,{“value”:“sdjklgsdjlg”}
是,但不会反序列化为简单的字符串参数编辑:查看@tmg的答案,可以使用语法{”“:“sdjklgsdjlg”}
因此,您需要某种特定的模型类来表示您试图从主体中获取的输入,例如:
public class AuthRequest {
public string Value { get; set; }
}
然后您应该能够成功地执行以下操作:
[Route("api/Authorization")]
public class AuthorizationController : Controller
{
[HttpPost]
public void Post([FromBody]AuthRequest authReq)
{
// authReq.Value should have your value in
}
}
现在,如果您将{“Value”:“some Value”}
发布到此,它应该会做您期望的事情。您也可以这样做:
[HttpPost]
public System.Net.Http.HttpResponseMessage Post([FromBody]dynamic value)
{
//...
}
或者用户[FromQuery]
并直接传递查询字符串值。Mark Hughes的答案在某一点之前是正确的。如果发布这种格式的json,modelbinder应该能够将其绑定到简单的字符串模型,而不需要包装器模型。您应该使用所有依赖项的RC2版本。
我发现System.Threading.Tasks.Extensions的默认版本是4.0.0。因此,您应该在project.json文件中明确指定此包的版本:
"System.Threading.Tasks.Extensions": "4.0.0-rc2-24027"
我在这里迟到了,但我想与大家分享确切的原因,以便任何其他用户都能获得准确的信息
您无法在控制器上获取值,因为您正在将数据发布为JSON对象:
{"value":"sdjklgsdjlg"} //See the curly braces represent an object.
为了解决这个问题,我们需要另一个对象来绑定这个数据。在控制器的操作中,类似于以下内容:
[HttpPost]
public void Post([FromBody]CustomViewModel data)
{
...
//here you can get value as: data.Value
}
这里CustomViewModel是一个类:
public CustomViewModel
{
public string Value { get; set; }
}
如果您希望按照当前操作签名获取数据:
[HttpPost]
public void Post([FromBody]string value)
{
...
}
然后,您需要在请求正文中以JSON字符串的形式传递数据:
"sdjklgsdjlg" //notice without any curly braces and property name
["item1", "item2"]
与字符串数组操作类似:
[HttpPost]
public void Post([FromBody]IEnumerable<string> values)
{
...
}
这对我很有用:
[HttpPost]
public async Task<IActionResult> CreateApp([FromQuery]string userId)
{
string appDefinition = await new StreamReader(Request.Body).ReadToEndAsync();
var newAppJson = JObject.Parse(appDefinition);
...
[HttpPost]
公共异步任务CreateApp([FromQuery]字符串用户ID)
{
string appDefinition=等待新的StreamReader(Request.Body).ReadToEndAsync();
var newAppJson=JObject.Parse(appDefinition);
...
你的网络嗅探器对此有何评论?你能粘贴http会话的捕获吗?你能粘贴整个错误消息吗?你的意思是什么?我正在使用Advance Rest客户端。它显示正确的请求头和原始正文,正如我上面提到的。你在没有[FromBody]的情况下尝试过吗?我想如果没有它,它会工作的。我以前试过,现在又试过。但是你不认为如果值没有显示在控制器中,那么这个[FromBody]
可能是出了问题。但事实并非如此。我发布了两张图片,这是我的第一个例外Middleware,您可以看到请求的主体和表单变量中出现了哪些错误。您添加了两次MVC,这正常吗?MvcCore也添加了两次。这在我使用的旧WebApi 2控制器中看起来很奇怪n使用接受字符串FromQuery
,但在这里也不起作用。您的DTO技巧确实允许我从请求中获取要映射到我的方法的值。但我仍然无法读取请求。正文和其他涉及上下文的内容。@FreshDev您仍然可以使用[FromQuery]执行此操作对于查询参数-只是不用于正文绑定-如果您请求api/Authorization?value=horse
,则使用[FromQuery]字符串值
应该正确解析。感谢@mark hughes,我为此苦苦挣扎了一段时间,解释得很好。我知道DTO的事情。正如mark hughes所说的那样。你能告诉我为什么我不能读取请求正文吗?在中间件中?哦,我不知道@tmg-有趣!你发送了什么正文ng?无论如何,我谦恭地建议您简化配置:您连续添加了4次MVC,我不知道当您多次添加时会发生什么。您还添加了两次Cors。我尝试了各种主体。但无法使任何一种都起作用。即使是最简单的配置,例如:{“value”:“someValue”}
我想以原始(字节)读取它表单,然后将其转换为字符串。但是连接到流的属性都不可用。正如你所说,我多次添加MVC。事实并非如此。我们必须在ConfigureServices
方法中注册服务,然后在Configure
方法中使用它们。这正是我正在做的。如果你完全看不到内容我给你的建议是简单化。删除所有你不需要的东西,没有身份验证,没有cors。简单化。你也可以尝试用visual stu创建一个演示应用程序