I have a controller and method that adds user to a DB.
I call it from Fiddler with a Request Header as follows -
Content-Type: application/xml
Accept: application/xml
Host: localhost:62236
Content-Length: 39
And a request body of -
<User>
<Firstname>John</Firstname>
<Lastname>Doe</Lastname>
</User>
This works as expected, the method is called, the user object processed in the method 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;
}
}
I am performing my Model Validation in it's own class
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);
}
}
}
BUT if I post the following
<User>
<Firstname></Firstname> **//MISSING FIRST NAME**
<Lastname>Doe</Lastname>
</User>
The Model is invalid, and a JSON response is returned even though I stated Accept: application/xml.
If I perform model validation within the UserController, I get a proper XML response, but when I perform it in ModelValidationFilterAttribute I get JSON.
Your problems with the following code:
var errors = new Dictionary<string, IEnumerable<string>>();
actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, errors);
So you try to create the response from the errors
object where its type is Dictionary<string, IEnumerable<string>>();
.
Web.API will try to automatically find the right MediaTypeFormatter
for your response type. However the default XML serializer (DataContractSerializer
) not able to handle the type Dictionary<string, IEnumerable<string>>();
so it will use the JSON serializer for your response.
Actually you should use the CreateErrorResponse and just create the response from the ModelState
directly (it will create a HttpError
object which is XML seriazable)
public class ModelValidationFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ModelState.IsValid == false)
{
actionContext.Response =
actionContext.Request.CreateErrorResponse(
HttpStatusCode.BadRequest,
actionContext.ModelState);
}
}
}
I think the Web API will return JSON as its default type for responses outside of controller methods.
Have you tried disabling the JSON formatter, as suggested in this article?
http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization
i.e.
void ConfigureApi(HttpConfiguration config)
{
// Remove the JSON formatter
config.Formatters.Remove(config.Formatters.JsonFormatter);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With