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

Nei*_*ett 7 c# asp.net-mvc json asp.net-mvc-5

我有一个客户端与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是否以不同的方式处理此问题?

有任何想法吗?

例:

application/json:{"FName":"Joe","MName":"M","LName":"Blow"}

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 1

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

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();
Run Code Online (Sandbox Code Playgroud)

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