Properties in a response object after a webservice call are null - c#

I can see the object in Fiddler but the object is not deserializing on my end. Has anyone seen this before?

"Response is null" or "Response contains nulls" or "Request is null" or "Request contains null" almost always mean that you have a namespace mismatch. For instance, the response may contain:
<response xmlns="http://foo.com"/>
but should in fact be
<response xmlns="http://bar.com"/>
In this case, null will be received.

I had the same problem, and as suggested the namespace problem was the root cause.However, my proxy class has nested classes and long chain of nested namespace.
It was confusing to identify the correct namespace to apply in Cs code for proxy class. Here, i describe how to figure out the namespace which is required to be updated in client proxy.
What i did was intercept the request in ClientMessageInspector class, AfterReceiveReply method (Enables inspection or modification of a message after a reply message is received but prior to passing it back to the client application.) Verified the namespace of the object which were returning null in Response by using XMLDocument. I updated the proxy class with the namespace retreived from XML. After making the changes, the objects were not null in response.
public class MyMessageInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message request, object correlationState)
{
MemoryStream ms = new MemoryStream();
XmlWriter writer = XmlWriter.Create(ms);
request.WriteMessage(writer);
writer.Flush();
ms.Position = 0;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(ms);
this.ReadMessage(xmlDoc);
ms = new MemoryStream();
xmlDoc.Save(ms);
ms.Position = 0;
XmlReader reader = XmlReader.Create(ms);
Message newMessage = Message.CreateMessage(reader, int.MaxValue, request.Version);
newMessage.Properties.CopyProperties(request.Properties);
request = newMessage;
}
private void ReadMessage(XmlDocument xmlDoc)
{
XmlNode v1 = xmlDoc.GetElementsByTagName("XPAth");
//Actual Namespace in XML, which should be used in Proxy Class
string namespaceURIForObjectInXML = v1.NamespaceURI;
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
}
}

I had a similar case where I created a client via SVCUTIL / Service Reference from VS. The response was received successfully with correct data (confirmed via IClientMessageInspector.AfterReceiveReply method) however the values at the object level were not being populated. There were no de-serialization errors (confirmed via system.diagnostics output)
The problem was twofold:
1) Certain objects were named exactly as their types but had different namespaces from their types. This seems to have confused the proxy generator in assigning the namespace parameter (in the System.Xml.Serialization.XmlElementAttribute annotation) of the class to the one of the object
2) The order parameter (in the System.Xml.Serialization.XmlElementAttribute annotation) of the properties was not required and also the namespace parameter was missing
so from: [System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Order=0)]
to: [System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Namespace="http://www.whathevernamespaceiscorrect.com")]
So basically, in the generated proxy I needed to fix the namespace of the class to the one specified in the type, and replace the order parameter with the namespace parameter setting it to the correct namespace according to the wsdl

The only reason I can think of is a contract mismatch. Although it's strange if no validation error is thrown. Are you using a client generated from the correct WSDL? Is it a WCF client or a SOAP one? The former one does validation, I'm sure, but schema mismatches may slip through the latter.

Every time this happens to me, it's because I need to update my service references. Try that and let me know what happens :)

Solved it... or at least have workaround. In the Java code the #XmlElementRefs and #XmlElementRef should have been #XmlElements and #XmlElement respectively (as well as the "type" attribute it needed a "name" attribute).
Guessing if I'd posted this as a new question with a Java tag as well as C# and web-services some hawk-eyed stackoverflower would have spotted this schoolboy error.

I had a similar issue which i resolved by checking the Order value in the Reference.cs.
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
The order of the return parameters had changed but updating my service reference in visual studio didn't change the "Order" value.
Check that parameters returned in Fiddler/SoapUI are the same as in your proxy generated class.

Ensure the definition / specification matches the output. Compare the WSDL (in browser) and the response (in SOAP-UI, Fiddler), e.g.
WSDL uses camel case (lastName) and
response uses underscores (last_name).

Related

