HTTP POST 反应式扩展异步。模式处理错误

发布于 2024-12-13 06:15:33 字数 3185 浏览 0 评论 0 原文

我尝试使用以下代码,但发生异常时它不起作用。谁能帮我解决这个问题吗?我试图在 fetchresponse().catch() 中抛出网络异常。是否可以返回 diff 类型的数据(不仅仅是字符串)。

IObservable<string> tempReturnData = null;
        try
        {
            // create http web request
            HttpWebRequest WSrequest = (HttpWebRequest)WebRequest.Create(WebURL);
            // instantiate Request class object
            RequestState rs = new RequestState();
            rs.Request = WSrequest;
            // Lock current webrequest object.. incase of retry attempt 
            lock (WSrequest)
            {
                rs.Request.ContentType = "application/x-www-form-urlencoded";
                rs.Request.Method = "POST";
                rs.Request.Timeout = 100;
                // bug in .net that closes the connection prior to it being finished 
                rs.Request.KeepAlive = false;
                rs.Request.ProtocolVersion = HttpVersion.Version10;
                // async pattern get request
                var fetchRequestStream = Observable.FromAsyncPattern<Stream>(rs.Request.BeginGetRequestStream, rs.Request.EndGetRequestStream);
                // async pattern get response
                var fetchResponse = Observable.FromAsyncPattern<WebResponse>(rs.Request.BeginGetResponse, rs.Request.EndGetResponse);
                // 
                tempReturnData = (from tempResult in fetchRequestStream() select tempResult).SelectMany(stream =>
                    {
                        using (var writer = new StreamWriter(stream)) writer.Write(postData);
                        // here i wants to catch web exception in fetchResponse()   FYI : in my function i am returning IObservable<string>
                        return fetchResponse().Catch(Observable.Empty<WebResponse>()).Retry(5);
                    }).Select(result =>
                    {
                        lock (rs)
                        {
                            rs.Response = (HttpWebResponse)result;

                            string s = "";
                            // if response is ok then read response stream data
                            if (rs.Response.StatusCode == HttpStatusCode.OK)
                            {
                                using (StreamReader reader = new StreamReader(rs.Response.GetResponseStream())) s = reader.ReadToEnd();
                            }
                            // Error case if error occurs then try after random time period
                            else
                            {
                                if (Attempt < appConfig.PSPRequestAttempt)
                                {
                                    Attempt++;
                                    RandomisePost(WebURL, postData, Attempt);
                                }
                            }
                            return s;
                        }
                    }); // get response stream data
                return tempReturnData;
            }
        }
        catch (Exception ex)
        {
            // Debug.WriteLine("Exception Occurs   " + ex.Message);
            return null;
        }

I am trying to use the following code, but it does not work when exception occurs. Can anyone help me out on this? i am trying to throw web exception in the fetchresponse().catch(). is it possible to return diff type of data in return(more than just a string out).

