Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start a REST plugin? #240

Closed
slodge opened this issue May 1, 2013 · 17 comments
Closed

Start a REST plugin? #240

slodge opened this issue May 1, 2013 · 17 comments
Labels
t/feature Feature request type

Comments

@slodge
Copy link
Contributor

slodge commented May 1, 2013

Feels like I've been toying with this for ages... could just put the standard cut&paste stuff in the JSON plugin?

I don't really want to get caught up in the REST details, but a simple 80% plugin might help get the ball rolling...

public interface ISimpleRestService
{
    void MakeRequest<T>(string requestUrl, string verb, Action<T> successAction, Action<Exception> errorAction);
}

public class SimpleRestService
    : ISimpleRestService
{
    private readonly IMvxJsonConverter _jsonConverter;

    public SimpleRestService(IMvxJsonConverter jsonConverter)
    {
        _jsonConverter = jsonConverter;
    }

    public void MakeRequest<T>(string requestUrl, string verb, Action<T> successAction, Action<Exception> errorAction)
    {
        var request = (HttpWebRequest)WebRequest.Create(requestUrl);
        request.Method = verb;
        request.Accept = "application/json";

        MakeRequest(
           request,
           (response) =>
           {
               if (successAction != null)
               {
                   T toReturn;
                   try
                   {
                       toReturn = Deserialize<T>(response);
                   }
                   catch (Exception ex)
                   {
                       errorAction(ex);
                       return;
                   }
                   successAction(toReturn);
               }
           },
           (error) =>
           {
               if (errorAction != null)
               {
                   errorAction(error);
               }
           }
        );
    }

    private void MakeRequest(HttpWebRequest request, Action<string> successAction, Action<Exception> errorAction)
    {
        request.BeginGetResponse(token =>
        {
            try
            {
                using (var response = request.EndGetResponse(token))
                {
                    using (var stream = response.GetResponseStream())
                    {
                        var reader = new StreamReader(stream);
                        successAction(reader.ReadToEnd());
                    }
                }
            }
            catch (WebException ex)
            {
                Mvx.Error("ERROR: '{0}' when making {1} request to {2}", ex.Message, request.Method, request.RequestUri.AbsoluteUri);
                errorAction(ex);
            }
        }, null);
    }

    private T Deserialize<T>(string responseBody)
    {
        var toReturn = _jsonConverter.DeserializeObject<T>(responseBody);
        return toReturn;
    }
}
@HowardvanRooijen
Copy link

Here's what I've thrown together to get a simple GET / JSON workflow working - looks very similar...

    public class HttpClient : IHttpClient
    {
        private const string SuccessAction = "SuccessAction";
        private const string ErrorAction = "ErrorAction";
        private const string StatusAction = "StatusAction";
        private const string RequestAction = "RequestAction";
        private const string Payload = "Payload";

        public void GetAsync<TResult>(Uri uri, Action<TResult> success, Action<Exception> error, Action<int> status)
        {
            var request = WebRequest.Create(uri);

            var context = new Dictionary<string, object>
            {
                { HttpClient.SuccessAction, success },
                { HttpClient.ErrorAction, error },
                { HttpClient.StatusAction, status },
                { HttpClient.RequestAction, request }
            };

            request.BeginGetResponse(this.GetAsyncCallback<TResult>, context);
        }

        private void GetAsyncCallback<TResult>(IAsyncResult ar)
        {
            var context = (Dictionary<string, object>)ar.AsyncState;
            var error = (Action<Exception>)context[HttpClient.ErrorAction];

            try
            {
                var request = (HttpWebRequest)context[HttpClient.RequestAction];
                var success = (Action<TResult>)context[HttpClient.SuccessAction];
                var status = (Action<int>)context[HttpClient.StatusAction];

                var response = (HttpWebResponse)request.SafeEndGetResponse(ar);

                status((int)response.StatusCode);

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    using (var streamReader = new StreamReader(response.GetResponseStream()))
                    {
                        string content = streamReader.ReadToEnd();
                        var result = JsonConvert.DeserializeObject<TResult>(content);

                        success(result);
                    }
                }
            }
            catch (Exception exception)
            {
                error(exception);
            }
        }
    }

@slodge
Copy link
Contributor Author

slodge commented May 1, 2013

Thanks

I'll kick off this REST plugin at some point soon (next couple of days) - then hand it over to you/your apprentice for finishing, testing, nuget'ing etc

Happy for it to go in endjin namespace (cirrious has got plenty in it already)

I would avoid HttpClient as a name though ;)

@HowardvanRooijen
Copy link

All sounds good to me.

@dbeattie71
Copy link
Contributor

Does the new PCL HttpClient stuff work on Android and Touch?

@slodge
Copy link
Contributor Author

slodge commented May 1, 2013

