ProtocolError while calling HttpWebRequest.GetResponse() - httpwebrequest

I have a page containing links to some files.
I basically need to access the source of the page for parsing it then and obtaining all the hyperlinks to the files.
My code is something like this (some piece of code I've found in many places on the net ..):
"private static byte[] ReadImageFromUrl(string url)
{
var myReq = (HttpWebRequest)WebRequest.Create(url);
myReq.Timeout = 10000;
WebResponse myResp = myReq.GetResponse();
Stream stream = myResp.GetResponseStream();
List<byte> bytesList = new List<byte>();
using (var br = new BinaryReader(stream))
{
try
{
while (true)
{
var b = br.ReadByte();
bytesList.Add(b);
}
}
catch (Exception)
{}
br.Close();
}
myResp.Close();
return bytesList.ToArray();
}"
Now the problem is I get "System.Net.WebException: The remote server returned an error: (500) Internal Server Error." when calling "myReq.GetResponse()" - examining the error I see that the status is 'ProtocolError'.
The response property of the WebException object contains some server error ..(although when opening it from the browser it opens correctly) ...also when I call this function with the url of one of my files I get the same ProtocolError status, but the 404 error ...
Please give any hint how could I solve it... or any other possibility of accomplishing this task.
Thanks !

My new code after using Fiddler is:
private static byte[] ReadFileFromUrl(string url)
{
var myReq = (HttpWebRequest)WebRequest.Create(url);
myReq.Accept = const_AcceptHeader;
myReq.Headers.Set(const_AcceptLanguageHeaderName, const_AcceptLanguageHeader);
myReq.UserAgent = const_AcceptUserAgentHeader;
myReq.CookieContainer = new CookieContainer();
myReq.KeepAlive = true;
myReq.Timeout = Int32.Parse(ConfigSettings.RequestPageTimeout) * 1000;
WebResponse myResp = null;
List<byte> bytesList = null;
myResp = myReq.GetResponse();
Stream stream = myResp.GetResponseStream();
bytesList = new List<byte>();
using (var br = new BinaryReader(stream))
{
try
{
while (true)
{
var b = br.ReadByte();
bytesList.Add(b);
}
}
catch (Exception ex)
{
throw;
}
br.Close();
}
return bytesList.ToArray();
}
All variables that start with const_ are taken from Fiddler.

Well, I solved that using Fiddler ... I passed to my request object the headers as I have seen them in Fiddler ...& it worked, no error

Related

A possible object cycle was detected. in both System.Text.Json and Newtonsoft.Json

I have been pulling my hair out with this one.
I have a very simple test class that throws this error:
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles.
It doesn't seem to break much, as the put request is successful and the serialize is also successful.
EDIT
I have chased the serialize exception out if it was ever really there. I am starting to think it is a problem with typed HttpClient. It throws the exception that comes out on the console and in the response on Postman. However, it doesn't allow me to catch the exception in the code and the PUT call works. So the exception is happening after the PUT request and is handled before it returns control to my app.
I am going to try to use a standard HttpClientFactor instead of a typed client and see if that works. I know that the JSON exception is a red herring, but it is ugly and breaking the response.
Any suggestions would be welcome.
public virtual async Task<CouchResponse> Create(string id, string db, TObj info)
{
CouchResponse ret = new() { Reason = "Unknown and unExpected error", Ok = false };
HttpResponseMessage rc = null;
if (id is null)
{
return new CouchResponse() { Id = "missing", Ok = false, Rev = "missing" };
}
string url = $"{db}/1";
try
{
// login to Couchdb servwer
await CouchLogin();
try
{
//var jsonInfo = JsonUtils.Serialize<TestJson>(jTest);
var jsonInfo = JsonSerializer.Serialize<TObj>(info, options);
HttpContent content = new StringContent(jsonInfo, Encoding.UTF8,
"application/json");
rc = await client.PutAsync(url, content);
}
catch (Exception eNewton)
{
Console.WriteLine($"Json Exception: {eNewton.Message}");
}
if (rc is not null)
{
var str = await rc.Content.ReadAsStringAsync();
var ret = JsonSerializer.Deserialize<CouchResponse>(str,options);
rc.EnsureSuccessStatusCode();
}
return ret;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
//return ret;
}
return ret;
}
Suggestions?
What a crazy bug. The diagnostic was very missing leading. Everything I was doing in the create method was correct.
What is missed was an await when I called the create method. This made it appear that the sendAsync was having the issue when it was really the controller trying to format the task return as a response. This caused the stack trace in the response message. Thanks for all the help.
Change this
var jsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
To this
var jsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
MaxDepth = null,
};

