Issue receiveing POST request with Content-Type text/xml

Yasar 26 Reputation points
2021-06-15T12:11:15.07+00:00

I'm kinda new to building web applications. I used the template for a ASP.NET Core Web App (Modell-View-Controller) to create a Web Api for REST POST requests.
It was chosen becuase I want to run it on a respberry pi 4 in the end and was able to select the target system when publishing in the Developer PowerShell in VS19.

I currently have a working POST function for request with the Content-Type application/xml. I have to adjust the server POST function because the request is not changeable.

I used an additional service to be able to work with xmls:

services.AddMvc(config =>
                {
                    config.InputFormatters.Insert(0, new XDocumentInputFormatter());
                }).SetCompatibilityVersion(CompatibilityVersion.Latest).AddXmlSerializerFormatters();

The used POST method:

[HttpPost]
        [Consumes("application/xml")]
        public void PostApplXML([FromBody] XDocument value)
        {
        }

I did send my request with Fiddler and received all the data I needed. I also checked it in VS and analyzed the received data.

I have an issue regarding a second POST function for Content-Type text/xml;charset=utf-8. I tried various input parameters to be able to receive the data but was not able to see them in my function.

These are the different ways I have already tried with the responses from Fiddler:

[HttpPost]
       [Consumes("text/xml")]
        public void PostTextXML(HttpRequestMessage request)
        {
          //Fiddler: HTTP/1.1 415 Unsupported Media Type
        }

[HttpPost]
        [Consumes("text/xml")]
        public void PostTextXML([FromBody] HttpRequestMessage request)
        {
            //Fiddler: HTTP/1.1 415 Unsupported Media Type
        }

[HttpPost]
        [Consumes("text/xml")]
        public void PostTextXML(string request)
        {
            //Fiddler: Status OK, request = NULL
        }

[HttpPost]
        [Consumes("text/xml")]
        public void PostTextXML([FromBody] string request)
        {
            //Fiddler: HTTP/1.1 500 Internal Server Error
        }

Edit:
I forgot to mention that I also added an InputFormatter especially for the xml data in the Startup.cs:

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);
        }
    }
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,815 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,429 questions
0 comments No comments
{count} votes

Accepted answer
  1. AgaveJoe 30,036 Reputation points
    2021-06-15T19:23:17.323+00:00

    Does it mean that I have to create a class with the exact XML structure (or only the values I require from that XML?)

    Yes. When you add an input parameter in the action method the model binder tries to match the input parameter to the [FromBody] stream. This is a fundamental concept in Web API.

    Try removing the input parameter and read the XML body into a string. From there you can do whatever you need with the XML string.

    [HttpPost]
    [Produces("text/xml")]
    [Consumes("text/xml")]
    public async Task<string> PostAsync()
    {
        string xml;
        using (System.IO.StreamReader reader = new System.IO.StreamReader(Request.Body, Encoding.UTF8))
        {
            xml =  await reader.ReadToEndAsync();
        }
    
        return xml;
    }
    
    2 people found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. AgaveJoe 30,036 Reputation points
    2021-06-15T13:50:51.713+00:00

    You're struggling with data binding. Web API comes with databinding which coverts the incoming data stream to a string type. This is integrated into the framework.

    First, configure the XML formatter in startup.

    services.AddControllers().AddXmlSerializerFormatters();
    

    The data model that will be populated by the XML stream

        public class DataModel
        {
            public int id { get; set; }
            public string value { get; set; }
        }
    

    The action to accept and return XML.

    [HttpPost]
    [Produces("text/xml")]
    public DataModel Post([FromBody] DataModel value)
    {
        value.value = $"From Post {value.value}";
        return value;
    }
    

    The raw xml data sent to the action.

    <DataModel>
        <id>1</id>
        <value>Hello World</value>
    </DataModel>
    
    1 person found this answer helpful.

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.