2017-02-06 14 views
0

Я пытаюсь остановить мой REST API, принимающий недействительные тела json в моем контроллере.Контроллер .NET MVC, принимающий недопустимый json

У меня есть REST API, который имеет конечную точку .NET MVC. На этой конечной точке мы имеем метод поста, который принимает тело типа клиента (в основном упрощенного в данном примере), класс для него следующим образом:

public class Customer 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public List<Address> Addresses { get; set; } 
    public List<Xref> Xrefs { get; set; } 
} 

public class Address 
{ 
    public string AddressLineOne { get; set; } 
    public string AddressLineTwo { get; set; } 
} 

public class Xref 
{ 
    public string System { get; set; } 
    public List<Segment> Segments { get; set; } 

} 

public class Segment 
{ 
    public string Name { get; set; } 
    public string Value { get; set; } 
} 

И метод для контроллера заключается в следующем:

[HttpPost] 
public async Task<IHttpActionResult> Post([FromBody]Customer customer) 
{ 
... 
} 

действительное Представление JSON тела следующим образом:

{ 
"FirstName": "firstName", 
"LastName": "lastName", 
"Addresses": 
[ 
    { 
     "AddressLineOne" : "addressLineOne", 
     "AddressLineTwo" : "addressLineTwo" 
    } 
], 
"Xrefs":[ 
    { 
     "System":"systemOne", 
     "Segments":[ 
      { 
       "Name":"name", 
       "Value":"value" 
      } 
     ] 
    } 
] 
} 

Я заметил, что если я делаю запрос к API с недостоверным JSON, контроллер запрос еще прн евы тело и будет игнорировать все после неправильной секции. Пример такого представления является ниже, где внешними ссылки не имеют закрывающую фигурную скобку:

{ 
"FirstName": "firstName", 
"LastName": "lastName", 

"Xrefs":[ 
    { 
     "System":"systemOne", 
     "Segments":[ 
      { 
       "Name":"name", 
       "Value":"value" 
      } 

     ] 

, 
"Addresses": 
[ 
    { 
     "AddressLineOne" : "addressLineOne", 
     "AddressLineTwo" : "addressLineTwo" 
    } 
], 
} 

Что происходит, когда эти данные размещен на контроллер, что объект клиента будет содержать Firstname, фамилию и внешнюю ссылку, но не будет содержать адрес. Это связано с тем, что в соответствии с иерархией json мы все еще находимся в xref и не закрыли его.

При создании модульного теста для этой функции и при попытке DeserializeObject вы сталкиваетесь с исключением JsonSerializationException, но это не происходит в методе контроллера.

Теперь я пытаюсь найти способ остановить недействительный json, принимаемый в контроллере. Я не хочу частично десериализовать json в любой форме, либо json действителен, либо нет. Я подумал о создании фильтра проверки и добавлении его в HttpConfig, этот фильтр будет использовать отражение, чтобы выяснить, как должен выглядеть предполагаемый объект запроса, затем он попытается десериализовать тело в него, если исключение будет запрос не пройдет.

Я позаботился об этом, потому что я предполагаю, что есть более простой и менее ресурсоемкий способ сделать это, встроенный в MVC, такой как флаг, чтобы разрешить неполное тело json, но я не смог его найти. Я также неохотно делаю это в фильтрах, так как это будет чрезвычайно ресурсоемким, чтобы фильтровать каждый запрос, подобный этому, тем более, что отражение очень облагается налогом, и мы ловим исключение, чтобы попытаться проверить. Этот фильтр был бы прекрасен в небольшом MVC API, но для этой системы требуется крайне малое время отклика.

Если вы знаете какие-либо лучшие решения, пожалуйста, дайте мне знать.

Благодаря

+0

Использование JSON Schema, см HTTP: // WWW .newtonsoft.com/jsonschema –

+0

и настраиваемое связующее устройство, в котором вы можете проверить JSON –

+0

или использовать пользовательскую строку ... вы получите строку JSON, проверите и преобразуете json в желаемый объект. –

ответ

0

Вы должны быть в состоянии использовать проверку привязки модели для обеспечения данных путем простого добавления ключевых слов в классе.

Взгляните, используя либо кучу необходимых тегов:

public class Xref 
{ 
    [Required] 
    public string System { get; set; } 
    [Required] 
    public List<Segment> Segments { get; set; } 

} 

или общую модель Validate:

[HttpPost] 
[ValidateModel] 
public async Task<IHttpActionResult> Post([FromBody]Customer customer) 
{ 
... 
} 

See this for specific examples