从 .NET Core 将 XML 数据发布到 REST 端点

问题描述 投票:0回答:2

我有一个外部用户正在尝试通过 SOAP(XML 格式)将数据 POST 到我的端点。但是,我的代码是 .NET 6 REST APi。我将 XML 有效负载转换为一个类并设法生成该类。以下是 XML 输出:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <soapenv:Header/>
            <soapenv:Body>
                            <PaymentNotificationRequest>
                                            <User>USER</User>
                                            <Password>pass</Password>
                            <HashVal>NzIwNGE3MzI5YmU5MTg3ZTUwZTQ1YmRjMjA0NDc2MjUyODQ2MmQ1ODIwZTIyYzNkNDk0NTBjNjUwZTgwYmM2Yw==</HashVal>
                                            <TransType>999</TransType>
                                            <TransID>FTC221024YAWQ</TransID>
                                            <TransTime>2210241702</TransTime>
                                            <TransAmount>1.00</TransAmount>
                                            <AccountNr>6592460859</AccountNr>
                                            <Narrative>Test</Narrative>
                                            <PhoneNr>66666</PhoneNr>
                                            <CustomerName>Customer 1</CustomerName>
                                            <Status>SUCCESS</Status>
                            </PaymentNotificationRequest>
            </soapenv:Body>
</soapenv:Envelope>

我的控制器为:

    [HttpPost]
    [Consumes("application/xml")]
    [Produces("application/xml")]
    public dynamic Post([FromBody] MYDATA mymodel)
    {
        int createdId = mpesaRepository.Add(mymodel);
        if (createdId > 0)
        {
            mymodel.TransType = createdId;
        }
        dynamic result = new
        {
            data = new
            {
                ID = createdId,
                mymodel.User,
                mymodel.Password,
                mymodel.HashVal,
                mymodel.TransType,
                mymodel.TransID,
                mymodel.TransTime,
                mymodel.TransAmount,
                mymodel.AccountNr,
                mymodel.Narrative,
                mymodel.PhoneNr,
                mymodel.CustomerName,
                mymodel.Status
            },
        };
        return result;
    }

通过 PostMan 发布数据时,会生成以下 404 错误

<MVC-Errors>
    <MVC-Empty>An error occurred while deserializing input data.</MVC-Empty>
    <mymodel>The mymodel field is required.</mymodel>
</MVC-Errors>

在我的 Program.cs 上,我已经启用了

            services.AddControllers(options =>
        {
            options.RespectBrowserAcceptHeader = true;
        }).AddXmlSerializerFormatters()
        .AddXmlDataContractSerializerFormatters();

下面是我的类从 XML 翻译而来:

    [XmlRoot(ElementName = "PaymentNotificationRequest")]
public class PaymentNotificationRequest
{
    [XmlElement(ElementName = "ID")]
    public int ID { get; set; }
    [XmlElement(ElementName = "User")]
    public string User { get; set; }

    [XmlElement(ElementName = "Password")]
    public string Password { get; set; }

    [XmlElement(ElementName = "HashVal")]
    public string HashVal { get; set; }

    [XmlElement(ElementName = "TransType")]
    public long TransType { get; set; }

    [XmlElement(ElementName = "TransID")]
    public string TransID { get; set; }

    [XmlElement(ElementName = "TransTime")]
    public string TransTime { get; set; }

    [XmlElement(ElementName = "TransAmount")]
    public string TransAmount { get; set; }

    [XmlElement(ElementName = "AccountNr")]
    public long AccountNr { get; set; }

    [XmlElement(ElementName = "Narrative")]
    public string Narrative { get; set; }

    [XmlElement(ElementName = "PhoneNr")]
    public string PhoneNr { get; set; }

    [XmlElement(ElementName = "CustomerName")]
    public string CustomerName { get; set; }

    [XmlElement(ElementName = "Status")]
    public string Status { get; set; }
}

[XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
    [XmlElement(ElementName = "PaymentNotificationRequest")]
    public PaymentNotificationRequest NCBAPaymentNotificationRequest { get; set; }

    [XmlAttribute(AttributeName = "soapenv", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string Soapenv { get; set; }
}
xml asp.net-mvc rest soap asp.net-core-6.0
2个回答
3
投票

更新2:

请您将您的

program.cs
修改如下:

builder.Services.AddMvc(config =>
{

}).AddXmlSerializerFormatters();

应放置在

builder.Build
之前,请参阅屏幕截图以供参考。

enter image description here

更新:

根据您的评论,您给出的

XML
模型似乎不正确。请参考以下课程:

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://schemas.xmlsoap.org/soap/envelope/", IsNullable = false)]
public partial class Envelope
{

    private object headerField;

    private EnvelopeBody bodyField;

  
    public object Header
    {
        get
        {
            return this.headerField;
        }
        set
        {
            this.headerField = value;
        }
    }

   
    public EnvelopeBody Body
    {
        get
        {
            return this.bodyField;
        }
        set
        {
            this.bodyField = value;
        }
    }
}


[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public partial class EnvelopeBody
{

    private PaymentNotificationRequest paymentNotificationRequestField;

  
    [System.Xml.Serialization.XmlElementAttribute(Namespace = "")]
    public PaymentNotificationRequest PaymentNotificationRequest
    {
        get
        {
            return this.paymentNotificationRequestField;
        }
        set
        {
            this.paymentNotificationRequestField = value;
        }
    }
}


[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class PaymentNotificationRequest
{

    private string userField;

    private string passwordField;

    private string hashValField;

    private ushort transTypeField;

    private string transIDField;

    private uint transTimeField;

    private decimal transAmountField;

    private ulong accountNrField;

    private string narrativeField;

    private uint phoneNrField;

    private string customerNameField;

    private string statusField;

    
    public string User
    {
        get
        {
            return this.userField;
        }
        set
        {
            this.userField = value;
        }
    }

  
    public string Password
    {
        get
        {
            return this.passwordField;
        }
        set
        {
            this.passwordField = value;
        }
    }

  
    public string HashVal
    {
        get
        {
            return this.hashValField;
        }
        set
        {
            this.hashValField = value;
        }
    }


    public ushort TransType
    {
        get
        {
            return this.transTypeField;
        }
        set
        {
            this.transTypeField = value;
        }
    }

   
    public string TransID
    {
        get
        {
            return this.transIDField;
        }
        set
        {
            this.transIDField = value;
        }
    }

  
    public uint TransTime
    {
        get
        {
            return this.transTimeField;
        }
        set
        {
            this.transTimeField = value;
        }
    }

   
    public decimal TransAmount
    {
        get
        {
            return this.transAmountField;
        }
        set
        {
            this.transAmountField = value;
        }
    }

  
    public ulong AccountNr
    {
        get
        {
            return this.accountNrField;
        }
        set
        {
            this.accountNrField = value;
        }
    }

   
    public string Narrative
    {
        get
        {
            return this.narrativeField;
        }
        set
        {
            this.narrativeField = value;
        }
    }

  
    public uint PhoneNr
    {
        get
        {
            return this.phoneNrField;
        }
        set
        {
            this.phoneNrField = value;
        }
    }

 
    public string CustomerName
    {
        get
        {
            return this.customerNameField;
        }
        set
        {
            this.customerNameField = value;
        }
    }

  
    public string Status
    {
        get
        {
            return this.statusField;
        }
        set
        {
            this.statusField = value;
        }
    }
}

注意:我已经使用

model
生成了这个
visual studio IDE
。您只需复制粘贴即可模拟测试。

我有一个外部用户正在尝试通过以下方式将数据发布到我的端点 SOAP(XML 格式)。但是,我的代码是 .NET 6 REST API。

嗯,

program.cs
中的代码片段似乎是正确的,
 XML output
也是有效的。但是,您的控制器似乎不正确。您无法将
XML Object
接收为
[FromBody]
,因此无法接收
model
。您将收到
XML string
然后
node
应该解析。您可以按照以下步骤操作:

控制器:

        [HttpPost]
        [Produces("application/xml")]
        [Consumes("application/xml")]
        public async Task<ActionResult> PostAsync()
        {
            string xml;
            using (System.IO.StreamReader reader = new System.IO.StreamReader(Request.Body, Encoding.UTF8))
            {
                xml = await reader.ReadToEndAsync();
            }
            XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
            using (TextReader reader = new StringReader(xml))
            {
                Envelope result = (Envelope)serializer.Deserialize(reader);
                //You can save your object to your repository/database here
                return Ok(result);

            }


        }

输出:

enter image description here

enter image description here

请求应从 HTTP 客户端发送:

 public async Task<object> PostXMLRequestAspNet6API()
        {

            try
            {
               
                var handler = new HttpClientHandler();
                handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
                var client = new HttpClient(handler);

                string xmlString = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"> <soapenv:Header/> <soapenv:Body> <PaymentNotificationRequest> <User>USER</User> <Password>pass</Password> <HashVal>NzIwNGE3MzI5YmU5MTg3ZTUwZTQ1YmRjMjA0NDc2MjUyODQ2MmQ1ODIwZTIyYzNkNDk0NTBjNjUwZTgwYmM2Yw==</HashVal> <TransType>999</TransType> <TransID>FTC221024YAWQ</TransID> <TransTime>2210241702</TransTime> <TransAmount>1.00</TransAmount> <AccountNr>6592460859</AccountNr> <Narrative>Test</Narrative> <PhoneNr>66666</PhoneNr> <CustomerName>Customer 1</CustomerName> <Status>SUCCESS</Status> </PaymentNotificationRequest> </soapenv:Body> </soapenv:Envelope>";

                var httpContent = new StringContent(xmlString, Encoding.UTF8, "application/xml");
                client.DefaultRequestHeaders.Accept.Clear();

                var sendRequest = await client.PostAsync("http://localhost:4400/home/PostAsync", httpContent);
                if (sendRequest.IsSuccessStatusCode == false)
                {
                    return null;
                }
                else
                {
                    //Read the response
                    var data = await sendRequest.Content.ReadAsStringAsync();
                   return data;
                }
            }
            catch (Exception ex)
            {

                throw;
            }

        }

0
投票

var xmlresp = 等待 _genServ.CallXml(_fcubsettings.FcubSwiftRequestPath, postxml, true);

 public async Task<GenericResponse> CallXml(string url, string XmlRequest, bool log = false, IDictionary<string, string> header = null)

{ 尝试 { var client = new RestClient(url); 客户端.超时= -1; var request = new RestRequest(Method.POST); request.AddHeader("Content-Type", "text/xml"); request.AddParameter("application/xml", XmlRequest, ParameterType.RequestBody); _logger.LogInformation($"网址 - {url}"); _logger.LogInformation($"{url} -- 请求 - {XmlRequest}");

     //ServicePointManager
     // .ServerCertificateValidationCallback +=
     // (sender, cert, chain, sslPolicyErrors) => true;

     if (header != null)
         foreach (var item in header)
             request.AddHeader(item.Key, item.Value);

     IRestResponse response = await client.ExecuteAsync(request);

     if (log)
         _logger.LogInformation($"{url} -- Response: StatusCode - {response.StatusCode}; ErrorMessage - {response.ErrorMessage}; Content - {response.Content}");
     return new GenericResponse() { Message = response.Content, Success = response.IsSuccessful, Response = EnumResponse.Successful };
 }
 catch (Exception ex)
 {
     _logger.LogError(ex.Message + " " + ex.StackTrace);
     return new GenericResponse() { Message = ex.Message, Response = EnumResponse.SystemError };
 }

}

    public class GenericResponse
{
    public bool Success { get; set; }
    public EnumResponse Response { get; set; }
    public string ResponseMessage => Response.GetDescription();
    public string Message { get; set; }
}
© www.soinside.com 2019 - 2024. All rights reserved.