Error in response from PUT method using compression - c#

I am using gzip compression in my .net core api. Responses from HTTP GET methods are all ok. When this method is a HTTP Put (example) the response body is corrupted. My put method response is the same data from request with additional information.
Have a additional configuration for this case?
This is my configuration:
services.AddResponseCompression(opt =>
{
opt.Providers.Add<GzipCompressionProvider>();
opt.EnableForHttps = true;
});
services.Configure<GzipCompressionProviderOptions>(opt => opt.Level = CompressionLevel.Fastest);

Thanks for all interested.
I have make a extensive debugging and found the problem: some classes with a circular reference caused serialization error.

Related

WCF: request/response with different content types

I'm trying to consume a SOAP service using WCF in .NET 5. The service provider expects the content type of the request to be text/xml but sends a response with content type application/xml.
The following code throws a ProtocolException because is expects both request and response to have content type text/xml.
var binding = new BasicHttpBinding();
var endpoint = new EndpointAddress("http://[...]/inquiry");
var channelFactory = new ChannelFactory<InquiryServiceSoapPort>(binding, endpoint);
var serviceClient = channelFactory.CreateChannel();
var inquiry = new Inquiry();
var result = serviceClient.createInquiry(inquiry);
I was able to change the content type to application/xml using a custom encoder, but that changes it for both request and response, and my request then is rejected by the server.
Is there a way to change the content type of the response only?
Edit
I am writing client-side code, not server-side code, mind you. As of now, it seems I can only catch and swallow the exception or re-implement the code either using another framework or from scratch.
Have a look at the WCF architecture here:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/architecture
So we have the ABC of WCF is the Address, Binding and Contract, and here we are in the contract serialization
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/data-transfer-and-serialization
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/data-contract-serializer
in detail:
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.serialization.datacontractserializer?view=net-5.0
the are the concept i recommend diving into, the http header type "content-type" is really a function of the rest in case You make the BasicHttp binding
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.basichttpbinding?view=dotnet-plat-ext-5.0
Which is sort of only the corner of a much bigger tool available in WCF. for instance wsHttpBinding which is really preferable in many scenarios, could alone solve your problem if the endpoint is available.
In the wsHttpBinding You can control the message encoding
https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/wcf/wshttpbinding
Ultimately choosing your Message encoder will determine how headers are set, there is a wealth of abstraction level(s) compared to REST io model, but it's there:
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/choosing-a-message-encoder
And You can even roll You own.

How to get more details on a BadRequest from HttpResponse

