list

How to integrate tickets from uservoice into your Windows Phone app

This time, we will have look on how to integrate tickets from uservoice into your Windows Phone app.

Users love to see a history of their tickets they submitted to a customer service. They can review them again, and maybe help also other users by showing or telling them about it.

However, if you want to get a list of all tickets from a specific user, we need to slightly change our request. We need to login as owner of the account to be allowed to search all tickets.

Let’s have a look on how to log in as owner:

        private void LoginAsOwner()
        {
            string loginAsOwnerPath = "/api/v1/users/login_as_owner";
            var client = new RestClient(BaseUrl)
            {
                Authenticator = OAuth1Authenticator.ForRequestToken(ConsumerKey, ConsumerSecret, oAuthCallBackUri)
            };

            //works only with POST!
            var request = new RestRequest(loginAsOwnerPath, Method.POST);
            request.AddHeader("Accept", "application/json");

            var response = client.ExecuteAsync(request, HandleLoginAsOwnerResponse);
        }

        private void HandleLoginAsOwnerResponse(IRestResponse restResponse)
        {
            var response = restResponse;
            var ownerTokens = JsonConvert.DeserializeObject<UserViaMailClass.Token>(response.Content);

            OwnerAccesToken = ownerTokens.oauth_token;
            OwnerAccesTokenSecret = ownerTokens.oauth_token_secret;

        }

The authorization request is pretty similar to the user’s authentication request. However, if we log in as owner, we are getting another AccessToken and another AccessTokenSecret. That’s why we are using the ‘ForRequestToken’-method with our RestClient.

Important to know is that the request itself works only with the HTTP-method ‘POST’, otherwise the login would be denied.

We are getting back the JSON string of our owner account, which can be deserialized with JSON.net to get our AccessToken and AccessTokenSecret. I attached my ‘UserViaMailClass‘ for easy deserialization (yes, it looks similar to the user class from my authentication post, but has some differences in there).

Now that we have our OwnerAccesToken and OwnerAccessTokenSecret, we are able to search for all tickets from a specific user:

        public void GetAllTicketsFromUser()
        {
            string mailaddress = "<usersmailaddress>";
            string getSearchTicketsPath = "/api/v1/tickets/search.json";
            var client = new RestClient(BaseUrl)
            {
                Authenticator = OAuth1Authenticator.ForProtectedResource(ConsumerKey, ConsumerSecret, OwnerAccesToken, OwnerAccesTokenSecret)
            };

            var request = new RestRequest(getSearchTicketsPath, Method.GET);

            request.AddParameter("query", mailaddress);

            var response = client.ExecuteAsync(request, HandleGetAllTicketsFromUserResponse);
        }

        private void HandleGetAllTicketsFromUserResponse(IRestResponse restResponse)
        {
            var response = restResponse;

            var tickets = JsonConvert.DeserializeObject<TicketDataClass.TicketData>(response.Content);
        }

This request is again pretty similar to what we did to get a list of all suggestions. Please find attached my ‘TicketDataClass‘ for easy deserialization.

Of course, users want to be able to submit new tickets/support requests from our app, too. I will show you how to do that:

        public void CreateNewTicketAsUser()
        {
            string ticketsPath = "/api/v1/tickets.json";
            var client = new RestClient(BaseUrl)
            {
                Authenticator = OAuth1Authenticator.ForProtectedResource(ConsumerKey, ConsumerSecret, AccessToken, AccessTokenSecret)
            };

            var request = new RestRequest(ticketsPath, Method.POST);
            request.AddParameter("ticket[subject]", "testing the uservoice API");
            request.AddParameter("ticket[message]", "hi there, \n\nwe are just testing the creation of a new uservoice ticket.");

            var response = client.ExecuteAsync(request, HandleCreateNewTicketAsUserResponse);
        }

        private void HandleCreateNewTicketAsUserResponse(IRestResponse restResponse)
        {
            var response = restResponse;
        }

