我有一个外部用户正在尝试通过 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; }
}
更新2:
请您将您的
program.cs
修改如下:
builder.Services.AddMvc(config =>
{
}).AddXmlSerializerFormatters();
应放置在
builder.Build
之前,请参阅屏幕截图以供参考。
更新:
根据您的评论,您给出的
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);
}
}
输出:
请求应从 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;
}
}
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; }
}