Change XML Tag Prefix SOAP - c#

I am trying to create a SOAP message with the prefix. however, I am having trouble setting the namespace correctly. I have been trying for days and tried many suggestions I found online, but none seem to work. I am hoping some of you can help me.
What I'm getting is
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Transaction xmlns="http://tempuri.org/">
<bankingTransaction>
<operation parameterOrder="string">
<fault />
<fault />
</operation>
<transactionDate>dateTime</transactionDate>
<amount>int</amount>
</bankingTransaction>
</Transaction>
</soap:Body>
</soap:Envelope>
& what I actually need is
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<res:Transaction xmlns="res:http://tempuri.org/">
<res:bankingTransaction>
<res:operation parameterOrder="string">
<res:fault />
<res:fault />
</res:operation>
<res:transactionDate>dateTime</res:transactionDate>
<res:amount>int</res:amount>
</res:bankingTransaction>
</res:Transaction>
</soap:Body>
</soap:Envelope>
& My MassageContact is
[MessageContract]
public class BankingTransaction
{
[MessageHeader] public Operation operation;
[MessageHeader] public DateTime transactionDate;
[MessageBodyMember] private unit sourceAccount;
[MessageBodyMember] public int amount;
}
Please Help me to add prefix with my XML Elements.
Thanks

You probably need to do something like this:
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://tempuri.org/")]
[MessageContract]
public class BankingTransaction
{
[MessageHeader] public Operation operation;
[MessageHeader] public DateTime transactionDate;
[MessageBodyMember] private unit sourceAccount;
[MessageBodyMember] public int amount;
}
I am not sure how you are serializing your objects, but something like this will add the prefix:
XmlSerializerNamespaces x = new XmlSerializerNamespaces();
x.Add("res", "http://tempuri.org/");
add the XmlSerializerNamespaces to you serialization process maybe? It's hard to say without seeing what else you are doing. All your contracts/classes in that namespace probably need this attribute: [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://tempuri.org/")]

We could create a MessageFormatter to customize the message format, you could refer to the following official tutorial.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/extending/custom-message-formatters
Here is an example about how to do this.
https://stackoverflow.com/questions/31595770/c-sharp-wcf-global-namespaces-royal-mail/31597758#31597758
http://vanacosmin.ro/Articles/Read/WCFEnvelopeNamespacePrefix

Related

SOAP serialization ignoring object but including its data members in C#

I have an existing SOAP method which has a huge number of parameters, e.g.
[OperationContract]
public ResultObject DoSomeAction(string a, string b, DateTime c, OtherEnum d,
string e, string f, ....)
Which results in
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<DoSomeAction>
<xs:element minOccurs="0" maxOccurs="1" name="a" type="xs:string"/>
...
</DoSomeAction>
</soapenv:Body>
</soapenv:Envelope>
Ideally I'd like to factor out these into an object without changing the SOAP WSDL, so that the code could look more like
[OperationContract]
public ResultObject DoSomeAction(RequestObject request)
[DataContract]
public class RequestObject
{
[DataMember]
public string a { get; set; }
...
}
However I can't seem to find the correct way to add an attribute to serialize only the properties of Request Object and not the object itself.
Are there any way to define the Request Object that that the resulting SOAP will end up the same?
You can do this using MessageContract instead of DataContract this gives you more control over the message. For this to work you have to also wrap the result object in a message contract object to get exactly the same.
Here is a sample of your objects changed to message contracts.
[MessageContract(WrapperName="DoSomeActionResponse")]
public class ResponseMessage
{
[MessageBodyMember(Name="DoSomeActionResult")]
public ResultObject ResultObject { get; set; }
}
[MessageContract(WrapperName = "DoSomeAction")] // renames the element to DoSomeAction
public class RequestObject
{
[MessageBodyMember]
public string a { get; set; }
[MessageBodyMember]
public string b { get; set; }
[MessageBodyMember]
public DateTime c { get; set; }
[MessageBodyMember]
public int d { get; set; }
[MessageBodyMember]
public string e { get; set; }
[MessageBodyMember]
public string f { get; set; }
}
And the operation contract becomes like this.
[OperationContract]
ResponseMessage DoSomeAction(RequestObject requestObject);
For more details on how to use message contracts check also the official documentation.
Due to your comment I post also the requests for both method declaration so you see it is the same.
Your original:
[OperationContract]
ResultObject DoSomeAction(string a, string b, DateTime c, int d, string e, string f);
And the SOAP request and response look like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IService1/DoSomeAction</Action>
</s:Header>
<s:Body>
<DoSomeAction xmlns="http://tempuri.org/">
<a i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
<b i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
<c>2020-04-05T02:04:00</c>
<d>0</d>
<e i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
<f i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
</DoSomeAction>
</s:Body>
</s:Envelope>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<DoSomeActionResponse xmlns="http://tempuri.org/">
<DoSomeActionResult xmlns:a="http://schemas.datacontract.org/2004/07/WcfService1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:ResultValue>12</a:ResultValue>
</DoSomeActionResult>
</DoSomeActionResponse>
</s:Body>
</s:Envelope>
And the request and response from the message contact methods so you see it is the same:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IService1/DoSomeAction</Action>
</s:Header>
<s:Body>
<DoSomeAction xmlns="http://tempuri.org/">
<a i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
<b i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
<c>2020-04-05T02:03:00</c>
<d>0</d>
<e i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
<f i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
</DoSomeAction>
</s:Body>
</s:Envelope>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<DoSomeActionResponse xmlns="http://tempuri.org/">
<DoSomeActionResult xmlns:a="http://schemas.datacontract.org/2004/07/WcfService2" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:ResultValue>11</a:ResultValue>
</DoSomeActionResult>
</DoSomeActionResponse>
</s:Body>
</s:Envelope>

