WebHeaderCollection & HttpWebRequest on Xamarin

2020-06-29 00:55发布

I'm trying to port my project from Xamarin Studio on Mac to Visual Studio 2012 on Windows 7. On Mac and XS works all fine. On VisualStudio 2012 i've those 2 problems:

Error 3 'System.Net.WebHeaderCollection' does not contain a definition for 'Add' and no extension method 'Add' accepting a first argument of type 'System.Net.WebHeaderCollection' could be found (are you missing a using directive or an assembly reference?) C:\Users\user\Documents\Visual Studio 2012\Projects\MyProject\MyProject.Core\Services\MyProjectService.cs

Error 4 'System.Net.HttpWebRequest' does not contain a definition for 'GetResponse' and no extension method 'GetResponse' accepting a first argument of type 'System.Net.HttpWebRequest' could be found (are you missing a using directive or an assembly reference?) C:\Users\user\Documents\Visual Studio 2012\Projects\MyProject\MyProject.Core\Services\MyProjectService.cs

on that code:

    var request = WebRequest.Create("https://www.myaddress.com/test/") as HttpWebRequest;
    request.Method = "GET";
    request.Accept = "application/json";
    request.Headers.Add(HttpRequestHeader.Cookie,"mycookievalue");

    // Get response  
    using (var response = request.GetResponse() as HttpWebResponse)
    {
        // Get the response stream  
        var reader = new StreamReader(response.GetResponseStream());
        content = reader.ReadToEnd();
    }

How could i solve it?

2条回答
狗以群分
2楼-- · 2020-06-29 01:41

There is no implementation of the things mentioned by you so far. But that's ok. They still do their work great!

Answering to your questions.

Error 3. Yes. Currently you can use only Headers["key"] = value. But. Not for every header. I was trying to put "Content-Length" there (as there is no "ContentLength" property implemented as well), but got "restricted headers" exception. However, Request POST processed successfully for me, so I let it go.

Error 4. Yes. There is no such method. (The same way, as there is no "GetRequestStream" (For instance, if you want to write POST data to request stream)). Good news is that there are BeginGetResponse and BeginGetRequestStream respectively, and C# action methods simplify all that kitchen.

(plus, I am sure, that's pretty useful for asynchronous practices general understanding).

Basic sample can be found on Microsoft official docs.

But to do it with actions I used the following:

    public void MakeRequest(string url, string verb, Dictionary<string, string> requestParams,
        Action<string> onSuccess, Action<Exception> onError)
    {
        string paramsFormatted;

        if (verb == "GET")
        {
            paramsFormatted = string.Join("&", requestParams.Select(x => x.Key + "=" + Uri.EscapeDataString(x.Value)));
            url = url + (string.IsNullOrEmpty(paramsFormatted) ? "" : "?" + paramsFormatted);
        }
        else
        {
            // I don't escape parameters here,
            // as Uri.EscapeDataString would throw exception if the parameter length
            // is too long, so you must control that manually before passing them here
            // for instance to convert to base64 safely
            paramsFormatted = string.Join("&", requestParams.Select(x => x.Key + "=" + (x.Value)));
        }

        var request = (HttpWebRequest)WebRequest.Create(url);
        request.Method = verb;

        requestParams = requestParams ?? new Dictionary<string, string>();

        Action goRequest = () => MakeRequest(request, 
            response =>
            {
                onSuccess(response);
            },
            error =>
            {
                if (onError != null)
                {
                    onError(error);
                }
            });

        if (request.Method == "POST")
        {
            request.BeginGetRequestStream(ar =>
            {
                using (Stream postStream = request.EndGetRequestStream(ar))
                {
                    byte[] byteArray = Encoding.UTF8.GetBytes(paramsFormatted);
                    postStream.Write(byteArray, 0, paramsFormatted.Length);
                }
                goRequest();
            }, request);
        }
        else // GET
        {
            goRequest();
        }
    }

    private void MakeRequest(HttpWebRequest request, Action<string> onSuccess, Action<Exception> onError)
    {
        request.BeginGetResponse(token =>
        {
            try
            {
                using (var response = request.EndGetResponse(token))
                {
                    using (var stream = response.GetResponseStream())
                    {
                        var reader = new StreamReader(stream);
                        onSuccess(reader.ReadToEnd());
                    }
                }
            }
            catch (WebException ex)
            {
                onError(ex);
            }
        }, null);
    }
查看更多
We Are One
3楼-- · 2020-06-29 01:45

To answer error 4, I made two extension methods so that I can have the GetRespone() and GetRequestStream() methods in the WebRequest class and working like their original versions i.e. blocking the thread. So here it is:

public static class ExtensionMethods
{
    public static WebResponse GetResponse(this WebRequest request){
        ManualResetEvent evt = new ManualResetEvent (false);
        WebResponse response = null;
        request.BeginGetResponse ((IAsyncResult ar) => {
            response = request.EndGetResponse(ar);
            evt.Set();
        }, null);
        evt.WaitOne ();
        return response as WebResponse;
    }

    public static Stream GetRequestStream(this WebRequest request){
        ManualResetEvent evt = new ManualResetEvent (false);
        Stream requestStream = null;
        request.BeginGetRequestStream ((IAsyncResult ar) => {
            requestStream = request.EndGetRequestStream(ar);
            evt.Set();
        }, null);
        evt.WaitOne ();
        return requestStream;
    }
}

Just make sure to place this in a different namespace than your regular code and import that namespace. Then you will have the GetResponse() method for WebRequest instances. Oh and also GetRequestStream() which is usefull for sending POST data

查看更多
登录 后发表回答