[Update 3] UserVoice WP8 library for user features

It is done. I made my first library for Windows Phone 8. This blog post is about why I did it and how to use it.

Update: I changed some method names of the library to make it easier to use the library. I updated the code in this post to reflect those changes.

Update 2: I added support to load more pages with clients. On top, I also added my EmojiDetector class, as the UserVoice API does not support Emojis. Check the code below.

Update 3: Now the library supports comments on suggestions and mark as helpful for knowledge base items.

Why UserVoice?

We indie developers have a big problem: We do not have a support team to explain our users how to use our apps or how to solve certain problems/issues. Which leads to our next problem: users are customers. Customers want to be satisfied. It is our job to do this with our apps by providing them a high level user experience and feature rich apps. Often users don’t go the extra mile to send us an email to tell us what is wrong. Or they plan it, but forget about it. Or even worse: they get annoyed and uninstall our apps.

As some of you know, I am working at the hardware support team of a German phone carrier. Over the years, I learned how important it is to listen to customers, pick up their ideas and wishes  and work to get them done if possible. And if it is not possible, you need to tell them that – even that is an important part of customer service!

Many of us have set up a twitter account, a separate mail address, maybe an extra online form to catch all requests from users up. But users tend to not use them for one reason: they are not integrated in our apps. So I spend some time “googling with Bing” (Thanks to @robwirving for that awesome phrase!) on possible solutions.

Uservoice as the best value if using a free subscription, and they have an API that we can use (see also this post on how to get started with uservoice). I made it a very slim library and concentrated on the features we really need in our app on the user side.

The Library!

You can get the library easily via NuGet directly into your app. Just add this package to your app’s packages list:


The library also needs RestSharp, which gets automatically added to your project if you install the library.

After you installed it, you need to declare some variables that we need over and over again while using the library:

Urls.subDomain = "<your subdomain>";
Urls.oAuthCallBackUri = "<your callback url>";
Tokens.ConsumerKey = "<your ConsumerKey>";
Tokens.ConsumerSecret = "<your ConsumerSecret>";

You can get this values out of Settings/Integrations in your UserVoice account.

Additionally, you should save these Tokens to not ask the user for login again and again.


Another important class you should be aware of  is the RequestParamaters class:

Screenshot (309)

It contains the needed variables for all requests, and you can easily use them to save them for TombStoning or anything else you want to save them.

Let’s have a look at the possible requests:

  • Knowledge Base:
