Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Receive (and send) XML via POST with ASP.NET

I have to set up an XML "web service" that receives a POST where the 'Content-type header will specify “text/xml”.'

What is the simplest way to get the XML into an XDocument for access by VB.NET's axis queries?

I don't believe the web service is guaranteed to follow any protocol (e.g. SOAP, etc); just specific tags and sub-tags for various requests, and it will use Basic Authentication, so I will have to process the headers.

(If it matters:
* the live version will use HTTPS, and
* the response will also be XML.)

like image 410
Mark Hurd Avatar asked Dec 23 '22 03:12

Mark Hurd


1 Answers

Given Steven's warning, the answer may be to parse Request.InputStream manually with Tom Holland's test first, followed by XDocument.Load in the Page_Load event.

A Google search initiated before I asked the question, but only checked after, found this, also suggesting I'm on the right track.

Also I was going to ask the question implied by my point that the response had to be XML too, as to what is the best way for that, but I've found an answer here.

In summary, the final code is:

 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If Request.ContentType <> "text/xml" Then _
        Throw New HttpException(500, "Unexpected Content-Type")

    Dim id = CheckBasicAuthentication

    Dim textReader = New IO.StreamReader(Request.InputStream)

    CheckXmlValidity(textReader)

    ' Reset the stream & reader
    Request.InputStream.Seek(0, IO.SeekOrigin.Begin)
    textReader.DiscardBufferedData()

    Dim xmlIn = XDocument.Load(textReader)

    ' process XML in xmlIn

    Dim xmlOut = <?xml version="1.0" encoding="UTF-8" ?>
                 <someresult>
                     <header>
                         <id><%= id.ToString() %></id>
                         <datestamp>To be inserted</datestamp>
                     </header>
                     <result/>
                 </someresult>

    ' Further generation of XML for output

    xmlOut.<someresult>.<header>.<datestamp>.Value = Date.UtcNow.ToString(xmlDateFormat)
    xmlText.Text = xmlOut.ToString
End Sub

Private Function CheckBasicAuthentication() As Integer
    Dim httpAuthorisation = Request.Headers("Authorization")
    If Left(httpAuthorisation, 6).ToUpperInvariant <> "BASIC " Then _
        Throw New HttpException(401, "Basic Authentication Required")
    Dim authorization = Convert.FromBase64String(Mid(httpAuthorisation, 7))
    Dim credentials = Text.Encoding.UTF8.GetString(authorization).Split(":"c)
    Dim username = credentials(0)
    Dim password = credentials(1)

    Return ConfirmValidUser(username, password)
End Function

Private Shared Sub CheckXmlValidity(ByVal textReader As System.IO.StreamReader)
    Try
        ' Check for "interesting" xml documents.
        Dim settings = New System.Xml.XmlReaderSettings()
        settings.XmlResolver = Nothing
        settings.MaxCharactersInDocument = 655360
        ' Successfully parse the file, otherwise an XmlException is to be thrown. '
        Dim reader = System.Xml.XmlReader.Create(textReader, settings)
        Try
            While reader.Read()
                'Just checking.
            End While
        Finally
            reader.Close()
        End Try
    Catch ex As Exception
        Throw New HttpException(500, "Invalid Xml data", ex)
    End Try
End Sub

and the ASP.NET webpage.aspx is:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="webpage.aspx.vb" Inherits="WebPage" ContentType="text/xml" %>

<asp:Literal ID="xmlText" runat="server" Mode="PassThrough"></asp:Literal> 

NB Throwing HTTPException is not a valid final solution for unwanted scenarios.

like image 62
Mark Hurd Avatar answered Jan 06 '23 07:01

Mark Hurd