确定在.NET MVC请求中发送无效的JSON键/值对的时间

8
我有一个客户使用MVC应用程序接收原始JSON请求。ModelBinder将传入的键值对映射到Controller Model属性上,这一点没有问题。
问题是,当他们发送无效的键/值对时,他们想要抛出一个错误,但我却找不到原始输入数据。
例如,如果我的模型有一个字符串属性"MName",但在他们的JSON请求中发送了"MiddleName":"M",ModelBinder将丢弃这个无效的键,并留下"MName"属性为空。这不会引发错误,ModelState.IsValid返回true。
我知道我可以在属性上添加"[Required]"特性,但那也不是正确的方法,因为该属性可能有空值,并且仍然不能解决检测不属于键值对的问题。
这不是过度发布的问题;我不想阻止传入的值绑定到模型。我试图检测传入的值是否未映射到模型中的任何内容。
由于这些值在请求体中以application/json的形式出现,我甚至无法访问、计数或枚举原始请求数据。我可以从ModelState.Keys中获取名称/值对,但这只包括成功映射的字段。这些键中没有一个在Request[]集合中。
是ASP.NET MVC 5,不是WebApi。WebAPI是否处理得有所不同?
有什么建议吗?
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)
    }
}

你如何将JSON反序列化为模型属性?能否请您提供相关代码? - Unbreakable
我要说一些显而易见的话,但你可能想要尝试使用ModelBinders。你也可以将Dictionary<string, string>用作你的操作参数,但这真的很丑:D - Yeldar Kurmangaliyev
我认为ModelState.IsValid不会捕获这种不匹配。你需要在ModelBinder中处理它。我只是一个尝试帮助的新手。我可能完全错了。 - Unbreakable
这是一种不可扩展的肮脏方式。但我只是随口说了一下。 - Unbreakable
也许这可以帮助: https://stackoverflow.com/questions/43215165/custom-validation-mvc-5 - Oleg Tamarintsev
显示剩余2条评论
2个回答

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()将无效属性名称列表和实际模型属性名称列表包含在返回给客户端的错误消息中)。

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 ;
}

我有点困惑。这些代码 person.FName = commingJson.FName; person.LName = commingJson.LName ; 怎么会 抛出异常 呢? - mmushtaq
@mmushtaq 如果即将到来的 JSON 没有 FName 和 LName 属性怎么办?例如 {Name:Rahul,LastName:SR},这只是为了确保我们将要初始化的值与模型匹配。 - RAHUL S R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接