确定在.NET MVC请求中何时发送无效的JSON密钥/值对

时间:2017-07-28 03:29:46

标签: c# json asp.net-mvc asp.net-mvc-5

我有一个客户端,其MVC应用程序接受原始JSON请求。 ModelBinder将传入的键/值对映射到Controller Model属性,没有问题。

问题是他们想要在发送无效的键/值对时抛出错误,并且在我的生命中我无法找到原始传入数据。

例如,如果我有一个带有字符串属性MName的模型,但是在他们发送"MiddleName":"M"的JSON请求中,ModelBinder将抛出此无效密钥并将MName属性留空。这不会引发错误,ModelState.IsValid会返回true

我知道我可以在属性上抛出[Required]属性,但这也不对,因为该属性可能有空值,但仍然无法访问检测不属于的键/值对的问题。

这不是一个过度发布的问题;我并没有试图阻止传入的值绑定到模型。我试图检测传入的值何时没有映射到模型中的任何内容。

由于这些值是作为application / json在请求体中出现的,我甚至没有运气,甚至没有运气计数或枚举原始请求数据。我可以从ModelState.Keys中提取名称/值对,但只包括已成功映射的字段。这些密钥都不在Request[]集合中。

是的,这是在ASP.NET MVC 5中,而不是WebApi。 WebAPI是否以不同的方式处理这个问题?

有什么想法吗?

示例:

应用/ JSON:     {     " FName参数":"乔&#34 ;,     " MNAME":" M&#34 ;,     " LName的":"吹塑"     }

public class PersonModel
{
    public string FName { get; set; }
    public string LName { get; set; }
}

public class PersonController() : Controller
{
    public ActionResult Save(PersonModel person)
    {
        if(ModelState.IsValid) // returns true
        // do things
        return View(person)
    }
}

2 个答案:

答案 0 :(得分:1)

您可以读取Request.InputStream请求中发送的json数据并反序列化到对象。然后,您可以将发布的属性名称与模型的属性名称进行比较

public ActionResult Save(PersonModel person)
{
    // Get the models property names
    var modelProperties = person.GetType().GetProperties().Select(x => x.Name);
   // Read the InputStream
    StreamReader reader = new StreamReader(Request.InputStream);
    reader.BaseStream.Position = 0;
    string jsonText = reader.ReadToEnd();
    // Deserialize to object and read property names
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    object jsonObject = serializer.DeserializeObject(jsonText);
    IDictionary<string, object> dictionary = jsonObject as IDictionary<string, object>;
    var jsonProperties = jsonObject.Keys;
    // Get the json property names which do not match the model property names
    List<string> invalidProperties = jsonProperties.Except(modelProperties, StringComparer.OrdinalIgnoreCase).ToList();

如果invalidProperties包含值,那么您可以抛出错误(并且可能使用String.Join()在错误消息中包含无效属性名称列表和实际模型属性名称列表回到客户端)。

答案 1 :(得分:0)

你可以试试像

这样的东西
  public ActionResult Save(object commingJson)
    {
         PersonModel person = new PersonModel();
          try{
           person.FName = commingJson.FName;
           person.LName = commingJson.LName ;
           }
          catch(Exception)
           {
             //Binding Failed invalid json
            }

         int countInObject = GetAttrCount(commingJson);
         int countInModel = GetAttrCount(person);
              if(countInObject != countInModel )
             {
               //Json have more or less value then model  
             }
        if(ModelState.IsValid) // returns true
        // do things
        return View(person)
    }



   public int GetAttrCount(obecjct countObject) 
{
    Type type = typeof(countObject);
    int attributeCount = 0;
    foreach(PropertyInfo property in type.GetProperties())
    {
     attributeCount += property.GetCustomAttributes(false).Length;
    }
return attributeCount ;
}