'How can we pass XML as request to .Net core API and get response in XML from Same API in c#?

I want to create an API in .net core which accept XML request and gives response in XML only.

I have searched and created sample but when I hit request to the API with XML request it does not work.

Debugger did not come up to the controller.

I have also added below the line of code in the configure services of the startup.cs class.

 services.AddMvc(options =>
        {
            options.RespectBrowserAcceptHeader = true; // false by default
            options.InputFormatters.Insert(0, new XDocumentInputFormatter());
        }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
           .AddXmlSerializerFormatters()
          .AddXmlDataContractSerializerFormatters();

The POST method have written in the controller as below.


    [Produces("application/xml")]
            [ProducesResponseType(typeof(CustomerDetails), (int)HttpStatusCode.OK)]
            [HttpPost("CustomerDetails", Name = "CustomerDetails")]
            public IActionResult CustomerDetails([FromBody] CustomerDetails CustReq)
            {
                var resp = new CustomerDetails
                {
                   BankId="1234567"
                };
                return Ok(resp);
            }

Processing my request from Postman getting an error. An unhandled exception occurred while processing the request. InvalidCastException: Unable to cast object of type 'System.Xml.Linq.XDocument' to type 'CustomerValidationAPI.Models.CustomerDetails'.

Below is my XML request I want to process.

It also has multiple nodes how can we handle.

<?xml version="1.0" encoding="UTF-8"?>
    <FIXML xmlns="http://www.finacle.com/fixml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.finacle.com/fixml
executeFinacleScript.xsd">
       <Header>
          <RequestHeader>
             <MessageKey>
                <RequestUUID>FEBA_1553756445880</RequestUUID>
                <ServiceRequestId>executeFinacleScript</ServiceRequestId>
                <ServiceRequestVersion>10.2</ServiceRequestVersion>
                <ChannelId>COR</ChannelId>
             </MessageKey>
             <RequestMessageInfo>
                <BankId>04</BankId>
                <TimeZone>GMT+05:00</TimeZone>
                <EntityId />
                <EntityType />
                <ArmCorrelationId />
                <MessageDateTime>2019-03-28T11:00:45.880</MessageDateTime>
             </RequestMessageInfo>
             <Security>
                <Token>
                   <PasswordToken>
                      <UserId>11111</UserId>
                      <Password />
                   </PasswordToken>
                </Token>
                <FICertToken />
                <RealUserLoginSessionId />
                <RealUser />
                <RealUserPwd />
                <SSOTransferToken />
             </Security>
          </RequestHeader>
       </Header>
       <Body>
          <executeFinacleScriptRequest>
             <ExecuteFinacleScriptInputVO>
                <requestId>validateAcct.scr</requestId>
             </ExecuteFinacleScriptInputVO>
             <executeFinacleScript_CustomData>
                <ACCT_NUM>01122507576</ACCT_NUM>
                <PHONE_NUM>59887834</PHONE_NUM>
                <NIC>G2105493001653</NIC>
             </executeFinacleScript_CustomData>
          </executeFinacleScriptRequest>
       </Body>
    </FIXML>

Customer Details Model Have created as below

 public class CustomerDetails
    {
        [Required]
        public string RequestUUID { get; set; }
        [Required]
        public string ServiceRequestId { get; set; }
        [Required]
        public string ServiceRequestVersion { get; set; }
        [Required]
        public string ChannelId { get; set; }
        [Required]
        public string BankId { get; set; }
        [Required]
        public string TimeZone { get; set; }

        public string EntityId { get; set; }

        public string EntityType { get; set; }

        public string ArmCorrelationId { get; set; }

        [Required]
        [DataType(DataType.Date)]
        public DateTime MessageDateTime { get; set; }

        [Required]
        public string Password { get; set; }
        public string FICertToken { get; set; }
        public string RealUserLoginSessionId { get; set; }
        public string RealUser { get; set; }
        public string RealUserPwd { get; set; }
        public string SSOTransferToken { get; set; }

        [Required]
        public string requestId { get; set; }
        [Required]
        public string ACCT_NUM { get; set; }
        [Required]
        public string PHONE_NUM { get; set; }
        [Required]
        public string NIC { get; set; }
    } 

My startUp class 

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(options =>
        {
            options.RespectBrowserAcceptHeader = true; // false by default
            options.InputFormatters.Insert(0, new XDocumentInputFormatter());
        }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
           .AddXmlSerializerFormatters()
          .AddXmlDataContractSerializerFormatters();
    } 

XDocumentInputFormatter in class have taken as below.. 

     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);
            //}

            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);
                }
            }
        }

