ASP.NET 3.5 Ajax JSON Serialization - c#

I have a website that works perfectly under built-for specification but with the increased use of SIM card dongles I’ve (I won’t be the first to be pulling his hair out over this) encountered a site-killing issue... (ok ok ok... a days’ work perhaps)
When the mobile provider gets a request for a file it's passed through a very clever application which essentially strips it down to 'just' functional. This is returned and the file works as expected even though it has been modified slightly (or heavily in the case of images).
The clever software which does this re-writes the request header also, which is causing the serialiser to ignore the response as it's not of the correct content type... I think anyway.
normal request : Content-Type application/json; charset=utf-8
SIM proxy request : Content-Type text/xml; charset=utf-8
issue number one with this is the request requires a verb in the web.config enabling GET/POST (easy added)
issue number two with this, the GET request is built like so www.site.com?a.asmx/function?value="a value" the JSON serialiser understand this is a string type so it removes the appended quotation marks and accepts the parameter, when the serialiser isn't used it will actually add more quotation marks "\"a value\"". (Easy fixed)
Issue number three the return value is XML and not JSON. Requires allot of work but can be fixed should i not be able to find another way.
I've just been reading the W3 for the HTTP header 'Cache-Control' and apparently I can send 'no-transform' and (assuming they conform) the proxy will ignore it. That would be fantastic.
Question is... How do I change the header value of a GET request via Sys.Net.WebServiceProxy.invoke()?
Also has any one any experience with this? the internet reveals little discussion on the topic.
Many Thanks in advance of any responses and sorry for the wall of text for a one line question... just fingers crossed someone has encountered this before.

There is one work around.
Edit the file where Sys.Net.WebServiceProxy.invoke function is kept.
and put following line :
request.get_headers()['Cache-Control'] = 'no-transform';
after
var request = new Sys.Net.WebRequest();

Related

Read SOAP XML message sent as HTTP message body

I have a 3rd party that is sending SOAP XML messages, as the HTTP message body (using HTTP Post). I need to write a program to accept / process these messages.
I have a specification document which contains 2 WSDL definitions - GetTransaction and CutOff.
I am trying to use Postman to send a test message. Content-Type is set to application/xml and the body is set to raw / XML.
I am using C#, ASP.Net (4.7.2), the code is in a Class Library. I have a Controller (ApiController) with:
[HttpPost]
[ValidationAttributes.RequireHttps]
public HttpResponseMessage Service(XmlDocument reqData)
but reqData is always null. I have tried different types instead of XmlDocument.
Now if probably a good time to say that this is all new to me - I've not created a program to accept SOAP messages before.
Should I be creating a WCF Service Application (rather than a .Net Framework Class Library)?
I've tried adding the WSDL "definitions" but they don't seem to produce anything useful. E.g. there is reference to a "GetTransaction" method, but it has a parameter list of about 150 items!?
I have found quite a lot of stuff via Google but it always seems to be about sending, rather than receiving, SOAP messages.
I appreciate that I have not really included much code to look at, but I feel like I've started from the wrong place. So, any basic guidance, suggestions or links to tutorial sites would be most welcome.

HTTP Error 414. The request URL is too long. asp.net