Post a string to restful webservice in C#

I am provided a webservice url similar to:
http://ericdev35:7280/persons/persons/
and a username and password.
I want to make a post call on this web service from WPF application.
The data to be sent to the service is the first name and last name of a person in the format:
"fname=Abc&lname=Xyz"
How can I make a call for this in C#?
Here is the code that I have tried:
HttpWebRequest httpWebRequest = (HttpWebRequest) WebRequest.Create("http://ericdev35:7280/persons/persons/");
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/json";
httpWebRequest.Credentials = new NetworkCredential(username, password);
string data = "fname=Abc&lname=Xyz";
StreamWriter writer = new StreamWriter(httpWebRequest.GetRequestStream());
writer.Write(data);
writer.Close();
This does not give me any error but I cannot see the data that I have posted. Is there anything that needs to be corrected?
Is the Content Type correct?
This Method posts json.
After that it gets the response and deserialize the Json Object.
private static string PostJson<T1>(string p_url, string p_json, string p_method, out T1 p_target)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(p_url);
httpWebRequest.UseDefaultCredentials = true;
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = p_method;
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(p_json);
streamWriter.Flush();
streamWriter.Close();
}
HttpWebResponse httpResponse;
try
{
httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
}
catch (WebException ex)
{
httpResponse = ex.Response as HttpWebResponse;
}
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var a_result = streamReader.ReadToEnd();
//If you dont need a Json object delete anything behind here
try
{
p_target = JsonConvert.DeserializeObject<T1>(a_result);
}
catch { p_target = default(T1); }
return a_result;
}
}

2 exceptions when trying to make async HttpWebRequest

I am writing an MVC Web API the make async HttpWebRequest calls. I am getting 2 different exceptions. Below is the method I am using.
The 1st exception is: "This stream does not support seek operations." and it is happening on the responseStream.
The 2nd exception is: "timeouts are not supported on this stream" and that is happening on the MemoryStream content.
What am I doing wrong? I have been Googling but not really finding any solution.
Thanks,
Rhonda
private async Task GetHtmlContentAsync(string requestUri, string userAgent, string referrer, bool keepAlive, TimeSpan timeout, bool forceTimeoutWhileReading, string proxy, string requestMethod, string type)
{
//string to hold Response
string output = null;
//create request object
var request = (HttpWebRequest)WebRequest.Create(requestUri);
var content = new MemoryStream();
request.Method = requestMethod;
request.KeepAlive = keepAlive;
request.Headers.Set("Pragma", "no-cache");
request.Timeout = (Int32)timeout.TotalMilliseconds;
request.ReadWriteTimeout = (Int32)timeout.TotalMilliseconds;
request.Referer = referrer;
request.Proxy = new WebProxy(proxy);
request.UserAgent = userAgent;
try
{
using (WebResponse response = await request.GetResponseAsync().ConfigureAwait(false))
{
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
await responseStream.CopyToAsync(content);
}
}
var sr = new StreamReader(content);
output = sr.ReadToEnd();
sr.Close();
}
}
catch (Exception ex)
{
output = string.Empty;
var message = ("The API caused an exception in the " + type + ".\r\n " + requestUri + "\r\n" + ex);
Logger.Write(message);
}
return output;
}
I fixed the issue by adding
content.Position = 0
before new StreamReader line. Now I just need to get it work with GZip compression.
Rhonda

How to return multipart/form-data in response from WCF service?