ERROR I AM GETTING NOW

An unhandled exception occurred while processing the request. InvalidOperationException: http://www.finacle.com/fixml'> was not expected.

Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderTestClass.Read3_TestClass() InvalidOperationException: There is an error in XML document (1, 174).

System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, string encodingStyle, XmlDeserializationEvents events)

Created the Class from XML as below

 public class XMLClass
    {

        // NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
        /// <remarks/>
        [System.SerializableAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
        [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.finacle.com/fixml", IsNullable = false)]
        public partial class FIXML
        {

            private FIXMLHeader headerField;

            private FIXMLBody bodyField;

            /// <remarks/>
            public FIXMLHeader Header
            {
                get
                {
                    return this.headerField;
                }
                set
                {
                    this.headerField = value;
                }
            }

            /// <remarks/>
            public FIXMLBody Body
            {
                get
                {
                    return this.bodyField;
                }
                set
                {
                    this.bodyField = value;
                }
            }
        }

        /// <remarks/>
        [System.SerializableAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
        public partial class FIXMLHeader
        {

            private FIXMLHeaderRequestHeader requestHeaderField;

            /// <remarks/>
            public FIXMLHeaderRequestHeader RequestHeader
            {
                get
                {
                    return this.requestHeaderField;
                }
                set
                {
                    this.requestHeaderField = value;
                }
            }
        }

        /// <remarks/>
        [System.SerializableAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
        public partial class FIXMLHeaderRequestHeader
        {

            private FIXMLHeaderRequestHeaderMessageKey messageKeyField;

            private FIXMLHeaderRequestHeaderRequestMessageInfo requestMessageInfoField;

            private FIXMLHeaderRequestHeaderSecurity securityField;

            /// <remarks/>
            public FIXMLHeaderRequestHeaderMessageKey MessageKey
            {
                get
                {
                    return this.messageKeyField;
                }
                set
                {
                    this.messageKeyField = value;
                }
            }

            /// <remarks/>
            public FIXMLHeaderRequestHeaderRequestMessageInfo RequestMessageInfo
            {
                get
                {
                    return this.requestMessageInfoField;
                }
                set
                {
                    this.requestMessageInfoField = value;
                }
            }

            /// <remarks/>
            public FIXMLHeaderRequestHeaderSecurity Security
            {
                get
                {
                    return this.securityField;
                }
                set
                {
                    this.securityField = value;
                }
            }
        }

        /// <remarks/>
        [System.SerializableAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
        public partial class FIXMLHeaderRequestHeaderMessageKey
        {

            private string requestUUIDField;

            private string serviceRequestIdField;

            private decimal serviceRequestVersionField;

            private string channelIdField;

            /// <remarks/>
            public string RequestUUID
            {
                get
                {
                    return this.requestUUIDField;
                }
                set
                {
                    this.requestUUIDField = value;
                }
            }

            /// <remarks/>
            public string ServiceRequestId
            {
                get
                {
                    return this.serviceRequestIdField;
                }
                set
                {
                    this.serviceRequestIdField = value;
                }
            }

            /// <remarks/>
            public decimal ServiceRequestVersion
            {
                get
                {
                    return this.serviceRequestVersionField;
                }
                set
                {
                    this.serviceRequestVersionField = value;
                }
            }

            /// <remarks/>
            public string ChannelId
            {
                get
                {
                    return this.channelIdField;
                }
                set
                {
                    this.channelIdField = value;
                }
            }
        }

        /// <remarks/>
        [System.SerializableAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
        public partial class FIXMLHeaderRequestHeaderRequestMessageInfo
        {

            private byte bankIdField;

            private string timeZoneField;

            private object entityIdField;

            private object entityTypeField;

            private object armCorrelationIdField;

            private System.DateTime messageDateTimeField;

            /// <remarks/>
            public byte BankId
            {
                get
                {
                    return this.bankIdField;
                }
                set
                {
                    this.bankIdField = value;
                }
            }

            /// <remarks/>
            public string TimeZone
            {
                get
                {
                    return this.timeZoneField;
                }
                set
                {
                    this.timeZoneField = value;
                }
            }

            /// <remarks/>
            public object EntityId
            {
                get
                {
                    return this.entityIdField;
                }
                set
                {
                    this.entityIdField = value;
                }
            }

            /// <remarks/>
            public object EntityType
            {
                get
                {
                    return this.entityTypeField;
                }
                set
                {
                    this.entityTypeField = value;
                }
            }

            /// <remarks/>
            public object ArmCorrelationId
            {
                get
                {
                    return this.armCorrelationIdField;
                }
                set
                {
                    this.armCorrelationIdField = value;
                }
            }

            /// <remarks/>
            public System.DateTime MessageDateTime
            {
                get
                {
                    return this.messageDateTimeField;
                }
                set
                {
                    this.messageDateTimeField = value;
                }
            }
        }

        /// <remarks/>
        [System.SerializableAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
        public partial class FIXMLHeaderRequestHeaderSecurity
        {

            private FIXMLHeaderRequestHeaderSecurityToken tokenField;

            private object fICertTokenField;

            private object realUserLoginSessionIdField;

            private object realUserField;

            private object realUserPwdField;

            private object sSOTransferTokenField;

            /// <remarks/>
            public FIXMLHeaderRequestHeaderSecurityToken Token
            {
                get
                {
                    return this.tokenField;
                }
                set
                {
                    this.tokenField = value;
                }
            }

            /// <remarks/>
            public object FICertToken
            {
                get
                {
                    return this.fICertTokenField;
                }
                set
                {
                    this.fICertTokenField = value;
                }
            }

            /// <remarks/>
            public object RealUserLoginSessionId
            {
                get
                {
                    return this.realUserLoginSessionIdField;
                }
                set
                {
                    this.realUserLoginSessionIdField = value;
                }
            }

            /// <remarks/>
            public object RealUser
            {
                get
                {
                    return this.realUserField;
                }
                set
                {
                    this.realUserField = value;
                }
            }

            /// <remarks/>
            public object RealUserPwd
            {
                get
                {
                    return this.realUserPwdField;
                }
                set
                {
                    this.realUserPwdField = value;
                }
            }

            /// <remarks/>
            public object SSOTransferToken
            {
                get
                {
                    return this.sSOTransferTokenField;
                }
                set
                {
                    this.sSOTransferTokenField = value;
                }
            }
        }

        /// <remarks/>
        [System.SerializableAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
        public partial class FIXMLHeaderRequestHeaderSecurityToken
        {

            private FIXMLHeaderRequestHeaderSecurityTokenPasswordToken passwordTokenField;

            /// <remarks/>
            public FIXMLHeaderRequestHeaderSecurityTokenPasswordToken PasswordToken
            {
                get
                {
                    return this.passwordTokenField;
                }
                set
                {
                    this.passwordTokenField = value;
                }
            }
        }

        /// <remarks/>
        [System.SerializableAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
        public partial class FIXMLHeaderRequestHeaderSecurityTokenPasswordToken
        {

            private ushort userIdField;

            private object passwordField;

            /// <remarks/>
            public ushort UserId
            {
                get
                {
                    return this.userIdField;
                }
                set
                {
                    this.userIdField = value;
                }
            }

            /// <remarks/>
            public object Password
            {
                get
                {
                    return this.passwordField;
                }
                set
                {
                    this.passwordField = value;
                }
            }
        }

        /// <remarks/>
        [System.SerializableAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
        public partial class FIXMLBody
        {

            private FIXMLBodyExecuteFinacleScriptRequest executeFinacleScriptRequestField;

            /// <remarks/>
            public FIXMLBodyExecuteFinacleScriptRequest executeFinacleScriptRequest
            {
                get
                {
                    return this.executeFinacleScriptRequestField;
                }
                set
                {
                    this.executeFinacleScriptRequestField = value;
                }
            }
        }

        /// <remarks/>
        [System.SerializableAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
        public partial class FIXMLBodyExecuteFinacleScriptRequest
        {

            private FIXMLBodyExecuteFinacleScriptRequestExecuteFinacleScriptInputVO executeFinacleScriptInputVOField;

            private FIXMLBodyExecuteFinacleScriptRequestExecuteFinacleScript_CustomData executeFinacleScript_CustomDataField;

            /// <remarks/>
            public FIXMLBodyExecuteFinacleScriptRequestExecuteFinacleScriptInputVO ExecuteFinacleScriptInputVO
            {
                get
                {
                    return this.executeFinacleScriptInputVOField;
                }
                set
                {
                    this.executeFinacleScriptInputVOField = value;
                }
            }

            /// <remarks/>
            public FIXMLBodyExecuteFinacleScriptRequestExecuteFinacleScript_CustomData executeFinacleScript_CustomData
            {
                get
                {
                    return this.executeFinacleScript_CustomDataField;
                }
                set
                {
                    this.executeFinacleScript_CustomDataField = value;
                }
            }
        }

        /// <remarks/>
        [System.SerializableAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
        public partial class FIXMLBodyExecuteFinacleScriptRequestExecuteFinacleScriptInputVO
        {

            private string requestIdField;

            /// <remarks/>
            public string requestId
            {
                get
                {
                    return this.requestIdField;
                }
                set
                {
                    this.requestIdField = value;
                }
            }
        }

        /// <remarks/>
        [System.SerializableAttribute()]
        [System.ComponentModel.DesignerCategoryAttribute("code")]
        [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
        public partial class FIXMLBodyExecuteFinacleScriptRequestExecuteFinacleScript_CustomData
        {

            private uint aCCT_NUMField;

            private uint pHONE_NUMField;

            private string nICField;

            /// <remarks/>
            public uint ACCT_NUM
            {
                get
                {
                    return this.aCCT_NUMField;
                }
                set
                {
                    this.aCCT_NUMField = value;
                }
            }

            /// <remarks/>
            public uint PHONE_NUM
            {
                get
                {
                    return this.pHONE_NUMField;
                }
                set
                {
                    this.pHONE_NUMField = value;
                }
            }

            /// <remarks/>
            public string NIC
            {
                get
                {
                    return this.nICField;
                }
                set
                {
                    this.nICField = value;
                }
            }
        }


    }

public class Token
{
   public PasswordToken PasswordToken{get;set;} 

}

public class PasswordToken
{
   public string UserId{get;set;} 

   public string Password{get;set;} 

}

public class Body
{
   public executeFinacleScriptRequest executeFinacleScriptRequest{get;set;} 

}

public class executeFinacleScriptRequest
{
   public ExecuteFinacleScriptInputVO ExecuteFinacleScriptInputVO{get;set;} 

   public executeFinacleScript_CustomData executeFinacleScript_CustomData{get;set;} 

}

public class ExecuteFinacleScriptInputVO
{
   public string requestId{get;set;} 

}

public class executeFinacleScript_CustomData
{
   public string ACCT_NUM{get;set;} 

   public string PHONE_NUM{get;set;} 

   public string NIC{get;set;} 

}




Solution 1:[1]

the result is serialized based on what the requester requested! if you want xml just put ja corresponding header! and why [FromBody]XElement xml ? cant you use a normal model?

Solution 2:[2]

If Your API need request in XML. Below are things need to consider 1. In .ent core add below code in ConfigureServices method of Startup.cs Class

 services.AddMvc(options =>
            {
                options.RespectBrowserAcceptHeader = true; // false by default
            }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
               .AddXmlSerializerFormatters()
              .AddXmlDataContractSerializerFormatters();
  1. Create XML Data class by just simply copy your XML request and in the visual studio ..select paste special from edit menu and select paste XML as classes. It will generate classes as per your XML.

  2. Now you this class as [FromBody] YourClassName request in post method. Do include produce annotation as application/xml above your post method

Solution 3:[3]

In ASP.NET Core, everything is highly modular, so you only add the functionality you need to your application. Consequently, there's a separate NuGet package for the XML formatters that you need to add to your .csproj file - Microsoft.AspNetCore.Mvc.Formatters.Xml

<PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Xml" Version="1.1.3" />

Adding the package to your project lights up an extension method on the IMvcBuilder instance returned by the call to services.AddMvc(). The AddXmlSerializerFormatters() method adds both input and output formatters, so you can serialise objects to and from XML.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddXmlSerializerFormatters();
}

Alternatively, if you only want to be able to format results as XML, but don't need to be able to read XML from a request body, you can just add the output formatter instead:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
    });
}

For Supporting XML as Input

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.FormatterMappings.SetMediaTypeMappingForFormat
            ("xml", MediaTypeHeaderValue.Parse("application/xml"));
        options.FormatterMappings.SetMediaTypeMappingForFormat
            ("config", MediaTypeHeaderValue.Parse("application/xml"));
        options.FormatterMappings.SetMediaTypeMappingForFormat
            ("js", MediaTypeHeaderValue.Parse("application/json"));
    })
        .AddXmlSerializerFormatters();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Patrick Beynio
Solution 2 Mayur
Solution 3 Grandevox