- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试找到一种解决方案来验证在 POST 请求中发送的 XML 数据是否满足给定的自定义 XML 模式。
如果我使用随 ASP.NET Web API 提供的 XmlMediaTypeFormatter
,据我所知,我没有可用的模式验证。例如:如果我有一个模型类型......
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
}
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
order
方法的
Post
是
null
,在示例 2 中,
order.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
可能是一个更好的地方吗?或者是否有一些开箱即用的更简单的东西?
最佳答案
如果我这样做,我不会使用格式化程序。格式化程序的主要目标是将连线表示转换为 CLR 类型。在这里,您有一个 XML 文档,您想要根据一个完全不同的任务来验证模式。
我建议创建一个新的 MessageHandler 来进行验证。从 DelegatingHandler 派生,如果内容类型是 application/xml
将内容加载到 XDocument 并进行验证。如果失败,则抛出 HttpResponseException。
只需将您的 MessageHandler 添加到 Configuration.MessageHandlers 集合中即可。
使用派生的 XmlMediaTypeFormatter 的问题在于,您现在正在执行嵌入在 ObjectContent 代码中的某个点,并且干净地退出可能会很棘手。此外,使 XmlMediaTypeFormatter 变得更复杂可能不是一个好主意。
我尝试创建 MessageHandler。我实际上并没有尝试运行此代码,所以买家要小心。此外,如果您避免阻止调用者,任务内容会变得非常棘手。也许有人会为我清理该代码,无论如何它就在这里。
public class SchemaValidationMessageHandler : DelegatingHandler {
private XmlSchemaSet _schemaSet;
public SchemaValidationMessageHandler() {
_schemaSet = new XmlSchemaSet();
_schemaSet.Add(null, "OrderSchema.xsd");
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
if (request.Content != null && request.Content.Headers.ContentType.MediaType == "application/xml")
{
var tcs = new TaskCompletionSource<HttpResponseMessage>();
var task = request.Content.LoadIntoBufferAsync() // I think this is needed so XmlMediaTypeFormatter will still have access to the content
.ContinueWith(t => {
request.Content.ReadAsStreamAsync()
.ContinueWith(t2 => {
var doc = XDocument.Load(t2.Result);
var msgs = new List<string>();
doc.Validate(_schemaSet, (s, e) => msgs.Add(e.Message));
if (msgs.Count > 0) {
var responseContent = new StringContent(String.Join(Environment.NewLine, msgs.ToArray()));
tcs.TrySetException(new HttpResponseException(
new HttpResponseMessage(HttpStatusCode.BadRequest) {
Content = responseContent
}));
} else {
tcs.TrySetResult(base.SendAsync(request, cancellationToken).Result);
}
});
});
return tcs.Task;
} else {
return base.SendAsync(request, cancellationToken);
}
}
关于asp.net-mvc - 使用 ASP.NET WebAPI 对 POST 请求进行 XML 架构验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11820594/
我想为我的 ABP 项目中的特定应用程序服务关闭自动 WebAPI 生成服务。 最佳答案 RemoteService 属性可用于将类标记为远程服务或禁用固有地实现 IRemoteService 接口(
我无法从 postman 访问 webapi 错误是下一个: 如您所见,没有授权。 valuescontroller.cs 是: namespace CVService.Controllers {
我无法从 postman 访问 webapi 错误是下一个: 如您所见,没有授权。 valuescontroller.cs 是: namespace CVService.Controllers {
我有以下 Controller ,它应该接受用户名和密码作为 POST 中的有效负载。如果我将其更改为 HttpGet 就可以了。 [RoutePrefix("api")] public class
使用以下路线: routes.MapHttpRoute( name: "Set", routeTemplate: "api/set/{id}",
我正在使用 AngularJS,我正在尝试将 json 从我的服务发送到 webAPI Controller 。当我通过发送时,我在 webApi 函数的参数中收到 null。 我的功能服务是: an
据我了解,如果我有一个 ASP.NET WebApi 方法,其签名如下所示...... public HttpResponseMessage PostCustomer(Customer custome
我遇到了一个解决方案问题,我使用 Visual Studio SPA 模板中的部分在具有 Oauth 身份验证的 WebApi 中拥有帐户 Controller 。 app.UseOAuthBea
我按照此处的说明将 webApi.HelpPage 区域和 View 添加到使用 structureMap 的现有项目中 - 但是在访问/Help url 时: StructureMap Except
我有一个 WebAPI。如何返回并打开网页。例如,我想打开 CNN.com 页面。 [HttpGet] public HttpResponseMessage Get()
我想知道是否有人可以澄清这一点。我发现用法令人困惑。 链接和视频都没有回答我的问题 我知道像这样的链接 asp.net core middleware vs filters 甚至还有关于它的视频 但是
运行以下最新版本(在撰写本文时): Visual Studio 2019 16.4.5 .NET 核心 SDK 3.1.102 x64 测试的浏览器: 谷歌浏览器 80.0.3987.122 火狐 7
想法是,将有一个外部实体 (SharePoint) 调用我的 WebAPI 并传入 PDF 文件以及有关该 PDF 文件的一些额外元数据信息。我被困在如何构造 Web API 方法的签名上。这是我到目
我有一个 WebApi 服务处理来自简单表单的上传,如下所示: 但是,我不知道如何使用 HttpClient API 模拟同一
嗨,我是 Angular 的新手,现在我从一个示例登录页面开始,该页面传递包含用户名和密码的 userEntity。userEntity 是一个对象/实体是 webapi。 问题:当我为登录按钮单击
我有一个 AngularJS + MVC + WebAPI,我正在尝试:- 使用标准(个人账户)进行MVC认证;- 使用相同的用户和密码进行基于 WebAPI 的身份验证。 问题,AngularJS
Web API 的版本存在一些混淆。看看这个 Web API at NuGet , Microsoft ASP.NET Web API 2.2 5.2.3 什么?这里是没有提到 2.2 的描述 我的猜
我正在开发一个 Web 应用程序,该应用程序将 Owin 托管用于 MVC 和 WebApi 2。 我最近将 Microsoft Mvc/WebApi 包从 5.2.2 版升级到 5.2.3 版,将
随着Web技术的发展,现在各种框架,前端的,后端的,数不胜数。全栈工程师的压力越来越大。 现在的前端的框架,既可以做各种Web,又可以做各种APP,前端框架更新换代越来越快,越来越多。 传统的模
1. WebAPI 背景知识 1.1 什么是 WebAPI JS 分成三个大的部分: ECMAScript: 基础语法部分 DOM API: 操作页面结构 BOM API: 操作浏览器 WebAPI
我是一名优秀的程序员,十分优秀!