NotSupportedException on EndGetRequestStream - c#

public async static Task<WebResponse> GetResponseAsync(this HttpWebRequest request, Dictionary<string, object> post)
{
var tcs = new TaskCompletionSource<WebResponse>();
try
{
request.BeginGetRequestStream((arReq) =>
{
var stream = request.EndGetRequestStream(arReq);//throw NotSupportedException
writeMultipartObject(stream, post);
stream.Close();
request.BeginGetResponse((ar) =>
{
var response = request.EndGetResponse(ar);
tcs.SetResult(response);
}, null);
}, null);
}
catch (Exception we)
{
tcs.SetException(we);
}
return await tcs.Task;
}
when i post something, it no works..=.=
var stream = request.EndGetRequestStream(arReq);//throw NotSupportedException
tell me why? ToT.................
System.NotSupportedException ---> System.NotSupportedException: Specified method is not supported.
at System.Net.Browser.ClientHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
at System.Net.Browser.ClientHttpWebRequest.<>c_DisplayClasse.b_d(Object sendState)
at System.Net.Browser.AsyncHelper.<>c_DisplayClass1.b_0(Object sendState)

I have experienced similar behaviour (on Windows Phone only) and got it working by explicitly disposing the stream you're writing to.
So try to add
stream.Flush();
before, and
stream.Dispose();
after your
stream.Close();
statement and see if that helps.
Apparently, the behaviour of the networking stack in .Net is different dependent on the platform your code runs on, due to the fact that the .Net framework is "redeveloped" for each platform.
I hope this helps.
Cheers,
Kristof.

Related

Exception not handled in Grpc server when reading from a stream

I made a simple app where chunks of a file are streamed from client to server. Server-side I have handled exceptions such that a response of my own is returned to the client. When I throw an exception before reading from the stream has been completed, however, even though it gets caught and a custom response is returned, client-side I still get an unhandled RpcException with status Cancelled.
public override async Task<UploadFileResponse> UploadFile(
IAsyncStreamReader<UploadFileRequest> requestStream,
ServerCallContext context)
{
try
{
bool moveNext = await requestStream.MoveNext();
using (var stream = System.IO.File.Create($"foo.txt"))
{
while (moveNext)
{
// If something goes wrong here, before the stream has been fully read, an RpcException
// of status Cancelled is caught in the client instead of receiving an UploadFileResponse of
// type 'Failed'. Despite the fact that we catch it in the server and return a Failed response.
await stream.WriteAsync(requestStream.Current.Data.ToByteArray());
moveNext = await requestStream.MoveNext();
throw new Exception();
}
// If something goes wrong here, when the stream has been fully read, we catch it and successfully return
// a response of our own instead of an RpcException.
// throw new Exception();
}
return new UploadFileResponse()
{
StatusCode = UploadStatusCode.Ok
};
}
catch (Exception ex)
{
return new UploadFileResponse()
{
Message = ex.Message,
StatusCode = UploadStatusCode.Failed
};
}
}
Perhaps the way I approach implementing this operation is wrong. I can see why the server would return a Cancelled RPC exception because we indeed cancel the call before the stream has been fully read but I don't understand why it overrides the custom response. It might be that handling both would have to be done client-side - a failed response and a potential RPC exception.
I found some materials on the topic - Server and Client.
Apparently it is common to throw RpcExceptions whenever there should be an invalid response as also shown in the official gRPC Github repository here.

HttpClient SendAsync Cannot access a disposed object ResponseHeadersRead