IObservable<string> tempReturnData = null;
        try
        {
            // create http web request
            HttpWebRequest WSrequest = (HttpWebRequest)WebRequest.Create(WebURL);
            // instantiate Request class object
            RequestState rs = new RequestState();
            rs.Request = WSrequest;
            // Lock current webrequest object.. incase of retry attempt 
            lock (WSrequest)
            {
                rs.Request.ContentType = "application/x-www-form-urlencoded";
                rs.Request.Method = "POST";
                rs.Request.Timeout = 100;
                // bug in .net that closes the connection prior to it being finished 
                rs.Request.KeepAlive = false;
                rs.Request.ProtocolVersion = HttpVersion.Version10;
                // async pattern get request
                var fetchRequestStream = Observable.FromAsyncPattern<Stream>(rs.Request.BeginGetRequestStream, rs.Request.EndGetRequestStream);
                // async pattern get response
                var fetchResponse = Observable.FromAsyncPattern<WebResponse>(rs.Request.BeginGetResponse, rs.Request.EndGetResponse);
                // 
                tempReturnData = (from tempResult in fetchRequestStream() select tempResult).SelectMany(stream =>
                    {
                        using (var writer = new StreamWriter(stream)) writer.Write(postData);
                        // here i wants to catch web exception in fetchResponse()   FYI : in my function i am returning IObservable<string>
                        return fetchResponse().Catch(Observable.Empty<WebResponse>()).Retry(5);
                    }).Select(result =>
                    {
                        lock (rs)
                        {
                            rs.Response = (HttpWebResponse)result;

                            string s = "";
                            // if response is ok then read response stream data
                            if (rs.Response.StatusCode == HttpStatusCode.OK)
                            {
                                using (StreamReader reader = new StreamReader(rs.Response.GetResponseStream())) s = reader.ReadToEnd();
                            }
                            // Error case if error occurs then try after random time period
                            else
                            {
                                if (Attempt < appConfig.PSPRequestAttempt)
                                {
                                    Attempt++;
                                    RandomisePost(WebURL, postData, Attempt);
                                }
                            }
                            return s;
                        }
                    }); // get response stream data
                return tempReturnData;
            }
        }
        catch (Exception ex)
        {
            // Debug.WriteLine("Exception Occurs   " + ex.Message);
            return null;
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笨死的猪 2024-12-20 06:15:33

我认为你太努力地将 Rx 和非 Rx 代码混合在一起。尝试使您的 Rx 代码按照如下所示的简单 Rx 查询工作:

    return
        from st in fetchRequestStream()
        from rp in postDataAndFetchResponse(st)
        from s in fetchResult(rp)
        select s;

此查询依赖于三个如下所示的函数:Func>

然后,您可以使用标准 RX 运算符来处理所有重试和异常处理。无需进行任何时髦的“随机”调用!

您可以这样调用它:

FetchStringFromPost("url", "postData")
.Retry(3)
.Subscribe(s => { }, ex =>
{
    /* Exceptions here! */
}, () => { });

这是完整的代码:

public IObservable<string> FetchStringFromPost(string WebURL, string postData)
{
    var request = (HttpWebRequest)WebRequest.Create(WebURL);
    request.ContentType = "application/x-www-form-urlencoded";
    request.Method = "POST";
    request.Timeout = 100;
    request.KeepAlive = false;
    request.ProtocolVersion = HttpVersion.Version10;

    var fetchRequestStream = Observable
        .FromAsyncPattern<Stream>(
            request.BeginGetRequestStream,
            request.EndGetRequestStream);

    var fetchResponse = Observable
        .FromAsyncPattern<WebResponse>(
            request.BeginGetResponse,
            request.EndGetResponse);

    Func<Stream, IObservable<HttpWebResponse>> postDataAndFetchResponse = st =>
    {
        using (var writer = new StreamWriter(st))
        {
            writer.Write(postData);
        }
        return fetchResponse().Select(rp => (HttpWebResponse)rp);
    };

    Func<HttpWebResponse, IObservable<string>> fetchResult = rp =>
    {
        if (rp.StatusCode == HttpStatusCode.OK)
        {
            using (var reader = new StreamReader(rp.GetResponseStream()))
            {
                return Observable.Return<string>(reader.ReadToEnd());
            }
        }
        else
        {
            var msg = "HttpStatusCode == " + rp.StatusCode.ToString();
            var ex = new System.Net.WebException(msg,
                WebExceptionStatus.ReceiveFailure);
            return Observable.Throw<string>(ex);
        }
    };

    return
        from st in fetchRequestStream()
        from rp in postDataAndFetchResponse(st)
        from s in fetchResult(rp)
        select s;
}

当我测试上述代码时,我尝试调用 FetchStringFromPost("http://www.microsoft.com", "foo").Materialize() 并得到了这个:

WebException

似乎工作起来就像一种享受。让我知道你进展如何。

I think you're trying too hard to mix Rx and non-Rx code together. Try to make your Rx code work in terms of a simple Rx query like this:

    return
        from st in fetchRequestStream()
        from rp in postDataAndFetchResponse(st)
        from s in fetchResult(rp)
        select s;

This query relies on three functions that look like this: Func<X, IObservable<Y>>.

You can then handle all of the retrying and exception handling using standard RX operators. No need to do any funky "randomise" calls!

You can call it like this:

FetchStringFromPost("url", "postData")
.Retry(3)
.Subscribe(s => { }, ex =>
{
    /* Exceptions here! */
}, () => { });

Here's the full code:

public IObservable<string> FetchStringFromPost(string WebURL, string postData)
{
    var request = (HttpWebRequest)WebRequest.Create(WebURL);
    request.ContentType = "application/x-www-form-urlencoded";
    request.Method = "POST";
    request.Timeout = 100;
    request.KeepAlive = false;
    request.ProtocolVersion = HttpVersion.Version10;

    var fetchRequestStream = Observable
        .FromAsyncPattern<Stream>(
            request.BeginGetRequestStream,
            request.EndGetRequestStream);

    var fetchResponse = Observable
        .FromAsyncPattern<WebResponse>(
            request.BeginGetResponse,
            request.EndGetResponse);

    Func<Stream, IObservable<HttpWebResponse>> postDataAndFetchResponse = st =>
    {
        using (var writer = new StreamWriter(st))
        {
            writer.Write(postData);
        }
        return fetchResponse().Select(rp => (HttpWebResponse)rp);
    };

    Func<HttpWebResponse, IObservable<string>> fetchResult = rp =>
    {
        if (rp.StatusCode == HttpStatusCode.OK)
        {
            using (var reader = new StreamReader(rp.GetResponseStream()))
            {
                return Observable.Return<string>(reader.ReadToEnd());
            }
        }
        else
        {
            var msg = "HttpStatusCode == " + rp.StatusCode.ToString();
            var ex = new System.Net.WebException(msg,
                WebExceptionStatus.ReceiveFailure);
            return Observable.Throw<string>(ex);
        }
    };

    return
        from st in fetchRequestStream()
        from rp in postDataAndFetchResponse(st)
        from s in fetchResult(rp)
        select s;
}

When I tested the above code I tried to call FetchStringFromPost("http://www.microsoft.com", "foo").Materialize() and got back this:

WebException

Seems to work like a treat. Let me know how you go.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文