在POST

时间:2019-07-08 23:19:46

标签: c#

我正在设法弄清如何满足我的服务消费者的需求。

在POST正文中,我发送了一个json对象。不需要任何字段。它们都是可选的。但是,消费者希望检测到空的{}或假的{{adaf:“ 32345”}实体并返回错误。

我目前正在使用ActionFilterAttribute来捕获必填字段,但是当这两种情况通过此行时,我无法弄清楚如何处理这两种情况:

  

varvalidationAttribute = attributeInstance作为ValidationAttribute;

因为它们是可选的,因此没有ValidationAttribute

有效的POST正文json是这两者之一...或无关紧要:

{
  amount: 123.45,
  age: 65
}

我的api签名:

[HttpPost]
[Route("/....blah")]
[ValidateModelState]
public async Task<Resp> AgePost([FromBody]AgeMoney)
{ .... }

我的ValidationFilter:

public class ValidateModelStateAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // Per https://blog.markvincze.com/how-to-validate-action-parameters-with-dataannotation-attributes/
        var descriptor = context.ActionDescriptor as ControllerActionDescriptor;
        if (descriptor != null)
        {
            foreach (var parameter in descriptor.MethodInfo.GetParameters())
            {
                object args = null;
                if (context.ActionArguments.ContainsKey(parameter.Name))
                {
                    args = context.ActionArguments[parameter.Name];
                }

                ValidateAttributes(parameter, args, context.ModelState);
            }
        }

        if (!context.ModelState.IsValid)
        {
            throw new BadRequestException("The following fields from the request body failed model validation: " + string.Join(", ", context.ModelState.Keys));
        }
    }

    private void ValidateAttributes(ParameterInfo parameter, object args, ModelStateDictionary modelState)
    {
        foreach (var attributeData in parameter.CustomAttributes)
        {
            var attributeInstance = parameter.GetCustomAttribute(attributeData.AttributeType);

            var validationAttribute = attributeInstance as ValidationAttribute;
            if (validationAttribute != null)
            {
                var isValid = validationAttribute.IsValid(args);
                if (!isValid)
                {
                    modelState.AddModelError(parameter.Name, validationAttribute.FormatErrorMessage(parameter.Name));
                }
            }
        }
    }
}

}

任何想法都值得赞赏。 TIA

1 个答案:

答案 0 :(得分:0)

我想出了一种使用反射的方法。随时发表评论/改进。总是渴望学习。

public class ValidateModelStateAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
       //snipped for brevity. See OP for full implementation  
       IsAllNullOrEmpty(args);
       ValidateAttributes(parameter, args, context.ModelState);

    }
}




public void IsAllNullOrEmpty(object myObject)
{
   //Get the object so we don't have to keep calling reflection
   var obj = myObject.GetType();

  //Get a count of how many properties there are
  var propCount = obj.GetProperties().Count();

  var areAllNullOrEmpty = obj.GetProperties()
  .Select(pi => pi.GetValue(myObject))
  .Count(value => value == null);

  if (areAllNullOrEmpty == propCount)
  { throw new BadRequestException("The request body failed model validation."); }

}