Пользовательская проверка - требуется только при установке метода - PullRequest
0 голосов
/ 25 февраля 2019

У меня есть две конечные точки API, post и put:

    [HttpPost]
    [Route("projects")]
    public IHttpActionResult Create([FromBody] ProjectDTO projectDto)
    {
        if (ModelState.IsValid)
        {
                var project = MappingConfig.Map<ProjectDTO, Project>(projectDto);
                _projectService.Create(project);

                return Ok("Project successfully created.");
        }
        else 
        { 
            return BadRequest(ModelState); 
        }
    }

    [HttpPut]
    [Route("projects")]
    public IHttpActionResult Edit([FromBody] ProjectDTO projectDto)
    {
        if (ModelState.IsValid)
        {
            var project = _projectService.GetById(projectDto.ProjectId);
            if (project == null)
                return NotFound();

            project = Mapper.Map(projectDto, project);
            _projectService.Update(project);

            return Ok("Project successfully edited.");
        }
        else 
        { 
            return BadRequest(ModelState); 
        }
    }

DTO выглядит так:

    public class ProjectDTO
    {
           public int ProjectId { get; set; }
           [Required(ErrorMessage = "Name field is required.")]
           public string Name { get; set; }
           [Required(ErrorMessage = "IsInternal field is required.")]
           public bool IsInternal { get; set; }
    }

Я пытаюсь проверить поле ProjectId.Поле ProjectId должно быть обязательным только в методе HttpPut при редактировании моей сущности.

Можно ли выполнить пользовательскую проверку RequiredIfPut или что-то подобное, где это поле потребуется только при редактировании, но не при создании?

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Вот что вы можете сделать, используя пользовательский атрибут проверки:

 public class RequiredWhenPutAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (System.Web.HttpContext.Current.Request.HttpMethod == "PUT")
            {
                var obj = (ProjectDTO)validationContext.ObjectInstance;
                if (obj.ProjectId == null)
                {
                    return new ValidationResult("Project Id is Required");
                }
            }
            else
            {
                return ValidationResult.Success;
            }
        }
    }

    public class ProjectDTO
    {
        [RequiredWhenPut]
        public int? ProjectId { get; set; }
    }

Обновление:

В ответ на ваш комментарий, чтобы сделать решение более общим, вы можете добавитьКласс ParentDto, от которого наследуются другие классы, и общее свойство должно быть в классе ParentDto, как показано ниже:

 public class RequiredWhenPutAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (HttpContext.Current.Request.HttpMethod == "PUT")
            {
                var obj = (ParentDto)validationContext.ObjectInstance;
                if (obj.Id == null)
                {
                    return new ValidationResult(ErrorMessage);
                }
            }
            else
            {
                return ValidationResult.Success;
            }
        }
    }
    public class ParentDto
    {
        [RequiredWhenPut(ErrorMessage = "Id is required")]
        public int? Id { get; set; }
    }
    public class UserDTO : ParentDto
    {
        // properties
    }
    public class ProjectTypeDTO : ParentDto
    {
        // properties
    }
    public class ProjectDTO : ParentDto
    {
         // properties
    }
0 голосов
/ 25 февраля 2019

Это одна из причин, почему я использую разные классы для обоих случаев (например, ProjectUpdateRequestDto и ProjectCreateRequestDto).Может быть, оба могут быть получены из общего базового класса, но даже если это не так, то намного легче различить оба сценария.

Также может возникнуть проблема с безопасностью, потому что если вы используете один и тот же класс, это может бытьВозможно, что запросы на создание уже содержат идентификатор, и если ваш метод создания просто отображает DTO на объект базы данных, вы можете перезаписать существующие данные.Это означает, что вы должны быть осторожны и думать о таких сценариях.Если ваш класс создания DTO не имеет этого свойства, он не может быть установлен из маппера и не может быть ошибочным.

...