In my WCF service I need to return MIME Multipart data (a text file) back to client in the response. Althoug the response returned to the client, I don't see the data being returned. As a matter of fact, I don't see anything I setup on the server side being returned to the client. Could someone shed some light on this? Here is what I have in my code for building and returning response:
MultipartFormDataContent formData = new MultipartFormDataContent("myboundary");
HttpResponseMessage responseMsg = new HttpResponseMessage();
try
{
using (Stream fs = File.OpenRead("C;\\mydata.txt"))
{
formData.Add(new StreamContent(fs), "Payload", "mydata.txt");
}
}
catch (Exception ex)
{
ServiceUtil.LogMessage(ex.Message);
}
responseMsg.StatusCode = System.Net.HttpStatusCode.OK;
responseMsg.Content = formData;
WebOperationContext.Current.OutgoingResponse.ContentLength = 2048;
WebOperationContext.Current.OutgoingResponse.ContentType = "multipart/form-data";
WebOperationContext.Current.OutgoingResponse.Headers["Accept"] = "multipart/form-data";
}

com.sun.jersey.api.client.UniformInterfaceException (returned a response status of 400)

I am trying to set up file upload example using JAX RS. I could set up the project and successfully upload file in a server location. But i get the following error when file size is more than 10KB (weird!!)
com.sun.jersey.api.client.UniformInterfaceException: POST http://localhost:9090/DOAFileUploader/rest/file/upload returned a response status of 400
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:607)
at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
at com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:507)
at com.sony.doa.rest.client.DOAClient.upload(DOAClient.java:75)
at com.sony.doa.rest.client.DOAMain.main(DOAMain.java:34)
I am new to JAX RS and i'm not sure what exactly the issue is. Do i need to set some parameters client side or server side (like size, timeout etc)?
This is the client side code calling webservice:
public void upload() {
File file = new File(inputFilePath);
FormDataMultiPart part = new FormDataMultiPart();
part.bodyPart(new FileDataBodyPart("file", file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
WebResource resource = Client.create().resource(url);
String response = resource.type(MediaType.MULTIPART_FORM_DATA_TYPE).post(String.class, part);
System.out.println(response);
}
This is the server side code:
#Path("/file")
public class UploadFileService {
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail) {
String uploadedFileLocation = "e://uploaded/"
+ fileDetail.getFileName();
writeToFile(uploadedInputStream, uploadedFileLocation);
String output = "File uploaded to : " + uploadedFileLocation;
return Response.status(200).entity(output).build();
}
private void writeToFile(InputStream uploadedInputStream,
String uploadedFileLocation) {
try {
OutputStream out = new FileOutputStream(new File(
uploadedFileLocation));
int read = 0;
byte[] bytes = new byte[16000];
out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
} } }
Please let me know what settings i have to change for file sizes greater than 10KB?
Thanks!
I use org.apache.commons.fileupload.servlet.ServletFileUpload in a Jersey context, and it works fine., and yes, it set the max file size, sorry I missed this before.
here is a snipet of code I use (this is a multipart form, so there are other fields along with the file)
private LibraryUpload parseLibraryUpload(HttpServletRequest request) {
LibraryUpload libraryUpload;
File libraryZip = null;
String name = null;
String version = null;
ServletFileUpload upload = new ServletFileUpload();
upload.setFileSizeMax(MAX_FILE_SIZE);
FileItemIterator iter;
try {
iter = upload.getItemIterator(request);
while (iter.hasNext()) {
....
if (item.isFormField()) {
....
}else{
BufferedInputStream buffer = new BufferedInputStream(stream);
buffer.mark(MAX_FILE_SIZE);
libraryZip = File.createTempFile("fromUpload", null);
IOUtils.copy(buffer, new FileOutputStream(libraryZip));
...
}
I have encountered the same problem with Jersey. I have activated jersey trace but nothing help me.
I have changed the library by an apache Library and I see than the problem with linked to a repository for temporary files for tomcat. The repository was not exist. For files under 10k, the repository was not used.
So, after the repository creation, I used jersey library and all works fine.