为PCL构建RESTful http客户端

时间:2016-05-12 20:36:48

标签: java c# android rest

上下文

最近我开始使用Xamarin开发移动项目,该项目与C#/ .NET一起使用。我来自开发Android应用程序和Java开发。当我在this的应用程序中构建http客户端时,我总是使用相同的方案。我喜欢只有在必要时才重写的概念。我想将这个Java RESTful http客户端转换为C#/ .NET RESTful http客户端。

我想要一个看起来像这样的API:

await MakeGetRequest<List<Role>>(Constants.RolesEnpoint)
            .OnSuccess((response) =>
            {
                //Response which is of type List<Role>
                ShowList(response);
            })
            .OnError((exception) =>
            {
                ShowErrorMessage("Unkown error:" + exception.Message);
            })
            .OnInternatServerError(() =>
            {
                ShowErrorMessage("The server explode");
            });

而且,主要是我面临的问题是我不确定如何实现这些lambda回调。到目前为止我所做的是:

    //<summary>
    // Makes a get request and deserializes the result JSON as T class objects.
    // Check https://forums.xamarin.com/discussion/22732/3-pcl-rest-functions-post-get-multipart
    //</summary>
    //<param name="endpoint">The endpoint name i.e. "/api/v1/feed"</param>
    //<param name="auth">True if we want to seth the AUTH_TOKEN cookie. False otherwise.</param>
    private async RequestTask<T> MakeGetRequest<T>(string endpoint, bool auth = true)
    {
        await new RequestTask<T>((rt) =>
        {
            try
            {
                ValidateAuthToken();
                var request = (HttpWebRequest)WebRequest.Create(new Uri(baseAddress, endpoint));
                SetHeaders(request);
                if (string.IsNullOrEmpty(authToken))
                {
                    rt.OnAuthTokenError();
                }
                request.Headers["Cookie"] = authToken;
                request.Method = "GET";

                HttpWebResponse response = await request.GetResponseAsync();

                if (!response.StatusCode.Equals(HttpStatusCode.OK))
                {
                    rt.OnHttpError(response.StatusCode);
                    switch (response.StatusCode)
                    {
                        case HttpStatusCode.Forbidden:
                            rt.OnForbidden();
                            break;
                        case HttpStatusCode.InternalServerError:
                            rt.OnInternalServerError();
                            break;
                        case HttpStatusCode.RequestTimeout:
                            rt.OnRequestTimeout();
                            break;
                        case HttpStatusCode.GatewayTimeout:
                            rt.OnGatewayTimeout();
                            break;
                        case HttpStatusCode.NotFound:
                            rt.OnNotFound();
                            break;
                        case HttpStatusCode.Unauthorized:
                            rt.OnUnauthorized();
                            break;
                    }
                }

                var respStream = response.GetResponseStream();
                respStream.Flush();

                using (StreamReader sr = new StreamReader(respStream))
                {
                    //Need to return this response 
                    string strContent = sr.ReadToEnd();
                    respStream = null;
                    rt.OnSuccess(JsonConvert.DeserializeObject<T>(strContent, dateTimeConverter));
                }
            }
            catch (Exception e)
            {
                rt.OnError(e);
            }
        });
    }

我不想要一个具体的答案,或者一个完整的代码答案,只是指出正确的方向。

1 个答案:

答案 0 :(得分:0)

这很容易,你想要的是一个流畅的api,它必须接受一些动作,如下:

public class RestClient
{
    Action<HttpWebResponse> onSuccess;
    Action<HttpWebResponse> onError;
    Action<HttpWebResponse> onInternalServerError;

    public RestClient OnSuccess(Action<HttpWebResponse> Handler)
    {
        onSuccess = Handler;
        return this;
    }

    public RestClient OnError(Action<HttpWebResponse> Handler)
    {
        onError = Handler;
        return this;
    }

    public RestClient OnInternalServerError(Action<HttpWebResponse> Handler)
    {
        onInternalServerError= Handler;
        return this;
    }

    private async RequestTask<T> MakeGetRequest<T>(string endpoint, bool auth = true)
    {

       //lots of code, blablabla, just let's go on the handling

       switch(response.StatusCode)
       {
           case HttpStatusCode.OK:

               if(onSuccess != null)
                   onSuccess(response);
               break;

           case HttpStatusCode.InternalServerError:

               if(onInternalServerError!= null)
                   onInternalServerError(response);
               break;

           default:

              if(onError!= null)
                   onError(response);
               break;
       }

    }
}