WebAPI验证

时间:2014-03-31 15:02:28

标签: c# asp.net validation asp.net-web-api fluentvalidation

我通常使用看起来像这样的ApiController方法

[HttpPost]
public HttpResponseMessage DoSomething(int someId)
{
  var someObj = Session.Get<SomeObj>(someId);
  if (someObj == null)
  {
    return Request.CreateResponse(HttpStatusCode.NotFound);
  }

  Do something...
}

我想摆脱if条件。我可以抛出NullPointerException但我希望能够指定要返回的HTTP状态代码。我想将if条件移动到某个验证类并在OnActionExecuting中执行验证。

我之前使用过FluentValidation和WebAPI,如果有这样的语法会很好:

RuleFor(x => x.SomeId).Must(x => someObjectExists()).WithMessage("SomeObject wasn't found").WithHTTPStatusCode(HttpStatusCode.NotFound);

...其中WithHTTPStatusCode将是解决我问题的方法。

你有什么建议吗?

3 个答案:

答案 0 :(得分:1)

我喜欢更默默地处理这个问题,因为它让任何一个人都知道他们是否缺少一个必需的变量而无法访问WebAPI端点。

        [AcceptVerbs("GET", "POST")]
        public ServiceResult Login(JObject args)
        {
            var retVal = new ServiceResult {Success = false};
            JToken tokenValue;
            var email = string.Empty;
            var password = string.Empty;

            if (args.TryGetValue("email", out tokenValue))
            {
                email = args.Value<string>("email");
            }

            if (args.TryGetValue("password", out tokenValue))
            {
                password = args.Value<string>("password");
            }

            var user = Services.Users.GetByEmail(email, true);

            if (null != user || null != user.Id)
            {
                return Services.Authentication.AuthenticateSignIn(user, password, true);

            }

            retVal.Data = tokenValue;
            return retVal;
        }

如果缺少变量,默认情况下它应该在到达端点之前出错,除非你将App_Start / WebApiConfig.cs设置为

config.Formatters.JsonFormatter.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore;

如果您不喜欢IF条件,则在获取变量后总是可以使用Assert。祝你好运!

答案 1 :(得分:1)

酷名!

我想向您推荐这种方法。创建一个你定义的新类,称为ServiceNotFoundException或类似的类,并让它继承自HttpResponseException,传入一个404未找到的构造函数,如下所示:

float Counter = 5.0f;
string Output = "";
while (Counter < 24.0f)
{
    Output += Counter;
    txtAvgTemp.Text += "\r\n" + Output.ToString(); //Appending the text
    Counter += 1.5f;
}

现在在你的Session.Get中,如果在那里没有找到实体,你应该抛出异常(所以将这个逻辑保留在你的控制器之外)。

这样,如果多个控制器使用您的服务,它将在所有情况下抛出异常。因为你从HttpResponseException继承并抛出NotFound,它将返回404.如果你需要特定的文本/消息,请使用构造函数,你会看到base()有一个你可以抛出的HttpResponseMessage交替出现(也许在响应中设置特定的消息文本)。

如果您更喜欢在控制器中执行此逻辑,那么无论如何都可以抛出异常,但您应该尽量不要重复!

如果有任何问题,请告诉我们。

答案 2 :(得分:1)

为什么不使用标准模型验证?你在使用Entity Framework吗?你可以使用你的pocos上的数据注释来实现这一点,或者根据你需要创建一个模型,在你的情况下,一个具有单个属性的类就可以了。

public async Task<IHttpActionResult> PutOrder(int id, Order order)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }...

订单模型看起来像这样......

    public partial class Order
    {
[Required]
 public int id { get; set; }
}