I am looking into an issue with some legacy code which is relaying a Http Request to another URL. It is an API Controller that reads the request and forwards it to another address asynchronously.
Very rarely, it throws a "Cannot access a disposed object" exception - full stack trace shown later in this question. It seems to be on the line where the HttpClient is calling the SendAsync method. I think it might be the ResponseHeadersRead option - I suspect it is happening when a large packet is being sent and it gets closed because it has just read the header and quit. Just thought I'd sanity check this with you all, for your thoughts. I'll change the option to be ResponseContentsRead option and see how that goes (but it can take a long time for the error to surface).
Here is the code:
using (var client = new HttpClient())
{
var request = BuildRelayHttpRequest(Request);
await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
}
private static HttpRequestMessage BuildRelayHttpRequest(HttpRequestMessage incomingRequest)
{
var forwardToUrl = new Uri(ConfigurationManager.AppSettings["ForwardFeedURL"]);
var relayRequest = new HttpRequestMessage(incomingRequest.Method, forwardToUrl);
if (incomingRequest.Method != HttpMethod.Get && incomingRequest.Content != null)
{
relayRequest.Content = incomingRequest.Content;
}
//Copies contents
relayRequest.Content = incomingRequest.Content;
return relayRequest;
}
And here is the exception:
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Web.Http.WebHost.HttpControllerHandler+LazyStreamContent'.
at System.Net.Http.HttpContent.CheckDisposed()
at System.Net.Http.HttpContent.CopyToAsync(Stream stream, TransportContext context)
at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at CHO.Web.Services.ETrains.Controllers.ETrainsApiController.<CopyandForwardFeedAsyn>d__18.MoveNext() in \Controllers\MyAPIController.cs:line 289
Note, line 289 is the "await client.SendAsync" line of code
Odds are there is an error code being set by the server.
Follow your code with a response.EnsureSuccessStatusCode(); that is wrapped in a Try Catch block:
try
{
var request = BuildRelayHttpRequest(Request);
await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
// Handle success
}
catch (HttpRequestException)
{
// Handle failure
}

Simulate HttpRequestException for unit testing

I have an application that downloads massive amounts of pdfs from the web. From time to time, I get a HttpRequestException, contaning the message: Error while copying content to a stream.
So, I am trying to unit test my code to handle this situation. My current code for downloading is:
var request = await httpClient.GetAsync(url);
// This is where the exception would be thrown
await request.Content.ReadAsByteArrayAsync());
Now I am trying to simulate a HttpRequestException, so that I can unit test the code above, but I dont know how to do it. Can anyone please help?
Thanks in advance!
The key here is creating an HttpContent that throws an exception:
public class ExceptionThrowingContent : HttpContent
{
private readonly Exception exception;
public ExceptionThrowingContent(Exception exception)
{
this.exception = exception;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
return Task.FromException(exception);
}
protected override bool TryComputeLength(out long length)
{
length = 0L;
return false;
}
}
Once you have that, you can use something like my own mockhttp to mock the request:
var handler = new MockHttpMessageHandler();
handler.When("http://tempuri.org/url")
.Respond(new ExceptionThrowingContent(ex));
var mockClient = new HttpClient(handler);
// pass mockHandler to your component
Now, if your component passes in HttpCompletionOption.ResponseHeadersRead when it makes the request, the exception will be thrown at await Content.ReadAsByteArrayAsync(). If not, HttpClient will attempt to buffer the response so the exception will be thrown at await HttpClient.GetAsync().
If the response is being buffered, it's realistically "impossible" for an exception to be thrown at ReadAsByteArrayAsync so there's no point in attempting to simulate it. ("impossible" outside an OutOfMemoryException)
With MockHttp it is easy setup HttpClient tests in a fluent manner you can return a customized HttpContent that throws a HttpRequestException like in this example.
[TestMethod]
[ExpectedException(typeof(HttpRequestException))]
public async Task Test()
{
var content = new ContentWithException();
var mockHttp = new MockHttpMessageHandler();
mockHttp.Expect("http://localhost/mypdfDownload").Respond(content);
var client = new HttpClient(mockHttp);
var response = await client.GetAsync("http://localhost/mypdfDownload");
await response.Content.ReadAsByteArrayAsync();
}
private class ContentWithException : HttpContent
{
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
throw new HttpRequestException();
}
protected override bool TryComputeLength(out long length)
{
length = 0;
return false;
}
}

NotSupportedException when calling AsyncWaitHandle.WaitOne on non-UI Thread

