c# .net SOAP API add a prefix to namespace - c#

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>

Related

How to pass a SAML object to do authentication in Webservice using System.ServiceModel.ClientBase

I have a project that consumes a service. When I added the service reference in the solution, I noticed that the service extends the "System.Model.ClientBase" class, right?
Well, when I instantiate this service, I need to pass a SAML object in the header, to authenticate.
The problem is that I can't get it to work. Let me show my code:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class CreditApplicationRequest{
[System.ServiceModel.MessageHeaderAttribute(Namespace="http://www.mycompany.com/HeaderDataXMLS")]
public headerData headerData;
// I inserted this one here.
[System.ServiceModel.MessageHeaderAttribute(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")]
Security security;
[System.ServiceModel.MessageBodyMemberAttribute(Name="MyRequest", Namespace="http://www.mycompany.com/types", Order=0)]
public CreditApplicationRequestType creditApplicationRequestType;
public CreditApplicationRequest() {
}
public CreditApplicationRequest(
headerData headerData,
Security security,
CreditApplicationRequestType creditApplicationRequestType) {
this.headerData = headerData;
this.security = security;
this.creditApplicationRequestType = creditApplicationRequestType;
}
}
After that, we have:
public CreditApplicationResponseType CreditApplication(
ref headerData headerData,
Security security,
CreditApplicationRequestType creditApplicationRequestType) {
CreditApplicationRequest inValue = new CreditApplicationRequest();
inValue.headerData = headerData;
inValue.creditApplicationRequestType = creditApplicationRequestType;
inValue.security = security;
CreditApplicationResponse retVal = ((PortType (this)).CreditApplication(inValue);
headerData = retVal.headerData;
return retVal.SMBExistingCreditApplicationResponse1;
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
CreditApplicationResponse CreditApplication(CreditApplicationRequest request) {
// The error happens here
return base.Channel.CreditApplication(request);
}
When I try to connect, I receive the follow error message: OSB-386200: General web service security error
Any idea about this?

How can I specify a namespace for OperationContract when using WCF?

I am creating a client for a server api I can't change. My client currently produces this format:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<StoreSomething xmlns="urn:aaa">
<Something>
<SomeText xmlns="urn:bbb">My text</SomeText>
</Something>
</StoreSomething>
</s:Body>
</s:Envelope>
However, the server expects Something to be in the urn:bbb namespace (i.e. move the xmlns attribute one level up). How can I achieve this?
OperationContractAttribute has no Namespace property.
Code:
using System;
using System.ServiceModel;
using System.Xml.Serialization;
[XmlType(Namespace="urn:bbb")]
public class Something
{
public string SomeText { get; set; }
}
[XmlSerializerFormat]
[ServiceContract(Namespace="urn:aaa")]
public interface IMyService
{
[OperationContract]
void StoreSomething(Something Something);
}
class Program
{
static void Main(string[] args)
{
var uri = new Uri("http://localhost/WebService/services/Store");
var factory = new ChannelFactory<IMyService>(new BasicHttpBinding(), new EndpointAddress(uri));
IMyService service = factory.CreateChannel();
service.StoreSomething(new Something
{
SomeText = "My text"
});
}
}
I managed to get it working by using unwrapped messages. This unfortunately results in both the method name and parameter name being left out. I therefore had to create wrapper classes which results in convoluted code.
Anyway, here is the code that made it work:
[ServiceContract]
public interface IMyService
{
[OperationContract]
[XmlSerializerFormat]
void StoreSomething(StoreSomethingMessage message);
}
[MessageContract(IsWrapped=false)]
public class StoreSomethingMessage
{
[MessageBodyMember(Namespace="urn:aaa")]
public StoreSomething StoreSomething { get; set; }
}
[XmlType(Namespace="urn:bbb")]
public class StoreSomething
{
public Something Something { get; set; }
}
public class Something
{
public string SomeText { get; set; }
}
I also created a MyServiceClient which implements IMyService and inherits from ClientBase<IMyService> since IMyService now requires a StoreSomethingMessage object, but i left that part out for simplicity.
I wish there was a simpler solution.

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

WCF List<Stream> is creating own Stream:MarchalByRefObj type on client generated code

I am creating a WCF service for which I have to send a List as a Request,
[MessageContract]
public class DocumentMergerRequest
{
[MessageHeader]
public OutputDocumentFileFormat OutputFileFormat;
[MessageBodyMember(Order = 1)]
public List<Stream> DocumentsToMerge;
}
The Stream is System.IO.Stream and when I try to use the service, the client generated code contains
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.225")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.datacontract.org/2004/07/System.IO")]
public partial class Stream : MarshalByRefObject {
}
The generated Stream is of type MarshalByRefObject instead of System.IO.Stream.
How can I fix this.

Invoke a SOAP method with namespace prefixes

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.

Categories