Как проверить тип коллекций? - PullRequest
0 голосов
/ 20 ноября 2018

Как проверить и отловить преобразование типа коллекции (строковый массив JSON в коллекцию C # long) для моего класса System.Web.Http.ApiController (до инициализации модели, если это возможно)?

Я хочу проверить и отловить любые нечисловые элементы в массиве JSON, которые будут возвращены как неправильный ответ на запрос (возможно, с аннотацией данных).

Когда включены нечисловые элементы JSON (для преобразования в длинную коллекцию), им не удается выполнить синтаксический анализ и удалить их перед передачей модели в метод ApiController. Учитывая классы ниже, допустимый ввод должен содержать только числовые значения для "PerferredNutTypes" и "GeographyIDs".

Классы

public class SquirrelController : ApiController
{
    [HttpPost]
    [Route("api/squirrels/search")]
    [SwaggerResponse(HttpStatusCode.OK, Type = typeof(SquirrelsResponse))]
    public HttpResponseMessage Squirrels(SquirrelsRequest model)
    {
        // model already parsed by the time breakpoint reaches here and non-convertable elements already stripped

        ...
        ...
        ...

        SquirrelsResponse results = Targeting.SearchForSquirrels(model);
        return Request.CreateResponse(HttpStatusCode.OK, results);
    }
}

public class SquirrelsRequest
{
    public SquirrelsRequest() {}

    public List<long> PreferredNutTypes { get; set; } = new List<long>();
    public GeographySearch geographySearch { get; set; } = new GeographySearch();
}

public class GeographySearch
{
    public GeographySearch() {}

    public BooleanOperator Operator { get; set; } = BooleanOperator.OR;
    public List<long> GeographyIDs { get; set; } = new List<long>();
}

public enum BooleanOperator
{
    AND,
    OR
}

Примеры:

//"Toronto" sould be an invalid input when converting from JSON string array to c# long collection.
{
  "PreferredNutTypes": [34,21],
  "GeographySearch": {
    "Operator": 1,
    "GeographyIDs": ["Toronto"]
  },
}

// This is what the model currently looks like in public HttpResponseMessage Squirrels(SquirrelsRequest model)
new SquirrelsRequest()
{
    PreferredNutTypes = new List<long>() { 34, 21 },
    GeographySearch = new GeographySearch()
    {
        Operator = 1
        GeographyIDs = new List<long>()
    }
}

Ожидания:

В идеале перехватывать любые нечисловые значения и возвращать их как неверный запрос. Подобно тому, как вы можете проверить, как вы используете аннотации данных для проверки диапазона. Допустимо решение для аннотирования данных. В идеале более понятный подход, чем доступ к ModelState и анализ сообщения / ключа ошибки. В идеале может применяться для любой коллекции.

Вещи, которые я пытался:

Попробовал пользовательский валидатор аннотаций данных, но может получить доступ к значениям только после его анализа. Попытался получить доступ к ошибкам проверки с помощью ModelState HttpActionContext, но в лучшем случае я могу получить только эти значения ...
System.Web.Http.Controllers.HttpActionContext actionContext.ModelState.["model.GeographySearch.GeographyIDs[0]"].Errors[0].Exception.Message => "Error converting value \"sonali7678687\" to type 'System.Int64'. Path 'subjectSearch.writingAbout[0]', line 6, position 36."
System.Web.Http.Controllers.HttpActionContext actionContext.ModelState.["model.GeographySearch.GeographyIDs[0]"].Errors[0].Exception.InnerException.Message => "Input string was not in a correct format."

... наверняка должен быть лучший способ проверки?

ОБНОВЛЕНИЕ 1: Перефразированный вопрос, чтобы сделать объяснение и намерение более ясным.

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Вы можете попробовать валидатор JSON Schema, изменить свой метод для получения тела JSON, сначала проверить его, а затем преобразовать в модель.

public class SquirrelController : ApiController
{
    [HttpPost]
    [Route("api/squirrels/search")]
    public SquirrelsResponse Squirrels(PostBody model)
    {
        var generator = new JSchemaGenerator();
        var schema = generator.Generate(typeof(SquirrelsRequest));
        var body = JObject.Parse(model.Body);

        bool valid = body.IsValid(schema, out IList<string> messages);
        if (!valid)
        {
            // Fail, do something
        }

        // Success
    }
}

public class PostBody
{
    public string Body { get; set; }
}

Получить дополнительную информацию ...
Проверка JSONсо схемой JSON
Схема Json.NET

0 голосов
/ 20 ноября 2018

Почему твой тип длинный?Кроме того, вы собираетесь работать с десятичными?Если нет, то вам нужно int.TryParse ().Где бы вы ни использовали int.parse (или long.parse () в вашем случае), замените его на int.TryParse ().TryParse возвращает логическое значение (True или False), которое сообщит вам, была ли проанализированная строка числом или нет.

пример:

bool isNumber = int.TryParse("Data I'm Trying to parse but it's a string", variableTheResultWillGetStoredToifSuccessful);

Возвращается значение false, имое супер длинное имя переменной, которое вы никогда не должны использовать, останется пустым или скорее неизменным.Таким образом, вы можете сделать

if(isNumber == false){
//skip storing the number
}else{
//keep doing what you're doing;
}

Вы также можете сделать, более кратко, переписав вышесказанное:

if(isNumber){
//keep doing what you're doing
}

Более или менее, это краткое изложение этого.TryParse будет возвращать значение true или false, основываясь на том, что анализ был успешным или нет без сбоя вашего кода, тогда вы можете использовать эту информацию, чтобы продолжить, как вам кажется подходящим.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...