Input parameters to web method becoming null - c#

I created a asmx service for existing client. The service works fine from SOAP UI but when called from external client the input parameters are becoming null. I tried calling the service from Console application using httpWebRequest (without adding service reference), the issue persists. This seems to be happening only when calling the service over https.
Oddly, the soapheader parameters are coming properly.
The client sends SoapAction as empty and cannot be modified hence used
[SoapDocumentMethodAttribute(Action = "")]
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Validate : System.Web.Services.WebService
{
private WSSEDraftSecurityHeader _security;
public WSSEDraftSecurityHeader Security
{
get { return _security; }
set { _security = value; }
}
[WebMethod]
[SoapDocumentMethodAttribute(Action = "")]
[SoapHeader("Security", Direction = SoapHeaderDirection.InOut)]
public ValidateResponse.validateResult validate(DateTime dt, string ac, string tc, string ot, string o, int sn, string bpb)
{
}
}
The Soap Request is:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <s:Header> <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <o:UsernameToken u:Id="uuid-9b091270-fad3-4cf7-bef5-58b9a57ed37e-9"> <o:Username>XXXXX</o:Username> <o:Password>iiiiii</o:Password> </o:UsernameToken> </o:Security> </s:Header> <s:Body> <validate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/"> <ac>SN</ac> <bpb>TTFD</bpb> <o>PXPXS1</o> <ot>port</ot> <sn>0</sn> <tc>T2</tc> <dt>2019-04-17T18:50:36.3259364+08:00</dt> </validate> </s:Body> </s:Envelope>
The web method is being called and passing the security header validation. But all string parameters coming as null and one date time parameter coming with default date of 01/01/0001

Maybe the issue is with the order of the parameters in Soap request, as they are listed in different order than in your method declaration. I would compare SOAP requests generated by SoapUI and Console app and then find the differences.

Related

How to access to differents methods of webservice with SOAPUI