I'm getting the error "HTTP Error 414. The request URL is too long." From the following article, I understand that this is due to a very long query string:
http://www.mytecbits.com/microsoft/iis/query-string-too-long
In web.config, I have maxQueryStringLength="2097151". Is this the maximum value?
In order to solve this problem, should I set maxUrl in web.config? If so, what's the maximum value supported?
What should I do to fix this error?
This error is actually thrown from http.sys, not from IIS. The error gets thrown before the request is passed along to IIS in the request-handling pipeline.
To verify this, you can check the Server header value in the HTTP response headers, as per https://stackoverflow.com/a/32022511/12484.
To get https.sys to accept longer request URLs without throwing the HTTP 414 error, in the Windows Registry on the server PC, at Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters, create a DWORD-type value with name MaxFieldLength and value sufficiently large, e.g. 65535.
Reference: Http.sys registry settings for Windows
If you decide to make this change, then obviously it’ll need to be made in all environments (including all production server(s)) -- not just on your local dev PC.
Also, whatever script and/or documentation your team uses to set up new server instances will need to be updated to include this registry setting, so that your team doesn’t forget to apply this setting 18 months from now when setting up a new production server.
Finally, be aware making this change could have adverse security consequences for all applications running on your server, as a large HTTP request submitted by an attacker won’t be rejected early in the pipeline as it would normally.
As an alternative to making this change to bypass the http.sys security, consider changing the request to accept HTTP POST instead of HTTP GET, and put the parameters into the POST request body instead of into a long URL. For more discussion on this, see question Design RESTful GET API with a long list of query parameters.
As described in this answer -> What is the maximum length of a URL in different browsers?
The allowed length of a url depends on a combination of browser and server. Hence it's hard to say exactly how long the url can be. The answer recommends to stay below 2000 char in the url. I do not know why your querystring is so long. Can you shorten it? It's hard to give you any recommendations without knowing more about the solution and your query string.
Generally, Url has its own limits in length and if you set this value you may solve the problem for a while, but bear in mind that for a long url situations, best practice is working with forms. To be specific, it is better to use POST actions instead of Get.
just to complement, if you try with massive parameters, using Request ajax and receive de 414 ERROR. change the dataType property to JSON then submit as POST type.
this resolved my problem.

In an Http Post request, what is the difference between submitting a form and sending content in the body

I have been trying to debug an issue communicating with a web service, and it led me to a question. I was wondering what the difference between WebClient.UploadValues and WebClient.UploadData was in C#. I found the answer to that here .NET WebClient.UploadValues vs WebClient.UploadData
The answer as essentially that UploadData submits content in the body of the request, where as UploadValues acts like submitting values from a form. I would have thought they were the same thing. When you submit content in the body of a post, it usually looks something like "key=value&key2=value2...". (when the content type is application/x-www-form-urlencoded)
I thought they were the same thing until I noticed something. Using UploadValues gives me a totally different result than UploadData. In the case of the service I am communicating with, using UploadValues succeeds and UploadData returns the error "Request format is invalid".
So what exactly is the difference between a form post data and the content in the body of a request? Are they actually different things? Does an http request contain a querystring, body, AND form data?
Thanks!
UPDATE Okay, so I know what my problem was and I think I know the answer to most of my question.
Upload Values submits the body with content type application/x-www-form-urlencoded. I am not entirely sure what content-type is used for UploadData by default, but you can set the header explicitly so it will take whatever you give it.
My original confusion arose when I was trying to do this by composing an HttpWebRequest and writing the content to the RequestStream. I was setting the Content Type too late. I guess it needs to be specified BEFORE writing to the Stream.
Form data is sent in the body of the request.
Okay, so I know what my problem was and I think I know the answer to most of my question.
Upload Values submits the body with content type application/x-www-form-urlencoded. I am not entirely sure what content-type is used for UploadData by default, but you can set the header explicitly so it will take whatever you give it.
My original confusion arose when I was trying to do this by composing an HttpWebRequest and writing the content to the RequestStream. I was setting the Content Type too late. I guess it needs to be specified BEFORE writing to the Stream.
Form data is sent in the body of the request.

Rest Sharp - 406 Error - No match for accept header

