Invoke a SOAP method with namespace prefixes - c#

My C# web service client sends following soap message to Java-based web service:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<getData>
<request>
<requestParameters xmlns="http://b...">
<equals>
...
</equals>
</requestParameters>
</request>
</getData>
</soap:Body>
</soap:Envelope>
and Java-based web service returns error:
500 Internal Server Error
...
Cannot find dispatch method for {}getData
...
Client written in Java, which works, sends the following message:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ns2:getData xmlns:ns2="http://a...">
<ns2:request>
<ns3:requestParameters xmlns:ns3="http://b...">
<ns3:equals>
...
</ns3:equals>
</ns3:requestParameters>
</ns2:request>
</ns2:getData>
</soap:Body>
</soap:Envelope>
Is there an easy way in C# to send SOAP messages the same way Java client sends: with namespace prefixes?
Following is C# code that sends message:
// class MyService is auto-generated using wsdl.exe tool
MyService service = new MyService();
RequestMessage request = new RequestMessage();
...
ResponseMessage response = service.getData(request);
...
UPDATE:
Here is RequestMessage class:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "3.0.4506.2152")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://uri.etsi.org/02657/v1.5.1#/RetainedData")]
public partial class RequestMessage
{
private byte[] requestPriorityField;
private RequestConstraints requestParametersField;
private string deliveryPointHIBField;
private string maxHitsField;
private NationalRequestParameters nationalRequestParametersField;
private System.Xml.XmlElement anyField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="hexBinary", Order=0)]
public byte[] requestPriority
{
get
{
return this.requestPriorityField;
}
set
{
this.requestPriorityField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=1)]
public RequestConstraints requestParameters
{
get
{
return this.requestParametersField;
}
set
{
this.requestParametersField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=2)]
public string deliveryPointHIB
{
get
{
return this.deliveryPointHIBField;
}
set
{
this.deliveryPointHIBField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="integer", Order=3)]
public string maxHits
{
get
{
return this.maxHitsField;
}
set
{
this.maxHitsField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=4)]
public NationalRequestParameters nationalRequestParameters
{
get
{
return this.nationalRequestParametersField;
}
set
{
this.nationalRequestParametersField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute(Order=5)]
public System.Xml.XmlElement Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
}
UPDATE #2:
The reason why Java-based web service didn't like my C# client produced SOAP message is not omission of namespace prefixes, but only because of omission of xmlns in getData element, so if my message looks like this:
...
<getData xmlns="http://a...">
...
</getData>
...
it works!
I managed to put xmlns inside getData by manually editing SoapRpcMethodAttribute in wsdl.exe-produced source code. Here is excerpt:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(
Name="AxxxPortTypeBinding", Namespace="http://a...")]
public partial class AxxxService
: System.Web.Services.Protocols.SoapHttpClientProtocol {
...
/// <remarks/>
[System.Web.Services.Protocols.SoapRpcMethodAttribute(
"http://a.../getData",
RequestNamespace = "http://a...",
ResponseNamespace = "http://a...",
Use = System.Web.Services.Description.SoapBindingUse.Literal)]
[return: System.Xml.Serialization.XmlElementAttribute("response")]
public ResponseMessage getData(RequestMessage request) {
object[] results = this.Invoke("getData", new object[] {
request});
return ((ResponseMessage)(results[0]));
}
...
}
Before my change, SoapRpcMethodAttribute had following constructor:
[System.Web.Services.Protocols.SoapRpcMethodAttribute(
"", RequestNamespace = "", ResponseNamespace = "",
Use = System.Web.Services.Description.SoapBindingUse.Literal)]
Now, the question is: what to put in WSDL file so that SoapRpcMethodAttribute have those strings in constructor (filled by the wsdl.exe tool) in the first place?

