【问题标题】:aspnet 5 RESTful api ModelState.IsValid == true even though values are not valid according to DataAnnotationsaspnet 5 RESTful api ModelState.IsValid == true 即使根据 DataAnnotations 值无效
【发布时间】:2017-04-21 00:14:33
【问题描述】:

我曾使用 fiddler 和 swagger 来尝试测试并获得相同的结果。

这是模型:

using System.ComponentModel.DataAnnotations;
namespace AdGeo.Configuration.WebApi.Model
{
    public class ValueAdd
    {
        public string test { get; set; }
        [Required(ErrorMessage = "Range is required")]
        [Range(0,9,ErrorMessage ="Range 0 to 9")]
        [Display(Name ="Test Required")]
        public int? testrequired { get; set; }
    }
}

这是控制器:

using Microsoft.AspNet.Mvc;
using AdGeo.Configuration.WebApi.Model;

// For more information on enabling Web API for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860

namespace AdGeo.Configuration.WebApi.Controllers
{
    [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        // GET api/values/5
        [HttpGet("{id}")]
        public string Get(int id)
        {
            return "value";
        }

        // POST api/values
        [HttpPost]
        public IActionResult Post([FromBody]ValueAdd valueAdd)
        {
            if(ModelState.IsValid)
            {
                return new CreatedAtActionResult("Get", "Values", new { id = 5 }, valueAdd);
            }
            return new BadRequestObjectResult(ModelState);
        }
    }
}

示例 Json:

{
  "test": "string",
  "testrequired": 100
}

它到达等于 true 的 ModelState.IsValid,我希望它等于 false,因为 100 超出了范围。

另外,如果我尝试发布这个 Json: 示例 Json:

{
  "test": "string"
}

我希望 ModelState.IsValid 为 false,但它等于 true。

我一直在搜索和搜索无济于事,我所看到的最接近的是人们试图创建一个动作过滤器,但这些大多是以前 MVC6 的解决方案,而不是相同的。

我遗漏了什么,请注意这是我在 StackExchange 上的第一篇文章,因此对任何格式问题表示歉意。请让我知道需要澄清的内容,我会进行相应的编辑。

谢谢!

【问题讨论】:

  • 您是否检查过模型状态错误是什么?你可以通过`var errors = ModelState.Where(e => e.Value.Errors.Count > 0).ToList();`.
  • 感谢您的提问,问题是 ModelState 认为没有任何错误。 ModelState.IsValid 一直返回 true,除非我误解了您的要求?只是为了验证我尝试执行您的建议,但 Where 不是 ModelState 上的方法。
  • 哈,你说得对!我误读了你的问题。我目前唯一的建议是在 HttpPost 方法中放置一个断点,并在 valueAdd 中的值处取一个峰值,看看它们是否是你所期望的。
  • 我已经这样做了,它显示 testrequired = null。我理解这是因为该属性是公共 int 吗?但我认为 [required] 和 [rande()] 标签会强制它在指定范围内具有值?提醒一下,如果有帮助,我正在使用 dnxcore50 和 MVC6。

标签: c# asp.net-core-mvc dnx


【解决方案1】:

这里也一样,我想这是因为我使用的是 AddMvcCore 而不是 AddMvc。为了解决这个问题,我创建了以下操作过滤器属性。它将检查模型是否为空且必需,当不为空时它将运行验证。

/// <summary>
/// Validate inputs and update ModelState with errors
/// </summary>
public class ValidateModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var parameters = context.ActionDescriptor.Parameters.Cast<ControllerParameterDescriptor>().ToDictionary(p => p.Name);

        foreach (var kvp in context.ActionArguments)
        {
            if (kvp.Value == null)
            {
                if (!parameters[kvp.Key].ParameterInfo.IsOptional)
                {
                    context.ModelState.AddModelError($"{kvp.Key}", "Parameter is required");
                }

                continue;
            }

            var results = new List<ValidationResult>();
            var vc = new ValidationContext(kvp.Value);
            if (!Validator.TryValidateObject(kvp.Value, vc, results))
            {
                var errs = from vr in results
                           from member in vr.MemberNames
                           select new { Member = member, vr.ErrorMessage };

                foreach (var err in errs)
                {
                    context.ModelState.AddModelError($"{kvp.Key}.{err.Member}", err.ErrorMessage);
                }
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-19
    • 2016-04-07
    • 2018-04-15
    • 1970-01-01
    • 2012-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多