To submit a new ticket, we are using the user’s AccessToken and AccessTokenSecret. This way, the ticket gets automatically assigned to the ticket. We then need to pass the ‘ticket[subject]’ and ‘ticket[message]’ parameters to the request to make it being accepted by the uservoice API.

The response is a json string that contains the ticket id, which can be used to fetch the submitted ticket data. The Alternative is to call again the search method we created before to get the updated list.

Answering to already existing tickets as user seems to be not possible with the current API. Normally, if a user responds to the response mail we answer their support ticket with, it will get assigned to the existing ticket. If we create a new ticket with the same subject, it will be a new ticket that creates a new thread. I already reached out to uservoice if there is a way to do the same from the API. As soon as I have a response that enables me to do so, I will update this post.

Now that we have all important functions for our new support system, I am starting to make a small helper library for your Windows Phone 8 apps. I hope to have it finished by this weekend, and will of course blog about here.

As always, I hope this blog post is helpful for some of you. Until the next post,

Happy coding everyone!

Posted by msicc in Dev Stories, windev, 4 comments

How to integrate the feedback forum of uservoice into your Windows Phone app

As I described in my first blog post about uservoice, uservoice has a feedback forum where users are able to submit and vote for ideas.

This post is about how to get those ideas into your app. On the API side, the ideas are called suggestions. Now that we know how to authenticate our users for the API, we are able to get a list of suggestions into our app:

        public void GetSuggestions()
        {

            string suggestionsPath = "api/v1/forums//suggestions.json";
            var client = new RestClient(BaseUrl)
            {
                Authenticator = OAuth1Authenticator.ForProtectedResource(ConsumerKey, ConsumerSecret, AccessToken, AccessTokenSecret)
            };

            var request = new RestRequest(suggestionsPath, Method.GET);
            var response = client.ExecuteAsync(request, HandleGetSuggestionResponse);
        }

This is pretty straight forward. We are using the oAuth1Authenticator with our saved tokens as parameter to call the suggestions endpoint of the uservoice API. The result is a JSON string that holds all suggestions as a list.

In our response handler, we are able to deserialize our List of suggestions (best with JSON.net):

private void HandleGetSuggestionResponse(IRestResponse restResponse)
        {
            var response = restResponse;

            var suggestionslist = JsonConvert.DeserializeObject<SuggestionsDataClass.SuggestionsData>(response.Content);
            suggestionsListBox.ItemsSource = suggestionslist.suggestions;
        }

To get the SuggestionsDataClass items, just go to json2csharp.com and pass in the json string we received with response.Content or download it from here: SuggestionsDataClass.

Now let’s have a look on how to submit a new idea on behalf of our user. To submit an idea, we are using the POST method after we authenticated our user again with the uservoice API:

public void PostSuggestion()
        {
            string suggestionsPath = "api/v1/forums//suggestions.json";
            var client = new RestClient(BaseUrl)
            {
                Authenticator = OAuth1Authenticator.ForProtectedResource(ConsumerKey, ConsumerSecret, AccessToken, AccessTokenSecret)
            };

            var request = new RestRequest(suggestionsPath, Method.POST);
            request.AddHeader("Accept", "application/json");
            request.Parameters.Clear();
            request.RequestFormat = DataFormat.Json;

            var newSuggestion = new SuggestionsDataClass.Suggestion();
            newSuggestion.title = "test suggestion number 2 from app development";
            newSuggestion.text = "please ignore this suggestion as we are testing integration of ideas into our apps";
            newSuggestion.vote_count = 3;

            request.AddParameter("suggestion[title]", newSuggestion.title);
            request.AddParameter("suggestion[text]", newSuggestion.text);
            request.AddParameter("suggestion[votes]", newSuggestion.vote_count);
            request.AddParameter("suggestion[referrer]", "uservoice test app");            

            var response = client.ExecuteAsync(request, HandlePostSuggestionResponse);

        }

