使用ModelState从Web API 2返回错误

时间:2014-03-09 22:59:06

标签: c# rest asp.net-web-api .net-4.5 dotnet-httpclient

我正在尝试使用ModelState对象向客户端发送错误;我正在使用asp.net Web API进行服务。

在Web服务方面,我这样做。

    public HttpResponseMessage VerifyData(Cobject data)
    {
        string[] errors;
        if (!VerifyAllRequiredData(data, out errors))
        {
            foreach(string error in errors)
                ModelState.AddModelError("", error);
            return Request.CreateErrorResponse(HttpStatusCode.ExpectationFailed, ModelState);
        }

        return Request.CreateResponse(HttpStatusCode.OK, data);
    }

我正在为该服务创建一个.NET客户端库,以便我们可以将它用于现有的Windows应用程序。

在客户端:

    public bool VerifyData(Cobject data)
    {
        try
        {  
            HttpClient c = new HttpClient();
            c.BaseAddress = BaseAddress;
            c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(JsonHeader));
            c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(HTMLHeader));
            c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(TextHeader));
            var asyncResponse = this.PostAsJsonAsync(url, data);
            asyncResponse.Wait();
            asyncResponse.Result.EnsureSuccessStatusCode();
            return true;
        }
        catch (HttpRequestException hre)
        {
            Console.WriteLine(hre.Message);
            return false;
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            return false;
        }
    }

这里的问题是我没有在respose上看到任何添加到ModelState的消息。我看到状态(ExpectionFailed)但没有消息。如何在客户端上检索这些消息?

3 个答案:

答案 0 :(得分:12)

我使用"类似的"代码发布帖子并进入我的网络API。让我复制一些代码,以便您可以从ModelState获取信息

var responseTask = await client.SendAsync(request);
var result = responseTask.ContinueWith(async r =>
               {
                   var response = r.Result;

                   var value = await response.Content.ReadAsStringAsync();
                   if (!response.IsSuccessStatusCode)
                   {
                       var obj = new { message = "", ModelState = new Dictionary<string,string[]>() };
                       var x = JsonConvert.DeserializeAnonymousType(value, obj);
                       throw new AggregateException(x.ModelState.Select(kvp => new Exception(string.Format("{0}: {1}", kvp.Key, string.Join(". ", kvp.Value)))));
                   }

               }).Result;

我希望这能为你解决问题:)

答案 1 :(得分:10)

我创建了一个强类型对象,并使用如下:

public class BadRequestResponse
{

    public string Message { get; set; }
    public Dictionary<string, string[]> ModelState { get; set; }
}

并使用它来反序列化JSON,如下例所示:

    public async Task DoStuff()
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = "http://localhost/";
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            RegisterUserRequest content = new RegisterUserRequest { ConfirmPassword = "foo", Password = "foo", Email = "foo@bar" };

            HttpResponseMessage response = await client.PostAsJsonAsync("api/Account/Register", content).ConfigureAwait(false);
            if (response.StatusCode == System.Net.HttpStatusCode.BadRequest)
            {
                BadRequestResponse message = await response.Content.ReadAsAsync<BadRequestResponse>().ConfigureAwait(false);
                // do something with "message.ModelState.Values"
            }
        }
    }

您可以检查HttpStatusCode.ExpectationFailed而不是HttpStatusCode.BadRequest

我还安装了WebApi Client包(因为此ReadAsAsync重载是此库的扩展名):

Install-Package Microsoft.AspNet.WebApi.Client

答案 2 :(得分:0)

实际上您可以使用“CreateErrorResponse”解决问题。此方法具有重载,使您有机会发回ModelState

 [HttpGet]
        public HttpResponseMessage Get([FromUri]InputFilterModel filter)
        {
            try
            {
                if (filter == null || ModelState.IsValid == false)
                {
                   return (filter == null)? Request.CreateErrorResponse(HttpStatusCode.BadRequest,"Input parameter can not be null")
                                          : Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }

模型状态返回带有验证问题的模型中每个字段的Json。你可以看到它直接在浏览器或fiddler中进行查询。