我正在尝试找到一种解决方案来验证在 POST 请求中发送的 XML 数据是否满足给定的自定义 XML 模式。
如果我使用XmlMediaTypeFormatter
随 ASP.NET Web API 提供的,我没有可用的模式验证,据我所知。例如:如果我有一个模型类型......
public class Order
{
public string Code { get; set; }
public int Quantity { get; set; }
}
ApiController
...以及...中的 POST 操作
public HttpResponseMessage Post(Order order)
{
if (ModelState.IsValid)
{
// process order...
// send 200 OK response for example
}
else
// send 400 BadRequest response with ModelState errors in response body
}
...我可以发布以下“错误”的 XML 数据,但仍会得到 200 OK 响应:
User-Agent: Fiddler
Host: localhost:45678
Content-Type: application/xml; charset=utf-8
<Order> <Code>12345</Nonsense> </Order> // malformed XML
或者:
<Order> <CustomerName>12345</CustomerName> </Order> // invalid property
或者:
<Customer> <Code>12345</Code> </Customer> // invalid root
或者:
"Hello World" // no XML at all
等等等等
我对请求进行验证的唯一一点是模型绑定:在请求示例 1、3 和 4 中,order
传递到Post
方法中的是null
,在示例 2order.Code
中null
,我可以通过测试order == null
或标记Code
属性来使属性无效[Required]
属性。我可以在响应中使用 400“BadRequest”Http 状态代码和响应正文中的验证消息将此验证结果发回。但是我不能确切地说出什么是错误的,也无法区分示例 1、3 和 4 中的错误 XML(没有order
发布,这是我唯一能看到的) - 例如。
要求Order
必须使用特定的自定义 XML 模式发布,例如xmlns="http://test.org/OrderSchema.xsd"
,我想验证发布的 XML 是否对此模式有效,如果不是,则在响应中发回模式验证错误。为了实现这一点,我从一个自定义开始MediaTypeFormatter
:
public class MyXmlMediaTypeFormatter : MediaTypeFormatter
{
// constructor, CanReadType, CanWriteType, ...
public override Task<object> ReadFromStreamAsync(Type type, Stream stream,
HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
{
var task = Task.Factory.StartNew(() =>
{
using (var streamReader = new StreamReader(stream))
{
XDocument document = XDocument.Load(streamReader);
// TODO: exceptions must the catched here,
// for example due to malformed XML
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.Add(null, "OrderSchema.xsd");
var msgs = new List<string>();
document.Validate(schemaSet, (s, e) => msgs.Add(e.Message));
// msgs contains now the list of XML schema validation errors
// I want to send back in the response
if (msgs.Count == 0)
{
var order = ... // deserialize XML to order
return (object)order;
}
else
// WHAT NOW ?
}
});
return task;
}
}
只要一切正确,这就是有效的。
但我不知道该怎么办msgs.Count > 0
。如何将此验证结果列表“传输”到Post
操作,或者如何创建包含这些 XML 模式验证消息的 Http 响应?
此外,我不确定自定义MediaTypeFormatter
是否是此类 XML 模式验证的最佳扩展点,以及我的方法是否正确。定制HttpMessageHandler
/可能DelegatingHandler
是一个更好的地方吗?或者是否有一些开箱即用的更简单的东西?