I try to wait for an HttpWebRequest to finish without writing a dozen AsyncCallbacks. For that I tried to handle the call in a Task and use WaitOne within it --> so the ui thread will not be blocked.
The Problem now is that there appears a NotSupportedException everytime I call it and I don´t understand why. Can someone tell me more about that and maybe how to fix this issue?
Here the code:
Task.Factory.StartNew((x)=>
{
HttpWebRequest request = WebRequest.CreateHttp(baseUri + "/api/" + ControllerName);
request.Method = "POST";
request.ContentType = "application/json";
request.Headers["Session"] = SessionKey;
IAsyncResult GetRequestStreamResult = request.BeginGetRequestStream(null, null);
GetRequestStreamResult.AsyncWaitHandle.WaitOne(); //<-- That causes the exception
using (Stream RequestStream = request.EndGetRequestStream(GetRequestStreamResult))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(Parameter.GetType());
serializer.WriteObject(RequestStream, Parameter);
}
Best regards
Christoph
I found this article. That pointed me to the direction that maybe it is no common silverlight issue, but a Problem with the actual implementation of the IAsyncResult which is of System.Net.Browser.OHWRAsyncResult. And this simply throws a NotSupportedException in any case when accessing the AsyncWaitHandle getter.
I helped me out by writing this small Extension method:
private static void WaitForIt(this IAsyncResult result)
{
while (!result.IsCompleted)
{
Thread.Sleep(50);
}
}
Not really pretty but it works...
Regards
Christoph
Use this handler...
while ((GetRequestStreamResult.AsyncWaitHandle.WaitOne(1000, true) == false)
&& (GetRequestStreamResult.IsCompleted == false))
{
// Do nothing
}

SecurityException from using HttpWebRequest cross-domain in Silverlight 4

I'm trying to write a function in my Silverlight app that requests a particular page that doesn't exist on the same domain as where my Silverlight app is hosted.
For example:
Silverlight App: http://www.mysilverlightsite.com/
Target Page: http://www.mysite.com/MyPage.aspx
However, this generates a 'SecurityException':
{System.Security.SecurityException:
Security error. at
System.Net.Browser.ClientHttpWebRequest.InternalEndGetResponse(IAsyncResult
asyncResult) at
System.Net.Browser.ClientHttpWebRequest.EndGetResponse(IAsyncResult
asyncResult) ...}
From what I understand, this is related to cross-domain requests being restricted, and found some posts that mentioned that this article (http://msdn.microsoft.com/en-us/library/cc197955(VS.95).aspx) might be related.
Here's my code:
public static void CheckPageContentsAsync(CheckPageContentsCallback callback, DependencyObject uiObject)
{
bool result = false;
try
{
HttpWebRequest request = WebRequest.CreateHttp("http://www.mysite.com/MyPage.aspx");
request.BeginGetResponse((asyncHandle) =>
{
try
{
uiObject.Dispatcher.BeginInvoke(new VoidDelegate(() =>
{
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncHandle);
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
string content = sr.ReadToEnd();
if (content.Contains("Value"))
{
result = true;
}
if (callback != null)
{
callback.Invoke(result);
}
}
}), null);
}
catch (Exception excep)
{
throw new Exception("Failed to process response.", excep);
}
}, null);
}
catch(Exception excep2)
{
throw new Exception("Failed to generate request.", excep2);
}
}
Haven't been able to make much sense of the applicability of the "clientaccesspolicy.xml" or "crossdomain.xml" files as a solution.
Can anyone explain clearly how I modify my app, or the web server I'm requesting from, to resolve this issue?
I use to copy this file in the root of my app:
<cross-domain-policy>
<allow-access-from domain="*.*" headers="SOAPAction"/>
<allow-http-request-headers-from domain="*.*" headers="SOAPAction"/>
<site-control permitted-cross-domain-policies="master-only"/>
</cross-domain-policy>
Name it crossdomain.xml.

Categories

Resources