【问题标题】:Handle invalid Body when receiving Post Request in Web Api在 Web Api 中接收 Post 请求时处理无效的 Body
【发布时间】:2019-08-02 23:54:15
【问题描述】:

我有第三方将向我正在制作的 Web Api 服务发送 Post 请求。

我有一个类似的功能

public returnObject PostFromThirdPartyObject(ThirdPartyObject JSONobj)
{
    // Process Object
    return returnObject;
}

当我发送正确的对象时,这工作正常。

问题是当一个无效的对象被发送时,ThirdPartyObject 被空值填充。

我希望能够捕获无效对象,以便记录和诊断问题,因为我不信任第三方规范。

如何处理与预期类型不匹配的 Post 正文?


编辑:用于测试的代码是否需要更改

string body = JsonConvert.SerializeObject(ThirdPartyObject);
var cfReq = (HttpWebRequest)WebRequest.Create(url);
cfReq.ContentType = "application/json";
cfReq.Method = "Post";
cfReq.ContentLength = body.Length;
var byteArray = Encoding.UTF8.GetBytes(body);
var stream = cfReq.GetRequestStream();
stream.Write(byteArray, 0, body.Length);

var httpResponse = (HttpWebResponse)cfReq.GetResponse();
var stringResponse = string.Empty;
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
    stringResponse = streamReader.ReadToEnd();
}

编辑 2:使用对象的解决方法确实很差,希望有人可以发布更正确的方法

public Status PostFromThirdPartyObject([FromBody] object sObject)
{
    ThirdPartyObject obj = null;
    string sRequest = null;
    try
    {
        sRequest = JsonConvert.SerializeObject(sObject);
        LogRequest(sRequest);
        var setting = new JsonSerializerSettings();
        setting.MissingMemberHandling = MissingMemberHandling.Error;
        obj = JsonConvert.DeserializeObject<ThirdPartyObject>(sRequest, setting);
    }
    catch
    {
        if (sObject != null)
        {
            return Error
        }
        else
        {
            return NullError
        }
    }
    return processThirdPartyObject(obj);
}

【问题讨论】:

    标签: c# json post asp.net-web-api


    【解决方案1】:

    尝试使用 ModelState.IsValid():

    public returnObject PostFromThirdPartyObject([FromBody] ThirdPartyObject JSONobj)
    {
        if(!ModelState.IsValid()) {
            // Do someting
        }
        // Process Object
        return returnObject;
    }
    

    【讨论】:

    • 我可以得到这个来告诉我对象是否无效,但这并没有给出传递给服务的实际数据。
    • 您可以使用Request.Content.ReadAsStringAsync()查看无效内容。
    【解决方案2】:

    会有一些不错的选择,但现在,您可以做的是将流作为输入并以字符串形式读取。您拥有您的客户在该字符串中发布的内容。您可以使用 Newtonsoft.Json.JsonConvert 将该字符串反序列化为 ThirdPartyObject,例如 JsonConvert.DeserializeObject&lt;ThirdPartyObject&gt;(inpString)

    你的功能可能是这样的:

    public returnObject PostFromThirdPartyObject(Stream jsonStream)
    {
            string sRequest = String.Empty;
            StreamReader stmRequest = new StreamReader(input, System.Text.Encoding.UTF8);
            sRequest = stmRequest.ReadToEnd();
            ThirdPartyObject obj = null;
    
            try{
                obj = JsonConvert.DeserializeObject<ThirdPartyObject>(sRequest)
               }
            catch
            {
               //you have the object posted by your client in sRequest
               //do whatever you want
            }
    
        // obj is your object to process
        // Process Object
        return returnObject;
    }
    

    您的客户不需要对其进行任何更改。

    【讨论】:

    • 我试过你的解决方案,看起来 jsonSteam 是空的。可能是测试代码,用它编辑了我的帖子。此外,假设“StreamReader(input...”应该是“StreamReader(jsonStream...”
    • 抱歉迟到了。还有那个拼写错误。你的方法是 POST 吗?因为它只适用于 POST
    【解决方案3】:

    要扩展 Shaukat Sarwar 的答案,您可以从 HttpContext 访问正文。

    public returnObject PostFromThirdPartyObject(ThirdPartyObject JSONobj)
    {
        var content = new System.IO.StreamReader(HttpContext.Current.Request.InputStream /*, Encoding here if necessary */)
                        .ReadToEnd();
    
        // Process Object
        return returnObject;
    }
    

    请记住在StreamReader 中使用适当的编码(很可能是UTF8)。

    正如另一个答案所说,您可能还想看看ModelState.IsValid。只需将模型中所有必需的属性标记为[Required](否则ModelState.IsValid 将始终为真)并在那里获取无效请求的原始内容以保存它。

    public returnObject PostFromThirdPartyObject(ThirdPartyObject JSONobj)
    {
        if (!ModelState.IsValid)
        {
            var content = new StreamReader(HttpContext.Current.Request.InputStream /*, Encoding here if necessary */)
                    .ReadToEnd();
    
            // Do something with the raw content here
    
            return BadRequest(ModelState);
        }
    
        // Process Object
        return returnObject;
    }
    

    另请参阅:Model Validation in ASP.NET Web API

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-20
      • 1970-01-01
      • 2022-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-23
      相关资源
      最近更新 更多