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