5

我有一个将用户添加到数据库的控制器和方法。

我从 Fiddler 调用它并带有请求标头,如下所示 -

内容类型:应用程序/xml

接受:应用程序/xml

主机:本地主机:62236

内容长度:39

还有一个请求体——

<User>
  <Firstname>John</Firstname>
  <Lastname>Doe</Lastname>
</User>

这按预期工作,调用方法,在方法 PostUser 中处理用户对象。

 public class UserController : ApiController
    {
        public HttpResponseMessage PostUser(User user)
        {
            // Add user to DB
            var response = new HttpResponseMessage(HttpStatusCode.Created);
            var relativePath = "/api/user/" + user.UserID;
            response.Headers.Location = new Uri(Request.RequestUri, relativePath);
            return response;
        }
    }

我正在自己的班级中执行我的模型验证

public class ModelValidationFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (actionContext.ModelState.IsValid == false)
        {
            // Return the validation errors in the response body.
            var errors = new Dictionary<string, IEnumerable<string>>();
            foreach (KeyValuePair<string, ModelState> keyValue in actionContext.ModelState)
            {
                errors[keyValue.Key] = keyValue.Value.Errors.Select(e => e.ErrorMessage);
            }

            actionContext.Response =
                actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, errors);
        }
    }
}

但是如果我发布以下内容

<User>
  <Firstname></Firstname> **//MISSING FIRST NAME**
  <Lastname>Doe</Lastname>
</User>

模型无效,即使我声明 Accept: application/xml,也会返回 JSON 响应。

如果我在 UserController 中执行模型验证,我会得到一个正确的 XML 响应,但是当我在 ModelValidationFilterAttribute 中执行它时,我会得到 JSON。

4

2 回答 2

6

您对以下代码的问题:

var errors = new Dictionary<string, IEnumerable<string>>();
actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, errors);

因此,您尝试errors从其类型为 的对象创建响应Dictionary<string, IEnumerable<string>>();

Web.API 将尝试自动找到MediaTypeFormatter适合您的响应类型的权利。然而,默认的 XML 序列化程序 ( DataContractSerializer) 无法处理该类型Dictionary<string, IEnumerable<string>>();,因此它将使用 JSON 序列化程序作为您的响应。

实际上,您应该使用CreateErrorResponse并直接创建响应ModelState(它将创建一个HttpErrorXML 可序列化的对象)

public class ModelValidationFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (actionContext.ModelState.IsValid == false)
        {
            actionContext.Response =
                actionContext.Request.CreateErrorResponse(
                    HttpStatusCode.BadRequest, 
                    actionContext.ModelState);
        }
    }
}
于 2013-01-30T20:35:47.917 回答
1

我认为 Web API 将返回 JSON 作为控制器方法之外的响应的默认类型。

您是否尝试过按照本文的建议禁用 JSON 格式化程序?

http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization

IE

void ConfigureApi(HttpConfiguration config)
{

    // Remove the JSON formatter
    config.Formatters.Remove(config.Formatters.JsonFormatter);
}
于 2013-01-30T20:33:23.933 回答