首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >将XML发布到asp.net核心2.0 web api

将XML发布到asp.net核心2.0 web api
EN

Stack Overflow用户
提问于 2017-09-19 22:10:00
回答 3查看 5.7K关注 0票数 5

我正在尝试将XML发布到asp.net核心2:

代码语言:javascript
复制
$.ajax({
    type: "POST",
    url: 'api/Test',
    data: "<test>hello<test>",
    contentType: "application/xml",
    success: function (response) { alert(response); },
});

我应该如何编写动作,让它接受xml作为参数?

  • IActionResult Post([FromBody]string xml) xml is null
  • IActionResult Post([FromBody]XElement xml) xml is null
  • IActionResult Post(XElement xml) -> InvalidOperationException:未能创建类型为'System.Xml.Linq.XElement‘的实例。绑定模型的复杂类型不能是抽象类型或值类型,并且必须具有无参数的constructor.
  • IActionResult Post(string xml) -> xml is

在Startup.ConfigureServices中:

代码语言:javascript
复制
services.AddMvc()
    .AddXmlSerializerFormatters();

如何编写控制器,使其接受XML作为参数?我知道我可以从HttpContext.Request中读取它,但我希望它是参数

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-09-20 19:52:54

我最终创建了自定义的InputFormatter,这非常简单,但是如果有更好的替代方案,非常欢迎你写一个答案!

代码语言:javascript
复制
public class XDocumentInputFormatter : InputFormatter, IInputFormatter, IApiRequestFormatMetadataProvider
{
    public XDocumentInputFormatter()
    {
        SupportedMediaTypes.Add("application/xml");
    }

    protected override bool CanReadType(Type type)
    {
        if (type.IsAssignableFrom(typeof(XDocument))) return true;
        return base.CanReadType(type);
    }

    public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
    {
        var xmlDoc = await XDocument.LoadAsync(context.HttpContext.Request.Body, LoadOptions.None, CancellationToken.None);
        return InputFormatterResult.Success(xmlDoc);
    }
}

在startup.cs中注册XDocumentInputFormatter

代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options => options.InputFormatters.Insert(0, new XDocumentInputFormatter()));
}
票数 5
EN

Stack Overflow用户

发布于 2018-05-31 17:01:13

对于Liero给出的答案,你应该使用一个StreamReader,这样你就可以支持多种编码了。使用UTF-8、UTF-16和ASCI声明头测试了我的解决方案。

更改XDocumentInputFormatter中的方法:

代码语言:javascript
复制
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
    var xmlDoc = await XDocument.LoadAsync(context.HttpContext.Request.Body, LoadOptions.None, CancellationToken.None);
    return InputFormatterResult.Success(xmlDoc);
}

至下图

代码语言:javascript
复制
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context) {
        // Use StreamReader to convert any encoding to UTF-16 (default C# and sql Server).
        using (var streamReader = new StreamReader(context.HttpContext.Request.Body)) {
            var xmlDoc = await XDocument.LoadAsync(streamReader, LoadOptions.None, CancellationToken.None);
            return InputFormatterResult.Success(xmlDoc);
        }
    }
票数 2
EN

Stack Overflow用户

发布于 2020-09-16 00:02:12

这些解决方案可以工作,但在.NET核心3中有一个缺点-它们会导致异常(在调用XDocument.LoadAsync内部):

不允许System.InvalidOperationException:同步操作。调用ReadAsync或将AllowSynchronousIO设置为true。

以下是我用FileBufferingReadStream修改的解决方案(灵感来自Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter)的代码

代码语言:javascript
复制
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
    Check.NotNull(context, nameof(context));

    var xmlDoc = await LoadXmlFromRequestAsync(context.HttpContext);
    return InputFormatterResult.Success(xmlDoc);
}

private static async Task<XDocument> LoadXmlFromRequestAsync(HttpContext httpContext)
{
    Check.NotNull(httpContext, nameof(httpContext));

    //Code from Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter to use FileBufferingReadStream to avoid synchronous read issue:
    //https://github.com/dotnet/aspnetcore/issues/18723 - Synchronous call inside XDocument.LoadAsync causes --> System.InvalidOperationException: Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
    int memoryThreshold = 30720;
    long contentLength = httpContext.Request.ContentLength.GetValueOrDefault();
    if (contentLength > 0 && contentLength < memoryThreshold)
    {
        memoryThreshold = (int)contentLength;
    }

    var readStream = new FileBufferingReadStream(httpContext.Request.Body, memoryThreshold);
    httpContext.Response.RegisterForDispose(readStream);
    await readStream.DrainAsync(CancellationToken.None);
    readStream.Seek(0, SeekOrigin.Begin);

    try
    {
        using (var streamReader = new StreamReader(readStream))
        {
            var xmlDoc = await XDocument.LoadAsync(streamReader, LoadOptions.None, CancellationToken.None);
            return xmlDoc;
        }
    }
    finally
    {
        await readStream.DisposeAsync();
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46302703

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档