SoapFormatter - how to include namespaces?

I have a blocker which I cannot solve. Issue is in auto-generated SOAP request built by SoapFormatter class. I'm trying to communicate with WCF service and pass some data. I've implemented class which I am trying to serialize to soap request.
[Serializable]
public class MySoapClass: ISerializable
{
public string Username{ get; set; }
public string Password{ get; set; }
public int Data3 { get; set; }
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.FullTypeName = "ThisIsNameIWantInSoap";
info.AddValue("Username", Username);
info.AddValue("Password", Password);
info.AddValue("Data3", Data3);
}
}
I'm using MemoryStream and MySoapClass object in SoapFormatter. I am getting soap string this way Encoding.UTF8.GetString(stream.GetBuffer(), 0, (int)stream.Position)
Generated soap string does not work, request is delivered, but I am getting "authentication error", just like WCF service could not extract any data from request.
This is auto-generated soap string:
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:ThisIsNameIWantInSoap id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/assem/http://tempuri.org/">
<Username id="ref-1">username</Username>
<Password id="ref-2">password</Password>
<Data3>10</Data3>
</a1:ThisIsNameIWantInSoap>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
After copying soap string to SoapUI and adding namespace tag to every parameter, everything works fine. I am getting proper response from WCF service.
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:ThisIsNameIWantInSoap id="ref-1" xmlns:a1="http://tempuri.org/">
<a1:Username id="ref-1">username</a1:Username>
<a1:Password id="ref-2">password</a1:Password>
<a1:Data3>10</a1:Data3>
</a1:ThisIsNameIWantInSoap>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
My questions are:
-How to auto-generate soap string which includes "a1:" namespace tag in every parameter?
-(Answered) How to change "a1:" namespace to"somethingElse:"?

SOAP Web service custom soap xml response

This is my XML response soap (WS in c# ".asmx") :
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<TestrequestResponse xmlns="http://tempuri.org/">
<TestrequestResult>
<name>filename.xml</name>
<code>30</code>
</TestrequestResult>
</TestrequestResponse>
</soap:Body>
</soap:Envelope>
I want to have a response like this :
<?xml version="1.0" encoding="utf-8"?>
<Response result=”KO”>
<name>filename.xml</name>
<code>30</code>
</Response>
how can I do this?
Thank you very much for your help.
edit :
[WebMethod]
public Response Testrequest()
{
var r = new Response();
r.name = "30";
r.code = "0";
return r;
}
object response :
public class Response
{
public string name { get; set; }
public string code { get; set; }
}
You may do SOAP message formatting ( https://msdn.microsoft.com/en-us/library/dkwy2d72%28v=vs.100%29.aspx ), but creating a simple web page returning the desired format instead of calling a SOAP service is easier.

XML Serialize and Deserialize Issue for Complicated XML

My XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ServerConfig loggingEnabled="1">
<Servers id="2" host="mytest">
<Server host="test1.example.com" port="9999" >
<Name id="newname1">
<FirstName id="myfirstname">hello first name</FirstName>
<SecondName id="myfirstname">hello first name</SecondName>
</Name>
</Server>
<Server host="test2.example.com" port="8888" />
</Servers>
<Servers id="1">
<Server host="test3.example.com" port="9899" >
<Name id="newname2">
<FirstName id="myfirstname">hello first name</FirstName>
</Name>
</Server>
<Server host="test4.example.com" port="8988" />
</Servers>
</ServerConfig>
I want to deserialize this xml to my class
Class
public sealed class ServerConfig
{
public sealed class Server
{
[XmlAttribute("host")]
public string Host { get; set; } // gives me host name
[XmlAttribute("port")]
public int Port { get; set; } // gives my prot number
}
[XmlArray]
public List<Server> Servers { get; set; } // gives me all 4 server lsit
[XmlAttribute("loggingEnabled")]
public int LoggingEnabled { get; set; } // gives me attribute detail
public ServerConfig()
{
Servers = null;
LoggingEnabled = 0;
}
}
Problem
My Problem is I don't know how to access the Attributes of the nested Element Name and sub nested element FirstName/SecondName
WIll be really very thankful.
Thanks.
The simplest way is being provided by Microsoft in VS 2012 onwards which is being brilliantly explained in this link.
XML TO C# Class
All you need to do is copy your xml and then paste special to a class as explained in the link.
Happy Coding.
Thanks,

List Collection XML Serialization

I've been playing around with the xml serialization for a while and I've hit a problem with serializing the a list collection. I want to serialize a list collection without the upper element wrapping around it. See example below:
Result serialization:
<?xml version="1.0" encoding="utf-8" ?>
<Person>
<Name>John</Name>
<AddressLine>
<string>Line 1</string>
<string>Line 2</string>
<string>Line 3</string>
</AddressLine>
<Telephone>123456789</Telephone>
</Person>
The serialization I want to output is:
<?xml version="1.0" encoding="utf-8" ?>
<Person>
<Name>John</Name>
<AddressLine>Line 1</AddressLine>
<AddressLine>Line 2</AddressLine>
<AddressLine>Line 3</AddressLine>
<Telephone>123456789</Telephone>
</Person>
I have tried setting different the attributes to my class I'm serializaing from but I can't seem to get anywhere with it. If anyone could show me what attributes I need to use to get my xml serialization to look like the ouput xml I want that would be greatly appreciated.
Cheers!
[Serializable]
public class Person
{
public string Name { get; set; }
[XmlElement]
public List<string> AddressLine { get; set; }
}
Produces desired output:
<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>John</Name>
<AddressLine>1</AddressLine>
<AddressLine>2</AddressLine>
<AddressLine>3</AddressLine>
</Person>

Categories