I've seen this problem before where the WSDL.exe tool did not properly pull in the namespace when generating the service code. Check the request object definition in your generated code. My guess is that there is no XmlRootAttribute attribute defined on the class definition for the request object.
Adding the attribute [XmlRootAttribute(Namespace "http://a...")] to the class definition for the request object should fix this issue.
As a side note, I recommend adding this additional attribute in a separate code file using a partial class definition. Defining the attribute in a separate file will allow you to regenerate the web service code using WSDL.exe whenever neccessary without overwriting the fix to set the root element's namespace properly.

The generated proxy class should have had the correct namespace in it. I recommend two things:
1) Run WSDL.EXE from the command line and note whether there are any errors or warnings. If so, please edit your question to include them.
2) Unless you are stuck using .NET 2.0, you should try to create your proxy classes using either "Add Service Reference" or the equivalent "SVCUTIL.EXE" these will use the modern, WCF infrastructure on the client side, which is much more likely to have been fixed to resolve this problem.

I had the same issue and solved it changing the value of the property Use in System.Web.Services.Protocols.SoapDocumentMethodAttribute attribute corrisponding to each web service method.
The System.Web.Services.Description.SoapBindingUse.Literal default value was replaced with System.Web.Services.Description.SoapBindingUse.Encoded.

Related

c# .net SOAP API add a prefix to namespace

We are calling a SOAP Service using .net in C#. We added the service reference. We receive an error when calling the method using the api. Our vendor determined that we are not sending a prefix in the namespace. I have included the .net generated code from the resources.cs file. My question is how can we add a prefix to the existing class in order to resolve the issue.
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="getLocationsByCriteria", WrapperNamespace="http://services.timecommerce.timetrade.com/ws", IsWrapped=true)]
public partial class getLocationsByCriteriaRequest {
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://services.timecommerce.timetrade.com/ws", Order=0)]
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public SystemRefresh.ConfigurationServices.locationSearchCriteria locationSearchCriteria;
public getLocationsByCriteriaRequest() {
}
public getLocationsByCriteriaRequest(SystemRefresh.ConfigurationServices.locationSearchCriteria locationSearchCriteria) {
this.locationSearchCriteria = locationSearchCriteria;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="getLocationsByCriteriaResponse", WrapperNamespace="http://services.timecommerce.timetrade.com/ws", IsWrapped=true)]
public partial class getLocationsByCriteriaResponse {
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://services.timecommerce.timetrade.com/ws", Order=0)]
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public SystemRefresh.ConfigurationServices.locationListResult #return;
public getLocationsByCriteriaResponse() {
}
public getLocationsByCriteriaResponse(SystemRefresh.ConfigurationServices.locationListResult #return) {
this.#return = #return;
}
}
Working body tag in SOAP UI below
<soapenv:Body>
<ws:getLocationsByCriteria>
<locationSearchCriteria>
<locationExternalId>sonoram3n</locationExternalId>
<locationGroupId>0</locationGroupId>
</locationSearchCriteria>
</ws:getLocationsByCriteria>
</soapenv:Body>
Failing tags from the current process below
<s:Body>
<getLocationsByCriteria>
<locationSearchCriteria>
<locationExternalId>sonoram3n</locationExternalId>
<locationGroupId>0</locationGroupId>
</locationSearchCriteria>
</getLocationsByCriteria>
</s:Body>

System.IndexOutOfRangeException on SalesForce OutBound Message Listener

