MVC 控制器句柄 POSTed JSON 作为字符串
MVC Controller handle POSTed JSON as a string
我有一个第 3 方应用程序 POST 提交到我的网站,正文为 application/json。我可以将强类型对象捕获为:
public string Postback([FromBody]MyResponse myResponse)
我的问题是,在完成这么多工作后,我被指示在同一端点支持第二种类型。因此,我需要接受一个字符串值(而不是模型联编程序的结果),然后 JsonConvert 将字符串转换为 2 种可能类型中的一种或另一种。
所以我认为我应该将方法的签名更改为:
public string Postback([FromBody]string _sfResponse)
但是字符串总是显示为空(有或没有 [FromBody] 指令)。似乎ModelBinder坚持要参与。无论如何说服他不要?
以防万一有关于路由的问题:
routes.MapRoute(
"MyPostback",
url: "rest/V1/sync/update",
defaults: new { controller = "Admin", action = "MyPostback" }
);
控制器动作:
[System.Web.Mvc.HttpPost]
[System.Web.Mvc.AllowAnonymous]
public string MyPostback([System.Web.Http.FromBody][ModelBinder(typeof(MyResponseModelBinder))] MyResponseToProduct _sfResponse)
{
//stuff
}
发送的 json 比平均值更复杂,但请记住,当控制器的签名引用与 json 匹配的强类型对象时,一切正常。 (重复一遍——我必须适应 2 种不同的传入类型,这就是为什么我需要在开头使用字符串而不是模型的原因)。
{
"results": [
{
"errors": {
"error": "No Error"
},
"sku": "70BWUS193045G81",
"status": "success",
"productId": "123"
},
{
"errors": {
"error": "No Error"
},
"sku": "70BWUS193045G82",
"status": "success",
"productId": "123"
}
],
"validationType": "products",
"messageId": "ac5ed64f-2957-51b4-8fbb-838e0480e7ad"
}
我添加了一个自定义模型绑定器,以便能够在控制器被击中之前查看值:
public class MyResponseModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
HttpRequestBase request = controllerContext.HttpContext.Request;
int id = Convert.ToInt32(request.Form.GetValues("Id"));
return new MyResponseToProduct()
{
results = new List<MyResponseToProduct.Result>()
};
}
}
当我检查自定义模型活页夹中的值时,controllerContext.HttpContext.Request.Form 是空的(这是一个 POST 提交,所以主体确实应该在那里,不是吗?)
我可以在bindingContext.PropertyMetadata中看到我的位数据,但我无法想象我应该是去那么深。
很奇怪为什么Request.Form是空的。
ASP.Net核心:
您可以将控制器操作参数声明为 object
,然后对其调用 ToString()
,如下所示:
[HttpPost]
public IActionResult Foo([FromBody] object arg)
{
var str = arg?.ToString();
...
}
在此示例中,str
变量将包含来自请求正文的 JSON 字符串。
ASP.Net MVC:
由于之前的选项在旧的 ASP.Net MVC 中不起作用,作为一个选项,您可以在控制器的操作中直接从 Request
属性 读取数据。以下扩展方法将帮助您:
public static string GetBody(this HttpRequestBase request)
{
var requestStream = request?.InputStream;
requestStream.Seek(0, System.IO.SeekOrigin.Begin);
using (var reader = new StreamReader(requestStream))
{
return reader.ReadToEnd();
}
}
你的动作将是这样的:
[HttpPost]
[Route("test")]
public ActionResult Foo()
{
string json = Request.GetBody();
...
}
我有一个第 3 方应用程序 POST 提交到我的网站,正文为 application/json。我可以将强类型对象捕获为:
public string Postback([FromBody]MyResponse myResponse)
我的问题是,在完成这么多工作后,我被指示在同一端点支持第二种类型。因此,我需要接受一个字符串值(而不是模型联编程序的结果),然后 JsonConvert 将字符串转换为 2 种可能类型中的一种或另一种。
所以我认为我应该将方法的签名更改为:
public string Postback([FromBody]string _sfResponse)
但是字符串总是显示为空(有或没有 [FromBody] 指令)。似乎ModelBinder坚持要参与。无论如何说服他不要?
以防万一有关于路由的问题:
routes.MapRoute(
"MyPostback",
url: "rest/V1/sync/update",
defaults: new { controller = "Admin", action = "MyPostback" }
);
控制器动作:
[System.Web.Mvc.HttpPost]
[System.Web.Mvc.AllowAnonymous]
public string MyPostback([System.Web.Http.FromBody][ModelBinder(typeof(MyResponseModelBinder))] MyResponseToProduct _sfResponse)
{
//stuff
}
发送的 json 比平均值更复杂,但请记住,当控制器的签名引用与 json 匹配的强类型对象时,一切正常。 (重复一遍——我必须适应 2 种不同的传入类型,这就是为什么我需要在开头使用字符串而不是模型的原因)。
{
"results": [
{
"errors": {
"error": "No Error"
},
"sku": "70BWUS193045G81",
"status": "success",
"productId": "123"
},
{
"errors": {
"error": "No Error"
},
"sku": "70BWUS193045G82",
"status": "success",
"productId": "123"
}
],
"validationType": "products",
"messageId": "ac5ed64f-2957-51b4-8fbb-838e0480e7ad"
}
我添加了一个自定义模型绑定器,以便能够在控制器被击中之前查看值:
public class MyResponseModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
HttpRequestBase request = controllerContext.HttpContext.Request;
int id = Convert.ToInt32(request.Form.GetValues("Id"));
return new MyResponseToProduct()
{
results = new List<MyResponseToProduct.Result>()
};
}
}
当我检查自定义模型活页夹中的值时,controllerContext.HttpContext.Request.Form 是空的(这是一个 POST 提交,所以主体确实应该在那里,不是吗?)
我可以在bindingContext.PropertyMetadata中看到我的位数据,但我无法想象我应该是去那么深。
很奇怪为什么Request.Form是空的。
ASP.Net核心:
您可以将控制器操作参数声明为 object
,然后对其调用 ToString()
,如下所示:
[HttpPost]
public IActionResult Foo([FromBody] object arg)
{
var str = arg?.ToString();
...
}
在此示例中,str
变量将包含来自请求正文的 JSON 字符串。
ASP.Net MVC:
由于之前的选项在旧的 ASP.Net MVC 中不起作用,作为一个选项,您可以在控制器的操作中直接从 Request
属性 读取数据。以下扩展方法将帮助您:
public static string GetBody(this HttpRequestBase request)
{
var requestStream = request?.InputStream;
requestStream.Seek(0, System.IO.SeekOrigin.Begin);
using (var reader = new StreamReader(requestStream))
{
return reader.ReadToEnd();
}
}
你的动作将是这样的:
[HttpPost]
[Route("test")]
public ActionResult Foo()
{
string json = Request.GetBody();
...
}