This call is a bit different from the previous one. We need to pass the idea data to as parameters to our request. The parameter “suggestion[title]” is the main one and always required. As you can see, “suggestion[text]” and “suggestion[votes]” are additional parameters that make the idea complete. All other date is generated by the uservoice server (like posted at, connect to the user who posted that, etc..). The parameter “suggestion[referrer]” is only visible in our admin console and can help you to track from where the suggestion was submitted.

In our response handler, we are receiving a complete set of suggestion data as a JSON string that we can use display to our users and enable sharing of this idea for example:

        private void HandlePostSuggestionResponse(IRestResponse restResponse)
        {
            var response = restResponse;

            //tbd: do something with the result (e.g. checking response.StatusCode)
        }

 

Screenshot (305)

The last important point I want to show you is how to let a user vote for an idea.

        public void VoteOnSuggestion()
        {
            string postUserVotesPath = "/api/v1/forums//suggestions/{0}/votes.json";
            string suggestionId = "";
            var client = new RestClient(BaseUrl)
            {
                Authenticator = OAuth1Authenticator.ForProtectedResource(ConsumerKey, ConsumerSecret, AccessToken, AccessTokenSecret)
            };

            var request = new RestRequest(string.Format(postUserVotesPath, suggestionId), Method.POST);
            request.AddHeader("Accept", "application/json");
            request.Parameters.Clear();
            request.RequestFormat = DataFormat.Json;

            request.AddParameter("to", 3);

            var response = client.ExecuteAsync(request, HandleVotingResponse);

        }

Of course we need to authenticate our user again. We need to pass the suggestion id to the request path (which is part of the Suggestion class). This call accepts only one parameter (“to”). The value can be between 1 and 3 (tip: only offer this three options from your code already to avoid erroneous responses).

The response handler returns the suggestion’s JSON string the user voted on again:

        private void HandleVotingResponse(IRestResponse restResponse)
        {
            var response = restResponse;

            //tbd: do something with the result (e.g. checking response.StatusCode)
        }

This was all about how to integrate the feedback forum of your uservoice account into your app. As always, I hope this will be useful for some of you.

If you want to explore which additional endpoints uservoice has, you are just a click away: https://developer.uservoice.com/docs/api/reference/

Happy coding, everyone!

Posted by msicc in Dev Stories, windev, 0 comments

How to save a List or a Collection on a NFC tag

 

WP8_NFC_PostLogo

As I am currently working again on my NFC app, I needed to save an ObservableCollection to a tag. My first attempts resulted in a heavily overlong string that I wasn’t able to save.

Anyways, after a short convo on Twitter, I went for the right way – serialize to JSON.

The first thing you’ll need for that is the JSON.NET library, which you can get here or via the NuGet package manager in Visual Studio.

After that, you will be able to save your List or ObservableCollection in a few easy steps.

One thing I need to recommend is to make the names in your class/viewmodel as short as possible. Here is my example:

public class ListItems
    {
        //ListItems
        public string i { get; set; }
        //isChecked
        public bool iC { get; set; }
    }

You will need every space you can get on your tag, so you really should go for a similar way like I did above.

After you are done with that, you only need one line of code to convert your List/Collection for writing on your tag:

var ListToSave = JsonConvert.SerializeObject(ItemsList);

Now you will be able to save it as a Text record or  whatever record type you need to save it to.

Deserializing the JSON string works also with only one line of code:

ItemsList = JsonConvert.DeserializeObject<ObservableCollection<ListItems>>(StringFromYourTag);

Then you set the ItemsSource of your ListBox to that (or whatever else the List/Collection is for).

I my case, I was able to save a Collection of 25 items to my tag (writable size 716 bytes) with having still about 200 bytes left in this way.

As always, I hope this will be helpful for some of you.

Happy coding!

Posted by msicc in Dev Stories, windev, 0 comments