Compiler adds random `1 to my interface instances

I have a RestClient of type IRestClient that does a request and gets a response.
the response is of type IRestResponse.
In the Unit test using Nunit I do:
var response = new RestResponse<MyResponse>
{
Content = "some string"
};
this.mockRestClient.Setup(c => c.ExecuteTaskAsync(It.IsAny<RestRequest>()))
.ReturnsAsync(response);
In the code this happens:
var response =
(await this.client
.ExecuteTaskAsync(request))
.EnsureStatusCode(HttpStatusCode.OK, HttpStatusCode.BadRequest);
return response.ParseContent<MyResponse>().Data;
ParseContent method does this:
public static IRestResponse<T> ParseContent<T>(this IRestResponse response)
{
if (!(response is RestResponse fullResponse))
{
throw new NotSupportedException($"Currently requires a concrete {typeof(RestResponse).Name}");
}
}
The API works correctly in various environments but the Nunit integration test fails with the error
Currently requires a concrete RestResponse
When I debug it, it is of type RestResponse`1
As you can appreciate this is very hard problem to search both in Google but also here in Stackoverflow because no search engine considers the backtick.
Does anyone know what this is and how to make Nunit behave correctly?
Type checking becomes a nightmare if instances are of T`1 type instead of T
Why does Nunit test project generate a new type while the actual application doesn't?
RestResponse<MyResponse> does implement IRestResponse, but it does not extend RestResponse.
In C#, generic types and their non-generic equivalents are not actually the same class. A response that doesn't have a specific type of data with it is represented in this framework as a RestResponse, whereas responses with a data type are represented as RestResponse<T> (which is represented by a back-tick when ToString()'d.
I'm not entirely clear on the intent of your ParseContent<> method, or how the code works outside of unit tests, but you may want to try creating your test data like this:
var response = new RestResponse
{
Content = "some string"
};
That way, you're providing the "concrete RestResponse" type that the method is asking for. And I assume the method itself produces a RestResponse<MyResponse> based on the contents of the RestResponse you pass in.

Custom soap header with proxy code generated from SVCUTIL

I have a program that submits data to a third party web service. They are implementing two-factor authentication where I have to create a nonce key (using NewGuid), they provide an encoded API key to include, as well as a screen name, URL and time stamp.
I have the nonce being created, and then using the api key, I sign the data and in the end, I'll have a long string such as this:
2017-04-15T17:08:57Z-1265fb1e-bbc3-453a-be409e2a808cbaaeWpyp6EJnIUlSX1rB/YRJxRyp8cXxw2IIrFMnnvuB06cUBabyRLnD 5hPj+ndH8zSIhojvNgc10/az2N+hh6SaMA==
It states that it would be sent in an HTTP header called X-WME-API-Token.
We have a MeterDataService.cs file that was generated from the SVCUTIL command line tool that creates a proxy client. I don't see anywhere in there that I can add the customer header.
I know that you can do something like this if you have something derived from WebRequest:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlString);
req.ContentType = "text/xml";
req.Headers["X-SPP-API-Token"] = Token;
req.Method = "POST";
However, none of the resulting objects is derived from WebRequest, so I'm not sure how to do this.
One object, the MeterDataPortClient object, has an Endpoint property. Is that where I would do it? How do I do that? I guess that's my question.
I did try modifying the MeterDataRequest object they created by having it inherit from WebRequest, but then I got this error:
"The type PostMeterDataRequest defines a MessageContract but also derives from a type System.Net.WebRequest that does not define a MessageContract. All of the objects in the inheritance hierarchy of PostMeterDataRequest must defines a MessageContract."
Here's the the definition of the PostMeterDataRequest and I see the MessageContractAttribute being applied to the class. I'm just not familiar with what that means. I just need to find a way to add the HTTP header to the request object before it's sent to the web service since the service at the receiving end expects the token to be in the HTTP header and I have no idea how to put it in with the code that I have at hand.
[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 PostMeterDataRequest : WebRequest // WebRequest added my me later on.
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://someorg.com/schema/MeterDataSchema/v2", Order = 0)]
public PostMeterDataType PostMeterData;
public PostMeterDataRequest()
{
}
public PostMeterDataRequest(PostMeterDataType PostMeterData)
{
this.PostMeterData = PostMeterData;
}
}
Finally found a solution. It was this earlier post that I never found before as much as I searched, but it worked.
How to add Custom HTTP Header for C# Web Service Client
Following the directions in the first answer worked beautifully.

C# object validate against xsd file

The question is can I validate c# object against xsd without serializing this object to the xml? If yes, please give me some quick sample.
Just to give You some introduction. I got reference to the external WCF service and I got some xsd file. I got some proxy objects requests/response for this service. In the service consumer side (just class library) I would like to validate response (c# object) against provided xsd. Can I do that without serializing response to the xml?
public Response Consume(Request message)
{
try
{
ServiceClient serviceClient = new ServiceClient();
var response = serviceClient.Execute(message);
// Here I would like to validate response without serializing against xsd
return response;
}
catch (FaultException<ValidationFault> validationException)
{
throw validationException;
}
}

Can I change the content of an incoming HTTP request using a HTTP Module?

I'm trying to extend my REST service (built using WCF/webHttpBinding) so that clients can upload gzipped data. I'm not sure what the best way to accomplish this but I thought it would be fairly easy by adding a HTTP module which will decompress the data if Content-Encoding for the incoming request is set to gzip.
So I created an class deriving from IHttpModule with the following implementation:
private void OnBeginRequest(object sender, EventArgs e)
{
var app = (HttpApplication) sender;
var context = app.Context;
var contentEncoding = context.Request.Headers["Content-Encoding"];
if (contentEncoding == "gzip")
{
// some debug code:
var decompressedStream = new GZipStream(context.Request.InputStream, CompressionMode.Decompress);
var memoryStream = new MemoryStream();
decompressedStream.CopyTo(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(memoryStream);
string msg = streamReader.ReadToEnd();
context.Request.InputStream.Seek(0, SeekOrigin.Begin);
app.Request.Filter = //new TestFilterStream(app.Request.Filter);
new System.IO.Compression.GZipStream(
app.Request.Filter, CompressionMode.Decompress);
}
}
The issue I'm seeing is that the GZipStream decompression is never actually performed. I've confirmed that the incoming data is in fact gzip'd (the msg-variable contains the proper data). I've also tried creating my own stream class (TestFilterStream) above and assign that to app.Request.Filter and I've confirmed that no members on the stream class is actually called by ASP.NET. So it seems like while it's possible to specify a filter, that filter isn't actually used.
Isn't HttpApplication.Request.Filter actually used?
I tried setting the Request Filter in two ways:
Using a HttpModule
Setting it in the start of Application_BeginRequest() (Global.asax)
Both with the same results (VS2012 web project + IISExpress):
If there is no input data (GET request or similar), the Filter.Read is not invoked
In case of a POST with actual data, the filter is executed and the web service gets the filtered data
Even if I read from the Request.InputStream before the Filter is set, I still get the filter triggered from my service code.
I have no easy way of testing with Gzippet input, so I have not tried if the actual filter works. However, I know it is getting triggered, since I get an error from GZipStream while it attempts to look for the input.
Perhaps you are having other HttpModules or Filters that disrupt your input or control flow?
This post proposes a method similar to yours, but also states the following, which may be causing some side effects (my tests were not using WCF):
"It appears that this approach trigger a problem in WCF, as WCF relies on the original Content-Length and not the value obtained after decompressing."
I've just done a couple of tests, and my Request.Filter stream is called into, as long as there is a request body and the request body gets read by the http handler. I'm guessing you use either a PUT or a POST, and certainly read the request body, so that shouldn't be a problem.
I suspect Knaģis' comment is correct. Have you tried without the debug code? If I dig into the HttpRequest source, I see a variable _rawContent being written to exactly once; at that same time the request filters are applied. After that the _rawContent value just gets cached, and is never updated (nor reset when a filter is added).
So by calling Request.InputStream in your debug code you are definitely preventing your filter from being applied later on. Reading the Request.Headers collection is no problem.
Are you sure, that application itself should bother?
Usually that's handled per configuration of host (IIS). So, basically, you only need to implement custom GZip support, when you host the service yourself.
You can take a look here

Incompatible Type when using web service

I have to use a web service which returns a string as result, it gets some string parameters too, so all things i have done is as this:
1- I have added that service reference to my project.
2- I have created an instance of that service class
3- I have call a desire function within class instance
here is my code:
MyServiceNS.PscoWSDLPortTypeClient mys= new MyServiceNS.PscoWSDLPortTypeClient();
string res;
res =mys.srvReq("11320000", "21310000", "13901009", "1", "3");
But the problem is when i call mys.srvReq i get an error as below:
The content type text/xml; charset=ISO-8859-1 of the response message
does not match the content type of the binding (text/xml;
charset=utf-8). If using a custom encoder, be sure that the
IsContentTypeSupported method is implemented properly. The first 572
bytes of the response were: ?xml version="1.0"
encoding="ISO-8859-1"?SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-
As I understand it, the problem is with the WFC not supporting the ISO-88859-1 encoding.
The default WFC encoder only supports utf-8 and utf-16 encoding.
You can create a suitable custom encoder as per the msdn:
http://msdn.microsoft.com/en-us/library/ms751486.aspx
And/Or modify this useful example
http://eclectrics.com/software/2009/09/getting-the-current-weather-conditions/

Categories

Resources