I'm getting a 406 error when trying to use RestSharp to post a request to a third-party application. I'm new to REST, so I have to admit I didn't even know you could add headers. I tried adding these, but I'm still getting the same issue:
var client = new RestClient(myURL);
RestRequest request = new RestRequest("restAction", Method.POST);
request.AddHeader("Accept", "text/plain");
request.AddHeader("Content-Type", "text/plain");
request.AddParameter("parameter1", param1);
request.AddParameter("parameter2", param2);
var response = client.Execute(request);
From what I've read, this may be dealing with a header named "accept". Is that right?
Any idea what could be going on?
In general in HTTP, when a client makes a request to a server, it tells the server what kinds of formats it's prepared to understand (accept). This list of acceptable formats is what the Accept header is for. If the server can't respond using any of the media types in the Accept header, it will return a 406. Otherwise, it will indicate which media type it chose in the Content-Type header of the response. Putting "*/*" in the Accept header tells the server that the client can handle any response media type.
In my original comment to your question, I said that RestSharp looks like it's including "*" in the Accept header by default, but looking closer I see now that it's actually not. So, if you don't override the Accept header like you've done here, the default header value is "application/json","application/xml","text/json","text/x-json","text/javascript","text/xml", and it appears the server you're talking to doesn't speak any of these media types.
If the server you're working with doesn't speak json or xml, I don't think you can use RestSharp, unless you create your own deserializer. I'm not sure if you can do this from the public API or if you'd have to modify the source yourself and recompile it for you own needs.
Since you're still getting HTTP errors from the server, I would recommend taking RestSharp out of the equation for right now, and just speaking HTTP directly to the server until you actually get a correct response from the server. You can use a tool like Fiddler to make a HTTP requests directly. When you send the request (for now in the debugging stage), send an Accept header of "*/*" to get around the 406. Once you've figured out what media types the server can send back to you, you should change this back to being a media type you know you can read and you know the server can send.
It sounds like the main issue here is really just not knowing the protocol of the server. If there's any documentation on the service you're talking to, I would read that very carefully to figure out what media types it's prepared to respond with and how to craft the URLs that it expects.

how to fix protocol violation in c#

I have a c# "client" and a Java "server". The java server has a wsdl it serves to the client.
So far it works for c# to make a request for the server to perform a soap action. My server gets the soap request executes the method and tries to return the result back to the client.
When I send the response to c# however, I get "The server committed a protocol violation. Section=ResponseStatusLine".
I have spent all day trying to fix this and have come up with nothing that works. If I explain what i did, this post would be very long, so I'll keep it brief.
i Googled for hours and everything tells me my "response line" is correct. I tried shutting down Skype, rearranging the response line, adding things, taking things away, etc, etc. All to no avail.
This is for a class assignment so no, I can not use apis to help. I must do everything manually on the server side. That means parsing by hand, creating the soap response and the http response by hand. Just thought you'd like to know that before you say to use something that does it for me.
I even tried making sure my server was sending the correct header by creating a java client that "mimicked" the c# one so I could see what the server returned. However, it's returning exactly what i told it to send.
I tried telling my java client to do the same thing but to an actuall running c# service, to see what a real service returns, and it returned basically the same thing. To be safe, I copied it's response and tried sending it to the c# client and it still threw the error.
Can anyone help? I've tried all i can think of, including adding the useUnsafeHeaderParsing to my app config. Nothing is working though. I send it exactly what a real service sends it and it yells at me. I send it what i want and it yells.
I'm sending this:
"200 OK HTTP/1.0\r\n" +
"Content-Length: 201\r\n" +
"Cache-Control: private\r\n" +
"Content-Type: text/xml; charset=utf-8\r\n\r\n";
The reason for your error is that you've got the status line syntax wrong. According to the RFC, the status line syntax is:
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
You got the parts of the response status line around the wrong way ... like the error message is telling you!
Some advice:
Don't try to talk HTTP or SOAP at this level. These protocols are complicated, and there are existing well-implemented, well-document libraries that do this kind of thing. Use them and don't waste your time reinventing the wheel.
If you really do want / need to implement this stuff yourself, it is CRITICAL that you read and understand the relevant specifications. They are easy to find using Google.
(I'm not going to provide links because that would only encourage you to waste your time on building the software equivalent of horse carts with square wheels. because you need to learn to find and use them yourself ... as a matter of course.)

Categories

Resources