I try to access to my webmethods with SOAP UI but it works only for the first one and I don't undestand why.
My Webservices methods :
[SoapHeader ("AuthenticationInfo", Required=true)]
[WebMethod(EnableSession = true)]
public string HelloWorld()
{
if (!(AuthenticationInfo.Username == "test" && AuthenticationInfo.Password == "test"))
{
throw new Exception();
// I put that in the aim to get an error, I'll modify this later
}
return "OK";
}
[SoapHeader("AuthenticationInfo", Required = true)]
[WebMethod]
public string Authenticate(string MethodName)
{
if (!(AuthenticationInfo.Username == "test" && AuthenticationInfo.Password == "test")
{
throw new Exception();
}
else
{
HelloWorld();
}
return "aaaa";
}
[WebMethod]
public int Calcul(int a, int b)
{
return a+b ;
}
When I put this XML in SOAP UI :
<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:Header>
<AuthHeader xmlns="http://tempuri.org/">
<Username>test</Username>
<Password>test</Password>
<key>string</key>
</AuthHeader>
</soap:Header>
<soap:Body>
<HelloWorld xmlns="http://tempuri.org/" />
</soap:Body>
</soap:Envelope
It works perfectly, I get the return of HelloWord() Method.
But if I put :
<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>
<Calcul xmlns="http://tempuri.org/">
<a>1</a>
<b>1</b>
</Calcul>
</soap:Body>
</soap:Envelope>
It invokes again HelloWorld() method. My URL which I use in SOAP UI is :"http://localhost:62353/MyWebService.asmx", so I try a new request with the last XML at the URL "http://localhost:62353/MyWebService.asmx/Calcul" and i have an error.
Have you I Idea ? May I'm in the wrong way to use SOAP UI ?
To reply to Kosala W :
I get an UI like that where I can click on the methods. The calcul methods works only here because this methos doesn't need the SoapHeader.
Here is the response :
When you specify the URL in SOAP UI you need to add ?wsdl at the end like that : http://localhost:62353/MyWebService.asmx?wsdl Then I refresh the project in SOAP UI and all the methods appears

How to define XML namespaces to be incuded in the header of XML request which will be send via invoke of a Web Service call?

I have developed a C# Class in VS 2012 from which I have to call (consume) through HTTPS, a remote web service method. I have already apply code to create custom headers for security tag, however I must apply in the root a declaration of namespace like
xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
The complete XML request that must be send through web service method invoke will be ( and has been tested successfully with SOAP UI ) as of the following :
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<env:Header>
<ns1:Security>
<ns1:UsernameToken>
<ns1:Username>XXXXXXXXXXXXXXXXXXXX</ns1:Username>
<ns1:Password>ZZZZZZZZZZZZZZZZZZZZ</ns1:Password>
</ns1:UsernameToken>
</ns1:Security>
</env:Header>
<env:Body>
<ns:vhWsVersion/>
</env:Body>
</env:Envelope>
for this, to work the namespace
xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
must be include via the invoke of web service method.
Any assistance of how to achieve this is kindly appreciated
Edit
var customBinding = new CustomBinding();
customBinding.Elements.Add(new TextMessageEncodingBindingElement
{
MessageVersion = MessageVersion.Soap11,
WriteEncoding = System.Text.Encoding.UTF8
});
var Uri = new Uri("https://");
var endpointAddres = new EndpointAddress(Uri, new MySecurityHeader());
var client = new ChannelFactory<ServiceReference3.VhWsCreatePayId>(customBinding)
.CreateChannel(e‌​ndpointAddres);
client.vhWsCreatePayIdVersion(request);
You'll need to ensure that the http://docs.oasis-open.org/... Namespace is included in the SoapHeader, e.g.
[System.Xml.Serialization.XmlRootAttribute(Namespace =
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
IsNullable = false)]
public partial class UsernameToken : System.Web.Services.Protocols.SoapHeader
{
// Namespace is also available here if different from the root element.
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Username {get; set;}
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Password {get; set;}
}
Edit
If you are using another technique to build the SoapHeader, note that the oasis namespace doesn't necessarily need to go into the root Envelope element - it can be placed locally in the header, e.g.:
<Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<UsernameToken>
<Username>XXXXXXXXXXXXXXXXXXXX</Username>
<Password>ZZZZZZZZZZZZZZZZZZZZ</Password>
<UsernameToken>
</Security>

Async result empty but data exists in response

I'm trying to consume a webservice with async methods. I have used it's WSDL to create a client and calling the metod like this:
public static GetStockResponse GetResult()
{
var client = new ServiceSoapClient();
var inItems = new ArrayOfItemNo();
inItems.Add(new ItemNoRow { ItemNo = "0000001350" });
Task<GetStockResponse> task = client.GetStockAsync(inItems, "034");
task.Wait();
return task.Result;
}
In fiddler I can see the call with status 200
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body>
<GetStockRequest xmlns="http://www.unikum.se/pws"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ItemNo>
<ItemNoRow>
<ItemNo>0000001350</ItemNo>
</ItemNoRow>
</ItemNo>
<StoreID>034</StoreID>
</GetStockRequest>
And the response:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body>
<GetStockResponse xmlns="http://www.unikum.se/pws">
<Items>
<Item>
<ItemNo>0000001350</ItemNo>
<DeliveryTimeText>4-6 veckor</DeliveryTimeText>
<DeliveryDays>42</DeliveryDays>
<Stores>
<Store>
<StoreID>034</StoreID>
<NotInERP>N</NotInERP>
<InStockQty>2</InStockQty>
<InShowRoom>N</InShowRoom>
</Store>
</Stores>
</Item>
</Items>
</GetStockResponse>
But the result of the task (task.Result) is empty. It is a GetStockResponse but all values is null.
Why? Everything seems correct or doesn't it?
Well, some more testing with some other methods provided by the service owner clearly indicated that they did not follow the response structure defined in their own WSDL. I could see that in a simpler test where they partially followed the WSDL structure I got correct values back on those specific properties but not on those that differed. So now I could more clearly point to the error and return with "Please fix this, or else" response to the service provider.

WCF set custom header - reading not working

I need to put custom headers into WCF. My Code is as follows:
ServiceReference1.Service2Client ws = new Service2Client();
using (OperationContextScope scope = new OperationContextScope((IContextChannel)ws.InnerChannel))
{
MessageHeaders messageHeadersElement = OperationContext.Current.OutgoingMessageHeaders;
messageHeadersElement.Add(MessageHeader.CreateHeader("Authorization", String.Empty, "string"));
messageHeadersElement.Add(MessageHeader.CreateHeader("username", String.Empty, "user"));
var res = ws.GetUser("123");
}
But when I try to read it in the service, nothing is availabe in the following
public class OAuthAuthorizationManager : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
int index = OperationContext.Current.IncomingMessageHeaders.FindHeader("username", String.Empty);
string auth = operationContext.IncomingMessageHeaders.GetHeader<string>("username", String.Empty);
var hereIseeIt = operationContext.RequestContext.RequestMessage;
index is -1: not found
auth: is also displaying an exception that the header is not available
hereIseeIt: .ToString() shows a xml where I can see that user is existent, but I see no way to access that information in any of the objects
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<username xmlns="http://Microsoft.WCF.Documentation">user</username>
</s:Header>
<s:Body>
<GetUser xmlns="http://tempuri.org/">
<UserId>123</UserId>
</GetUser>
</s:Body>
</s:Envelope>
But I cannot access them since I find no way to access the s:Header ...
try using:
XPathNavigator XPN = operationContext.RequestContext.RequestMessage.CreateBufferedCopy ().CreateNavigator ();
NOT elegant but it gives you the whole Message accessible through a XPathNavigator which should make it easy to get to any value inside the Message you want..
some links:
http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.requestcontext.aspx
http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.message.aspx
http://msdn.microsoft.com/en-us/library/system.xml.xpath.xpathnavigator.aspx
Here's an easy way to get the inner XML of the username header for your scenario. Even if you already solved your issue a long time ago, I thought it might help somebody else who faces the same issue.
var username = String.Empty;
// using the namespace from you XML sample
var usernameHeaderPosition = OperationContext.Current
.IncomingMessageHeaders
.FindHeader("username", "http://Microsoft.WCF.Documentation");
if (usernameHeaderPosition > -1)
{
username = OperationContext.Current
.IncomingMessageHeaders
.GetReaderAtHeader(usernameHeaderPosition).ReadInnerXml();
}

Remove WS-Addressing/WS-Security sections from WSE 3.0 Client request

I've got a simple C# web service proxy class that I created with WSDL.exe. I am invoking a method on the remote web service, and it is including a bunch of WS-Addressing and WS-Security headers that I do not want (and that the server is choking on). Here is an example of the raw soap request:
<?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"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soap:Header>
<wsa:Action></wsa:Action>
<wsa:MessageID>urn:uuid:22f12267-b162-4703-a451-2d1c5c5a619b</wsa:MessageID>
<wsa:To>http://example.com/wstest</wsa:To>
<wsse:Security>
<wsu:Timestamp wsu:Id="Timestamp-5c9f0ef0-ab45-421d-a633-4c4fad26d945">
<wsu:Created>2009-04-15T16:27:25Z</wsu:Created>
<wsu:Expires>2009-04-15T16:32:25Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</soap:Header>
<soap:Body>
<Func1 xmlns="http://example.com">
<arg_1 xmlns="">blah</arg_1>
<arg_2 xmlns="">blah2</arg_2></arg_2>
</Func1>
</soap:Body>
</soap:Envelope>
But I don't care about the WS-Addressing/WS-Security stuff. I've done nothing to include it. The .NET WSE 3.0 package seems to be adding them by default. Is there any way to get rid of these? I can see no properties on my proxy object that allow me to remove these sections. I've tried:
proxyObject.Addressing.Clear();
proxyObject.Security.Clear();
Those cause a null reference exception when I invoke my web service method.
I want the SOAP request to look like this:
<?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:Header>
</soap:Header>
<soap:Body>
<Func1 xmlns="http://example.com">
<arg_1 xmlns="">blah</arg_1>
<arg_2 xmlns="">blah2</arg_2></arg_2>
</Func1>
</soap:Body>
</soap:Envelope>
Thanks in advance
Well, I ended up using a technique I have used in the past. I created classes that implement SoapFilter and PolicyAssertion which allow me to modify the raw XML of the SOAP request before it is sent. Below is an example:
public class MyPolicy : SoapFilter
{
public override SoapFilterResult ProcessMessage(SoapEnvelope envelope)
{
// Remove all WS-Addressing and WS-Security header info
envelope.Header.RemoveAll();
return SoapFilterResult.Continue;
}
}
public class MyAssertion : PolicyAssertion
{
public override SoapFilter CreateClientInputFilter(FilterCreationContext context)
{
return null;
}
public override SoapFilter CreateClientOutputFilter(FilterCreationContext context)
{
return new MyPolicy();
}
public override SoapFilter CreateServiceInputFilter(FilterCreationContext context)
{
return null;
}
public override SoapFilter CreateServiceOutputFilter(FilterCreationContext context)
{
return null;
}
}
Then in your web service proxy's contructor you apply the policy:
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.1433")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="MyBinding", Namespace="http://example.com")]
public partial class MyWebClient : WebServicesClientProtocol {
// ... member variables here
/// <remarks/>
public MyWebClient()
{
this.Url = "http://example.com";
if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
this.UseDefaultCredentials = true;
this.useDefaultCredentialsSetExplicitly = false;
}
else {
this.useDefaultCredentialsSetExplicitly = true;
}
// Apply policy here
Policy policy = new Policy();
policy.Assertions.Add(new MyAssertion());
this.SetPolicy(policy);
}
}
to remove the addressing header i used the below code in one of my app.
public override void SecureMessage(SoapEnvelope envelope, Security security)
{
//remove addressing Header from envelope
AddressingHeaders objAH = new AddressingHeaders(envelope);
objAH.RemoveXml(envelope);
//Add Wahtever security token you want to add.
security.Tokens.Add(bla-bla-bla);
}
I used SecureMessage function because i wanted to add security tokens,but same code can be used in ProcessMessage function.
I wonder if your problem might not also have ben resolved by simply not using WSE?
Based on the answer in this page, I added the code below to remove specific header (by tagname) recursively from XML.
Public Overrides Function ProcessMessage(ByVal envelope As SoapEnvelope) As SoapFilterResult
' Remove all WS-Addressing and WS-Security header info
RemoveTag(envelope.DocumentElement, "wsa:Action")
RemoveTag(envelope.DocumentElement, "wsa:MessageID")
RemoveTag(envelope.DocumentElement, "wsa:To")
Return SoapFilterResult.[Continue]
End Function
Private Sub RemoveTag(ByVal XE As System.Xml.XmlElement, ByVal TagName As String)
For Each N As XmlNode In XE
If N.ChildNodes.Count > 0 Then
RemoveTag(N, TagName)
End If
If N.Name = TagName Then
XE.RemoveChild(N)
End If
Next
End Sub
I found the easiest way to remove these addressing and security headers was to change the web service configuration to use BasicHttpBinding instead of WSHttp binding.

Categories