I'm trying to connect to a companies web service, but I'm getting a BadRequest value returned. I suppose that isn't a huge issue, and I'm not asking for help on how to fix the bad request. The issue I'm running into, is how to get more details on what is causing it. So I have this HttpResponseMessage Class variable:
HttpResponseMessage response = c.Post(address, content);
//...fill in content
response = cAssessments.Post(addressInfo, content); //return "Bad Response"
I send it off to their servers with the proper content, and I get back 400 response stating "Bad Request". My question is how do I dig deeper into that repsonse variable to see exactly what is causing it. I'm figuring that there is some dependance on the service I'm hitting to supply information so I'm going to assume it's in there somewhere. But what are something things inside that variable I should be looking into? For example:
"response.StatusCode" gives me the the 400 code. What other properties can I look into?
Any help is appreciated.
Filling content of BadRequest response with some useful tip or information what could possibly go wrong is totally up to web service which serves response. You cant do anything from your side.
Try the Content itself, also the URL of the originating request.
Depending on the API you're requesting against, they may include what specifically caused the 400 in the response's Content.
Also the format you are requesting it in (json vs xml vs whatever)
It all depends on what the service is returning. To check that, you can read the response stream:
using (var stream = response.GetResponseStream ()){
using (var reader = new StreamReader(stream, Encoding.UTF8)
{
var text = reader.ReadToEnd();
// text contains your info
}
}
Another useful option for debugging is using something like postman, where you can paste in your request and see the full response immediately
If the response doesn't include any useful info, you're stuck though, there's nothing you can do about that.

httpWebRequest.AutomaticDecompression does not set "Accept_Encoding: gzip" header

I am using a web service reference in my .net 3.0 app and I'm trying to set up gzip decoding.
When I use SoapUI the responses are compressed with gzip because the the header 'Accept-Encoding: gzip,deflate' is set in the request. When my .net request is sent it does not have this header so the server is not compressing the response.
I found this link which describes exactly what I want to do. I implemented the code and verified with the debugger that it was being executed on every request, but it is still not adding the 'Accept-Encoding:gzip' header.
Next I added the header manually in the class from the link.
httpWebRequest.Headers.Add("Accept-Encoding", "gzip");
Finally I received a compressed response from the server! But no, now I get an malformed xml exception which I'm pretty sure is because the response is not being decompressed even though the following is set by using the class from the link.
httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip;;
I cannot understand what is going wrong.
Ok I figured out a solution to my problem.
Since I am using a web reference you have to set EnableDecompression = true on the web reference object.
So the solution is something like this
var client = new ReferredService
{
EnableDecompression = true
}
where ReferredService is the web reference name.

What is a structure of a standard POST request

I am using C# for my project, can anyone tell me what is a standered structure of a HTTP POST Requset. How to attach POST data like a file in the Request from code.
Simply i want to create a POST request from my code itself, with diffrent items to be posted available.
I have checked Ietf's RFC for http POST but its too long....
Specs for simple reference
I have always appreciated HTTP Made Really Easy as a starting point. It's small, concise and friendly.
Often you can get enough implementation details (or at least enough understanding) from this guide's simple style to suffice your need. It has worked for me many times. There is a section on POST. The guide builds cumulatively.
Additionally it links to proper specifications and fuller resources should you need to reference them and get into more detail.
.NET Supporting Classes
Fortunately the .NET Framework Class Library contains higher level classes that can simplify your life. Look into the MSDN documentation and examples about System.Net.WebClient (doesn't lend itself as well to POST, favours GET for quick usage methods). Consider the more flexible System.Web.HttpRequest and System.Web.HttpResponse counterpart classes.
Example using C#
This code sample shows the concept of posting binary data to a stream.
This method is called like:
PostMyData(Stream_instance, "http://url_to_post_to");
Namespaces involved are:
using System.IO;
using System.Net;
The custom method would look something like the following.
Note: Concept taken from MSDN sample code here.
Although I use MIME type application/octet-stream for generic binary data, you can use any well known type from this list of mime types to target the kind of binary data you are sending.
public int PostMyData(Stream binaryData, string postToUrl) {
// make http request
var request = (HttpWebRequest)WebRequest.Create(postToUrl);
request.Method = "POST";
request.ContentType = "application/octet-stream"; // binary data:
// data (bytes) that will be posted in body of request
var streamOut = request.GetRequestStream();
binaryData.CopyTo(streamOut);
// post and get response
using (var response = (HttpWebResponse)request.GetResponse()) {
var code = response.StatusCode;
return (int)code;
}
}
Use HttpWebRequest, its always the best way, but for a more simple aproach on Http Post read:
http://programaticallyspeaking.site40.net/blog/2010/11/how-to-implement-an-http-server-part-1/
Hey i found a way to view a sample POST request, Use Fiddler to track HTTp transfers and click on RAW to view raw data being transfered.

WSE 3.0 set content type

I've a simple question, for you, that I just can't seem to get my head around.
The situation is the following:
We create and send a request to a web service, using WSE 3.
The web service is written in Java.
Most of the things are fine, but I can't seem to have an impact on the ContentType of either the WebResuest or WebResponse and that's causing some problems.
The errormessage I keep getting is the following:
Client found a response content type of ' application/xop+xml;type="text/xml; charset=utf-8" ' but expected 'text/xml'.
The request failed with the error message: ....
In the details of the error message it has the response to our call from the server and it's coming through properly.
Obviously it's not good as it is at the moment as it's coming through an exception :).
So, how could I set the expected content type for the response?
If I'm correct, the Request and the Response in WSE 3.0 has to have the same ContentType. So I thought I would try to set the request.Headers[HttpRequestHeader.ContentType] to the expected one, but with no luck. (also, I can set the HttpWebRequest's contenttype in quite a few places, but none of them seem to do the trick)
This has been solved luckily, so here's the solution for future reference:
Our client inherits from the WebServicesClientProtocol class, in which there's a method called GetWebResponse(..).
Simply overriding that method and changing the ContentType of the Response seemed to work out for us.
protected override WebResponse GetWebResponse(System.Net.WebRequest request)
{
WebResponse response = base.GetWebResponse(request);
response.Headers[HttpResponseHeader.ContentType] = "text/xml";
return response;
}

Categories

Resources