KnowledgeBase kb = new KnowledgeBase();`   
//load complete knowledge base  
UservoiceRequests.KnowledgeBase = await kb.getAll();  
//load specific page in your knowledge base
int page = 2;
 UservoiceRequests.KnowledgeBase = await kb.getAll(page);
//load specific topic 
UservoiceRequests.KnowledgeBaseTopic = await kb.getTopic(RequestParameters.topicId);
//load specific page in topic
int page = 2;
UservoiceRequests.KnowledgeBaseTopic = await kb.getTopic(RequestParameters.topicId, page);
//mark article as helpful
var ratingResponse = await kb.markHelpful(RequestParamaeters.articleId);
  •  Suggestions:
Suggestion suggestion = new Suggestion();  
//load all suggestions  
UservoiceRequests.allSuggestions = await suggestion.getAll(RequestParameters.forumId);  
//load specific page in all suggestions
int page = 2;
UservoiceRequests.allSuggestions = await suggestion.getAll(RequestParameters.forumId, page); 
//vote on a suggestion 
UservoiceRequests.voteForSuggestion = await, RequestParameters.suggestionId,;  
//submit new suggestion  
UservoiceRequests.postSuggestion = await suggestion.create(RequestParameters.forumId, RequestParameters.newSuggestionTitle, RequestParameters.newSuggestionText, RequestParameters.newSuggestionReferrer, RequestParameters.newSuggestionVotes); 
//search suggestions  
UservoiceRequests.searchSuggestion = await;
//get all comments for suggestion:
UservoiceRequests.allCommentsForSuggestion = await suggestion.getComments(RequestParameters.forumId, RequestParameters.suggestionId);
//submit a new comment on suggestion:
UservoiceRequests.postCommentOnSuggestion = await suggestion.comment(RequestParameters.forumId, RequestParameters.suggestionId, RequestParameters.newCommentText);
  •  User data:
User user = new User();  
UservoiceRequests.User = await user.getUser();
  •  Tickets:
//Tickets are not associated with the user from the API side. However, you are able to show all tickets from a user with this:  
ticket = new Ticket();  
UservoiceRequests.AllTicketsFromUser = await ticket.getAll(RequestParameters.userMail); 
//load specific page in all tickets:
int page = 2;
UservoiceRequests.AllTicketsFromUser = await ticket.getAll(RequestParameters.userMail, page);
//submit a new ticket on behalf of the user
UservoiceRequests.newTicket = await ticket.create(RequestParameters.TicketSubject, RequestParameters.TicketMessage);

As you can see, all requests are async.

You don’t need explicitly authenticate a user, because the library is built to detect this automatically. If an authenticated user is required, the user will be redirected to the authentication page of UserVoice.

In the current version, you will need to manual send the request again after the user is authenticated, but I will update the library to make also this automatically soon.

  • EmojiDetector
  string text = "here would be the string from your textboxes that contain emojis";

            //check if Emojis are in text:
            if (EmojiDetector.HasEmojis(text) == true)
                //your code here
            //remove Emojis in text:
            text = EmojiDetector.RemoveEmojis(text);

The UserVoice API does not support Emojis, that’s why I wrote this little helper that you can easily use to remove them with only one line of code or to display a message to your users.

One last point: I don’t use RestSharp’s serializer – all request return the corresponding JSON string. This way, everyone of you can use the serializer of choice (I absolutely recommend, though).

Please consider the current version as beta release, and report any issues with that to me via Twitter or mail.

And now enjoy my library & happy coding!



Posted by msicc in Archive, 9 comments

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 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 Archive, 4 comments

Experiment: using for Support, Feedback and FAQ

On my daily job, I am working as a Mobile Hardware Support Agent of a German  carrier. Because of that, I know how important a good support for customers (=users) is – and also, a little knowledge base where users can find most probably an answer for their  questions.

I want my customers to be satisfied. As an indie developer, I have a little problem: I don’t have a support team that catches all the support questions for me. I need to do this by myself. Until now, I am doing this by using a send-me-a-mail button in my apps. However, due to the fact that I have a 9to5 job and a family besides developing apps, time is a bit limited for me. I searched for some solutions to improve the way I am doing my customer service, and uservoice seems like a good tool to improve my customer service a lot.

As you can see at the feature comparison list of uservoice, the free account already allows you to do a lot of things: It is free for one support agent – perfect for an indie developer like me.

What can you do with uservoice?

uservoice has a lot of features:

  • support ticket system
  • knowledge base
  • feedback system/forum
  • and many more, if you are going for a paid plan

Let’s have a look at the first three features:

Support ticket system

Adding the ticketing system is very easy. You just need a EMailComposeTask pointing to your ticket system. Your standard mail address for that will be: “tickets@<yourname>”. This is how a received ticket looks like:

Screenshot (289)

Answering to a user is as easy as writing an email – plus you have a ticket history at a glance.

On top of that, you are able to insert a so called ‘canned response’ based on your knowledge base:

Screenshot (290)

Knowledge base

You can build up a knowledge base for your apps.

Screenshot (286)

In the left menu at the bottom at your admin console, you will find the ‘ARTICLES’ section. This is where all the knowledge base articles are collected.

You can create also topics within that KB. I did so for all of my apps:

Screenshot (286)

This way, you can use your free account to support all of your apps with FAQ/KB articles – pretty easy.

Here is how to set up a new article: after clicking on ‘All articles’, there is a ‘New Article’ button on the right side of your screen. Click on that, you will see this on the right hand side:

Screenshot (287)

You can set up the article name, the text and the topic as well as the position you want to show it up in your knowledge base.

You can take a look at my knowledge base here:

How can you use this in your apps? I plan to create an API wrapper for their C# SDK, which is not compatible with Windows Phone at the moment. I will write another blog post for that. Luckily, uservoice as a very nice mobile interface, so you can start off with a simple WebBrowserTask to open your knowledge base:


Technically, it would be possible to use a WebBrowser control, too. But you would need to code more to get a proper browsing handling.

Feedback system/forum

Some of you might be already familiar with the feedback or idea forum of uservoice (even Microsoft uses this). This time, we look at the other side of the forum, from our admin console:

Screenshot (292)

You have a similar view to what users see, but there are some more parts to control your forum. As a free user, you have only one forum, so it might be useful if you add the app name in front of the title of an idea. You can respond, take notes, and change the status of the ideas:

Screenshot (293)

To integrate the feedback function in your app, you can again use a WebBrowserTask to open the mobile page of your idea forum:


These are the first simple steps to create your own customer support system with uservoice. Like I said before, I will write a Windows Phone wrapper to get this into an app as native, and will share it here with you all.

Until the next post, happy coding!

Posted by msicc in Archive, 0 comments