I believe Xamarin provided their own port...

But apparently this is the type of question when I need to use a bat signal up

<BatSignal>@dsplaisted</BatSignal>

@slodge
Copy link
Contributor Author

slodge commented May 1, 2013

Hmmm.. code escaped batsignals might not work @dsplaisted!

@slodge
Copy link
Contributor Author

slodge commented May 1, 2013

If you feel like leave random links on issues...

... please add some text explaining what your point is/isn't

Pure randomness is reserved for me only :)

Thanks

@slodge
Copy link
Contributor Author

slodge commented May 1, 2013

Thanks - I'm sure Daniel wrote part of those packages... so I'd hope he knows what they are!

But I still have no idea what point you are trying to make. Is there some question you are trying to answer? Are you suggesting we shouldn't build a REST plugin because of these packages?

Sorry - really very happy for you to contribute ideas, code, links and more - but I've really no idea what you are trying to say.

If in doubt, assume I'm still jet-lagged or just that I'm the middle of ten different things... spell it out for me... who do you want to do what with those links?

Adding a smilie to help avoid Godwin's Law :)

Thanks

Stuart

@dbeattie71
Copy link
Contributor

I'm not sure actually :)

@slodge
Copy link
Contributor Author

slodge commented May 1, 2013

The problem with randomness is you can never be sure... http://dilbert.com/strips/comic/2001-10-25/ :)

@dbeattie71
Copy link
Contributor

I think I thought that the current portable Http stuff doesn't support compression or the compression parts would have to live in platform specific projects. The new portable HttpClient seems more robust and compression works with adding another nuget "plugin."

@dsplaisted
Copy link
Contributor

The PCL HttpClient isn't supported (or licensed to run) on Mono, but Xamarin has their own version. You should be able to create a PCL that uses Microsoft.Bcl.Async on Microsoft platforms and Xamarin's version on Mono, but right now you there might be "hacks" required to do so. When Xamarin releases official PCL support hopefully we can make this better.

In any case, one option is just to use HttpClient in the platform-specific implementations of your REST plugin.

@slodge
Copy link
Contributor Author

slodge commented May 7, 2013

Not forgotten this....

Just working on it more slowly than anticipated.

(open questions like whether to use httpwebrequest or httpclient... whether to support multipart forms... prototype 1 will be up 'soon' then I'll leave it to others!)

@slodge
Copy link
Contributor Author

slodge commented May 9, 2013

Code started - pushed it into the network plugin for now - it needed a reason to live.

First commit is:
fafbb6a

It still needs tidying (lots of), testing and some better post stuff added.

Also, it's lacking WP compression (my bug-bear)

Will get a bit more done tomorrow - but then very ready to hand this on - it can be put in a separate repo or worked on in-place - or we can leave this one as-is and then create a second one or...


I hacked it into the N=7 Books example briefly with code like

public class SimpleRestService
    : ISimpleRestService
{
    private readonly IMvxJsonRestClient _json;

    public SimpleRestService(IMvxJsonRestClient json)
    {
        _json = json;
    }

    public void MakeRequest<T>(string requestUrl, Action<T> successAction,
                               Action<Exception> errorAction)
    {
        var request = new MvxRestRequest(requestUrl);
        _json.MakeRequest(request, (MvxDecodedRestResponse<T> resp) => successAction(resp.Result), errorAction);
    }

}

Which is called via:

        string address = string.Format("https://www.googleapis.com/books/v1/volumes?q={0}",
                                        Uri.EscapeDataString(whatFor));
        _simpleRestService.MakeRequest<BookSearchResult>(address, success, error);

@zleao
Copy link
Contributor

zleao commented Jul 12, 2013

I'll be starting to use this plugin.... Does anyone have a newer version than the one provided in the MvvmCross-V3 branch of @slodge?
If someone has a more complete version that I can work with, I'll be much appreciated. I'll be runing some tests and hoppefully I'll add my contribution if needed.
Thanks!

@slodge
Copy link
Contributor Author

slodge commented Jul 23, 2013

Well... this is definitely started... and I know @zleao has some changes underway... and I know others have said they were doing bits... but that's all gone quiet.

So I'm closing this general issue.

Other more specific issues will have to be raised for specific increments.

And I do still hope to get a PCL demo using RestSharp up and running one day....

Thanks all

Stuart

@slodge slodge closed this as completed Jul 23, 2013
@slodge
Copy link
Contributor Author

slodge commented Jul 26, 2013

Also cross referencing in https://github.com/zleao/MvvmCrossUtilities from #362 :)

martijn00 added a commit to martijn00/MvvmCross that referenced this issue Dec 8, 2016
…names

Call MvxAppCompatSetupHelper.FillDefaultBindingNames
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
t/feature Feature request type
Development

No branches or pull requests

5 participants