I have a webservice in ASMX and I am trying to create a Listener and here is what I have in the webservice.cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Services;
using System.Web.Services;
/// <summary>
/// Summary description for WebService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
class MyNotificationListener : NotificationBinding
{
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public notificationsResponse Notifications(notifications n)
{
Method.SendMail("info#domain.com", "test#domain.com", "Here I am ", "I am loaded ", "", "");// This is to see if it loaded
notificationsResponse r = new notificationsResponse();
r.Ack = true;
return r;
}
}
in my outboun message configuration I am calling this webservice like so www.domain/webservice.asmx/Notification but when I load this service I See the following:
`System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.Web.Services.Protocols.HttpServerType..ctor(Type type)
at System.Web.Services.Protocols.HttpServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)`
In my config file I have the following
`<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
<add name="HttpSoap" />
</protocols>
</webServices>`
Here is what I have in the Notification Object this was generated from WSDL file to a class using wsdl.exe as directed in this example.
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.7.3081.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://soap.sforce.com/2005/09/outbound")]
public partial class notifications
{
private string organizationIdField;
private string actionIdField;
private string sessionIdField;
private string enterpriseUrlField;
private string partnerUrlField;
private LeadNotification[] notificationField;
/// <remarks/>
public string OrganizationId {
get {
return this.organizationIdField;
}
set {
this.organizationIdField = value;
}
}
/// <remarks/>
public string ActionId {
get {
return this.actionIdField;
}
set {
this.actionIdField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
public string SessionId {
get {
return this.sessionIdField;
}
set {
this.sessionIdField = value;
}
}
/// <remarks/>
public string EnterpriseUrl {
get {
return this.enterpriseUrlField;
}
set {
this.enterpriseUrlField = value;
}
}
/// <remarks/>
public string PartnerUrl {
get {
return this.partnerUrlField;
}
set {
this.partnerUrlField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Notification")]
public LeadNotification[] Notification {
get {
return this.notificationField;
}
set {
this.notificationField = value;
}
}
}
So, After looking at your code I see that in your webservice the implementation of the public interface is named wrong, when I generated the Class with a WSDL from salesforce it creates the interface and its named INotificationBinding not NotificationBinding which makes me think that you didn't create the class properly from the wsdl, in the example you shown above that you are following says to use wsdl.exe /serverInterface leads.wsdl.
Did you create the above class notification using the wsdl.exe ? if so did you make sure it was using the option of /serverInterface this is important(See image below), on salesforce it clearly mentions that you need to implement a class that calls the notification interface if this is not properly handled it will give the error of System.IndexOutOfRangeException
Please try again using the serverinterface option. That should fix the issue.
I think you can't reach this method because you try to pass an object : "notifications n"
and using a GET request.
you can't do GET to this method.
anyway the Exception you describe does not seem to be related. it's in your code .
try to share the Code you use to consume this service

SOAP Request format

I am trying to create a SOAP web service to use with a client.
According to the documentation, we have to create a web service with two methods that return certain information. I have created them without a problem, but I can not get them to fit the example format.
I have to say that for years I did not create any SOAP services (since Net 2.0) because I have been doing REST services for a long, so if you see any nonsense, forgive me.
The example request that there is in the documentation (the good one) is this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pag="http://pagorecibos.pagosrecibos.com/">
<soapenv:Header/>
<soapenv:Body>
<pag:obtenerImporte>
<referencia>040</referencia>
</pag:obtenerImporte>
</soapenv:Body>
</soapenv:Envelope>
That's the format that my service want to recieve:
<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>
<obtenerImporte xmlns="http://tempuri.org/">
<referencia>string</referencia>
</obtenerImporte>
</soap:Body>
</soap:Envelope>
The code of my service is this:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service: System.Web.Services.WebService
{
[WebMethod]
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
public string ObtenerImporte(ObtenerImporte obtenerImporte)
{
return "Hola a todos";
}
[WebMethod]
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
public string RealizarPago(RealizarPago realizarPago)
{
return "Hola a todos";
}
}
Class (the other class is similar):
public class ObtenerImporte
{
[XmlElement("referencia")]
public string Referencia { get; set; }
}
The difference is in the namespace and the prefix in node "obtenerImporte" but I can't resolve it.
I'm using VS2017 Community Edition y created the project using "ASP.NET Web Service" template.
Problem solved!!!. Adding and removing code.... suddenly it works :D. The right way to define the service is this (thanks #zaitsman for your clue):
[WebService(Namespace = "http://pagorecibos.pagosrecibos.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
[WebMethod]
[SoapDocumentMethod(Use = SoapBindingUse.Literal, ParameterStyle = SoapParameterStyle.Bare)]
public string ObtenerImporte(ObtenerImporte obtenerImporte)
{
return "Obtener Importe";
}
[WebMethod]
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
public string RealizarPago(RealizarPago realizarPago)
{
return "Realizar Pago";
}
}
I hope that this solution could help other one.

Receiving eBay SOAP notification messages

I am trying to receive notifications using ebay and their SDK. I have managed to find a working example using an ASP.net web service. However I want to be able to host this on Azure and moving this to a WCF seems like a suitable solution. I have tried doing so and the closest I have got is getting a xml serializer error like below:
The server encountered an error processing the request. The exception message is 'Unable to deserialize XML body with root name 'Envelope' and root namespace 'http://schemas.xmlsoap.org/soap/envelope/' (for operation 'GetOutBid' and contract ('IReceiver', 'urn:ebay:apis:eBLBaseComponents')) using XmlSerializer. Ensure that the type corresponding to the XML is added to the known types collection of the service.'
From what I have seen online, looks like it could be to do with how the datacontract should be setup - I'm new to WCF, so not sure!
Below is what is working in the web service which I'm trying to put into WCF:
[WebMethod()]
[System.Web.Services.Protocols.SoapHeaderAttribute("RequesterCredentials", Direction = System.Web.Services.Protocols.SoapHeaderDirection.In)]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute(Action = "http://developer.ebay.com/notification/OutBid", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Bare)]
public void OutBid(GetItemResponseType GetItemResponse)
{
if (CheckSignature(GetItemResponse.Timestamp))
{
//Implement your own business logic here
}
else
{
//Implement your own business logic here
}
LogRequest(Server.MapPath("files/OutBid_" + GetItemResponse.Item.ItemID + "_" + GetItemResponse.Item.SellingStatus.BidCount.ToString() + "_" + GetItemResponse.CorrelationID + ".xml"));
}
public class student { public int rollno { get; set; } }
public class school { public student obj { get; set; } }
class Program
{
static void Main(string[] args)
{
school obje = new school(); obje.obj.rollno = 2; Console.WriteLine(obje.obj.rollno);
}
}
Based on your code, I found that the protocol between the service and client is SOAP. To support SOAP, we need to use basicHttpBinding in WCF. The protocolMapping configuration section in web.config should be like this.
<protocolMapping>
<add binding="basicHttpBinding" scheme="http"/>
</protocolMapping>
After that, we could define the service contact and service to handle requests.
The service contact could be like this.
[ServiceContract]
public interface IService1
{
[OperationContract(Action= "http://developer.ebay.com/notification/OutBid")]
string OutBid(school value);
}
A sample of Service.
public class Service1 : IService1
{
public string OutBid(school value)
{
return string.Format("The rollno is {0}", value.obj.rollno);
}
}
Following are my test results.
Sample request.
<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://developer.ebay.com/notification/OutBid</Action>
</s:Header>
<s:Body>
<OutBid xmlns="http://tempuri.org/">
<value xmlns:d4p1="http://schemas.datacontract.org/2004/07/TestSOAP" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<d4p1:obj>
<d4p1:rollno>2</d4p1:rollno>
</d4p1:obj>
</value>
</OutBid>
</s:Body>
</s:Envelope>
Sample result.
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<OutBidResponse xmlns="http://tempuri.org/">
<OutBidResult>The rollno is 2</OutBidResult>
</OutBidResponse>
</s:Body>
</s:Envelope>
If you can't finish the work on your side, please post your sample XML request content for further discussion.

Remove xml header from C# webservice

I need to build an API using C# webservice, which needs to return values in json format.
Currently I have the following lines of code
namespace WebService1
{
/// <summary>
/// Summary description for Service1
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return new JavaScriptSerializer().Serialize(new { errMsg = "test" });
}
}
}
The output of this when the post method is invoked is
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">{"errMsg":"test"}</string>
But this isn't a valid json how do I make the webservice return the json object only and not the xml headers?
Calling this webservice with header Content-Type: application/json will automatically transform the response to json and your xml will be gone.

Categories