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.
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.
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.
Tokens.AccessToken Tokens.AccessTokenSecret Tokens.OwnerAccessToken Tokens.OwnerAccessTokenSecret
Another important class you should be aware of is the RequestParamaters class:
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.knowledgeBase(); //load specific topic UservoiceRequests.KnowledgeBaseTopic = await kb.knowledgeBaseTopic(RequestParameters.topicId);
Suggestion suggestion = new Suggestion(); //load all suggestions UservoiceRequests.allSuggestions = await suggestion.allSuggestions(RequestParameters.forumId, RequestParameters.suggestionsPage); //vote on a suggestion UservoiceRequests.voteForSuggestion = await suggestion.voteOnSuggestion(RequestParameters.forumId, RequestParameters.suggestionId, RequestParameters.vote); //submit new suggestion UservoiceRequests.postSuggestion = await suggestion.newSuggestion(RequestParameters.forumId, RequestParameters.newSuggestionTitle, RequestParameters.newSuggestionText, RequestParameters.newSuggestionReferrer, RequestParameters.newSuggestionVotes); //search suggestions UservoiceRequests.searchSuggestion = await suggestion.searchSuggestions(RequestParameters.suggestionsSearchQuery);
- User data:
User user = new User(); UservoiceRequests.User = await user.userData();
//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.allTicketsFromUser(RequestParameters.userMail); //submit a new ticket on behalf of the user UservoiceRequests.newTicket = await ticket.newTicket(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.
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 JSON.net, though).
And now enjoy my library & happy coding!