wpdev

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 authenticate users with the uservoice API on Windows Phone

I am really enjoying playing around with the uservoice API. It enables me to integrate a lot of cool new features that take the user experience to a new level, while helping me to improve my apps.

Today, I am going to write about how to authenticate a user with the uservoice API.

uservoice uses the oAuth authentication in version 1.0a. Therefore, we need a consumer key and a consumer secret for our app. Log into <yourname>.uservoice.com, and go to ‘Settings/Integration’, where you create a new API client for your app.

I recommend to set it up as a trusted client, as you will have more rights with a trusted client. After your set up your app, you should have an entry like this under integrations:

uservoice_api_client

Now we have everything set up on the uservoice part. Let’s go to our app. I am using the RestSharp library that makes it a little easier to authenticate users. You should do the same if you want to follow along this post. In Visual Studio, right click the project name and select ‘Manage NuGet packages’, and search for RestSharp in the ‘Online’ section.

After we have integrated the RestSharp library in our app, we are going to set up some objects for authentication:

 const string ConsumerKey = "<yourkey>";
 const string ConsumerSecret = "<yoursecret>";
 static string oAuthToken = "";
 static string oAuthTokenSecret = "";
 static string oAuthVerifier = "";
 static string AccessToken = "";
 static string AccessTokenSecret = "";
 const string BaseUrl = "http://<yourname>.uservoice.com";
 const string oAuthCallBackUri = "<yourcallbackUrl>";
 const string requestTokenPath = "oauth/request_token";
 const string authorizePath = "/oauth/authorize?";
 const string accessTokenPath = "oauth/access_token";

Setting up these static and constant string object are needed for our authentication flow.

Next, add a WebBrowser control in XAML. We need this to let the user authorize our app to communicate with the uservoice servers:

<Grid x:Name="authBrowserGrid" Visibility="Collapsed">
 <phone:WebBrowser x:Name="authBrowser" Height="800" Width="460"></phone:WebBrowser>
 </Grid>

You might have noticed that I set the Visibility property  to collapsed.  With oAuth, we are typically authenticating users by referring them to the web site, that handles the login process for us. After the user has authorized our app, the website transfers the user to our callback url that we define with our API client.

As I told you already above, RestSharp helps us a lot when it comes to authentication.

There are several ways to use the RestSharp API, but for the moment, I am using it directly to authenticate my users.

This is the start method:

public void GetUserAuthenticated()
 {

            authBrowserGrid.Visibility = Visibility.Visible;

            var client = new RestClient(BaseUrl)
 {
 Authenticator = OAuth1Authenticator.ForRequestToken(ConsumerKey, ConsumerSecret, oAuthCallBackUri)
 };

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

We are creating a new RestClient that calls our BaseUrl which we defined before. In the same call, we are telling our client that we want to use oAuth 1.0(a), passing the parameters ConsumerKey, ConsumerSecret and our callback url with the client. As we want to receive a RequestToken, we are generating a new RestRequest, passing the requestTokenPath and the ‘GET’ method as parameters.

Finally, we want to continue with the response, that should contain our RequestToken. Windows Phone  only supports the ExecuteAsync method, which needs a specific response handler to be executed. That was the first lesson I had to learn with using RestSharp on Windows Phone. To handle the response, we are creating a new handler method that implements ‘IRestResponse’: 

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

          //tbd: write an extraction helper for all tokens, verifier, secrets
 oAuthToken = response.Content.Substring((response.Content.IndexOf("oauth_token=") + 12), (response.Content.IndexOf("&oauth_token_secret=") - 12));
 var tempStringForGettingoAuthTokenSecret = response.Content.Substring(response.Content.IndexOf("&oauth_token_secret=") + 20);
 oAuthTokenSecret = tempStringForGettingoAuthTokenSecret.Substring(0,  tempStringForGettingoAuthTokenSecret.IndexOf("&oauth_callback_confirmed"));

var authorizeUrl = string.Format("{0}{1}{2}",BaseUrl, authorizePath, response.Content);

           authBrowser.Navigate(new Uri(authorizeUrl));
 authBrowser.IsScriptEnabled = true;
 authBrowser.Navigating += authBrowser_Navigating;

}

We now have an object that we are able to work with (the variable response). We need to extract the oauth_token and the oauth_token_secret and save them for later use.

After that, we can build our authorization url, that we pass to the WebBrowser control we created earlier. Important: you should set the ‘IsScriptEnabled’ property to true, as authentication websites often use scripts to verify the entered data. Last but not least, we are subscribing to the Navigating event of the browser control. In this event, we are handling the response to the authorization:

void authBrowser_Navigating(object sender, NavigatingEventArgs e)
 {
      if (e.Uri.AbsolutePath == "<yourAbsolutePath>")
      {
           oAuthVerifier = e.Uri.Query.Substring(e.Uri.Query.IndexOf("&oauth_verifier=") + 16);

           GetAccessToken();
      }
 }

We only need the verification string for out next request we have to send, so we are extracting the parameter “oauth_verifier” and going over to get our AccessToken for all further requests:

private void GetAccessToken()
 {
 var client = new RestClient(BaseUrl)
 {
 Authenticator = OAuth1Authenticator.ForAccessToken(ConsumerKey, ConsumerSecret, oAuthToken, oAuthTokenSecret, oAuthVerifier)
 };

            var request = new RestRequest(accessTokenPath, Method.GET);
 var response = client.ExecuteAsync(request, HandleAccessTokenResponse);

        }

This time, we are telling our RestClient that we want to get the AccessToken, and we need also the oAuthToken and the oAuthTokenSecret we saved before we navigated our users to the uservoice authentication site. Of course, we also need a handler for the response to this request:

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

            AccessToken = response.Content.Substring(12, response.Content.IndexOf("&oauth_token_secret=") -12);
 AccessTokenSecret = response.Content.Substring(response.Content.IndexOf("&oauth_token_secret=") + 20);

            authBrowserGrid.Visibility = Visibility.Collapsed;

            //continue with your code (new method call etc.)
 }

The only thing we now need to do is to extract the AccessToken and the AccessTokenSecret and save them permanently in our app (as long as the user is authenticated). We need them for a lot of calls to the uservoice API.

Let’s call the uservoice API to get more information about the user that has now authorized our app:

public void GetUser()
 {
 var client = new RestClient(BaseUrl)
 {
 Authenticator = OAuth1Authenticator.ForProtectedResource(ConsumerKey, ConsumerSecret, AccessToken, AccessTokenSecret)
 };

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

As you can see, we are now only using the AccessToken and the AccessTokenSecret to call the uservoice API, no additional login is required. To complete this sample, here is again the handler for the response:

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

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

       }

We have now received a JSON string that tells us a lot of information about our user and the date we have on uservoice:

Screenshot (304)

 

As you can see, it is relatively easy to get our users authenticated and calling the uservoice API. In my next blog post, I will write about suggestions (that’s the idea forum). I will go into details on getting a list of all suggestions, how to let a user post a new idea and letting a user vote for ideas – all from within  your app!

In the meantime, I hope this post is helpful for some of you.

Happy coding, everyone!

Posted by msicc in Dev Stories, windev, 2 comments

How to fetch articles from your uservoice knowledgebase into a Windows Phone app

As some of you might know, I recently switched to uservoice.com for feedback, support and also FAQ hosting (read more here). Of course I want to integrate all those features into my app(s) to make the user experience as native as possible.

First, you need to generate a new app in uservoice.com. Log into your account, click on ‘Admin Console’, ‘Settings’ and finally ‘Integrations’. Then add your API client, you will have something like this:

uservoice_api_client

Today, we are starting with getting our knowledge base articles into our app.

This is the easiest part besides assigning the support mail address to a button.

Here is how we are doing it:

First, we need to declare some constants:

//consumer key and secret are needed to authorize our requests (oAuth)
 //KB articles only need the ConsumerKey
 const string ConsumerKey = "<youKey>";
 const string ConsumerSecret = "<yourSecret>";
 //all KB articles:
 const string KnowledgebaseString = "http://<yoursubdomain>.uservoice.com/api/v1/articles.json?client={0}";
 //KB topic articles:
 //using sort=oldest ensures that you will get the right order of your articles
 const string KnowledgebaseTopicString = "http://<yousubdomain>.uservoice.com/api/v1/topics/{0}/articles.json?client={1}&sort=oldest";

static string articleJsonString;

As you can see, we have two options to fetch our knowledgebase articles – all articles (if you have only one app, you’re fine with that) or topic based.

To get the needed topic id, just open the topic in your browser. The topic id is part of the url:

uservoice_topic_id

For getting authorized to receive the JSON string of our knowledge base, we need to pass the consumer key as parameter “client” to the base url of our request. To get our list sorted, I am using the sort parameter as well.

To receive the JSON string, we are creating an async Task<string> that fetches our article. To make the result reloadable, add the IfModifiedSince Header (otherwise Windows Phone caches the result during the app’s current lifecycle).

//receiving the JSON string for our KB does not need any advanced requests: 
//a basic HttpClient handles everything for us, as we don't need any authentication here
public async Task<string> GetKBJsonString()
{
      string getKBJSonStringFromUserVoice = string.Empty;

     HttpClient getKBJsonClient = new HttpClient();
     getKBJsonClient.DefaultRequestHeaders.IfModifiedSince = DateTime.Now;

     getKBJSonStringFromUserVoice = await getKBJsonClient.GetStringAsync(new Uri(string.Format(KnowledgebaseTopicString, "47463", ConsumerKey), UriKind.RelativeOrAbsolute));

      return getKBJSonStringFromUserVoice;
 }

Of course we want to have a list shown to our users – to display our JSON string in a ListBox, we need to deserialize it. To be able to deserialize it, we need a data class. You can use json2sharp.com to generate the base class or use this one (download Link). It fits for both all articles or topic based articles.

First, create a ListBox with the corresponding DataTemplate (I am only using question and answer text for this demo).

            <ListBox x:Name="FAQListBox">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"></RowDefinition>
                                <RowDefinition Height="Auto"></RowDefinition>
                            </Grid.RowDefinitions>
                            <TextBlock Grid.Row="0" x:Name="questionTB" Style="{StaticResource PhoneTextTitle2Style}" Text="{Binding question}" TextWrapping="Wrap"></TextBlock>
                            <TextBlock Grid.Row="1" x:Name="answerTB" Style="{StaticResource PhoneTextSubtleStyle}" Text="{Binding text}" TextWrapping="Wrap"></TextBlock>
                        </Grid>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

I am using JSON.net for everything around JSON strings. Here is how to deserialize the JSON string and set the ItemsSource of our Listbox:

            articleJsonString = await GetKBJsonString();

            var articlesList = JsonConvert.DeserializeObject<KBArticleDataClass.KBArticleData>(articleJsonString);

            FAQListBox.ItemsSource = articlesList.articles;

You are now already able to run the project. Here is the result of my test app, displaying the FAQ of my NFC Toolkit app:

uservoice_listbox_testapp_screenshot

As you can see, it takes only about ten minutes to get the knowledge base into your app. Using a remote source has a lot of advantages, the most important one is you don’t need to update your app when you add new answered questions.

I am now starting to work on integrating the feedback forum. It requires an oAuth authentication, and will be a bit more complicated than this one. Of course I will share it with you all here on my blog – stay tuned.

Until then – happy coding!

Posted by msicc in Dev Stories, windev, 3 comments

[Updated] NFC Toolkit uri schemes

app2app_nfctoolkit

If you are following me, you might have noticed that uri schemes actually are playing a big role in my Windows Phone apps. (read more)

NFC Toolkit, one of my main projects, offers now also the possibility to interact with your apps.

One of the unique features of NFC Toolkit is profiles. Profiles are designed to open up to 5 settings pages in a row (as directly setting them is not possible because of OS restrictions). At the end of a profile, an extra from within the app or another app can be launched.

In Phase I, NFC Toolkit enables other developers to add their custom uri association/scheme to the list of launchable apps in profiles.

Here is how the uri needs to be formatted to work:

"nfctoolkit:addmyapp?appname=<yourappnamehere>&urischeme=<yoururischemehere>"

I will add more uri associations with the next updates and update this post with them.

[Update 2]

Starting with version 0.9.8.1 of NFC Toolkit, I added new uri schemes to enable you to write data on NFC tags. Here is the list of possible writing records:

  • website record:
"nfctoolkit:writetag?type=smartposter&url=<url>&title=<title of the website>&languagecode=<two letter lang code (standard: en)>"
  •   text record:
"nfctoolkit:writetag?type=text&content=<your text here>&languagecode=<two letter lang code (standard: en)>"
  • send mail record:
"nfctoolkit:writetag?type=mail&mailaddress=<mailaddress>&mailsubject=<mailsubject>&mailbody=<mailbody>"
  •  settings page:
//supported pages: flight mode, cellular, WiFi, Bluetooth, location, lock screen
"nfctoolkit:writetag?type=settings&page=<settings page name as listed above>"
  •  launch system app:
//supported pages: 
//"Alarm", "background tasks", "brightness settings", "Bing Vision", "Calculator", "Calendar", "call history", 
//"Camera", "Data Sense", "date + time settings", "ease of access", "find my phone", "Games", "Help+Tips", 
//"Internet Explorer", "internet sharing", "keyboard settings", "kid's corner settings", "language + region settings", 
//"Maps",  "Messaging", "Music+Videos", "Office", "OneNote", "People", "Phone", "phone information", "Photos", 
//"Rooms", "SIM Applications", "Start", "Store", "theme settings", "Wallet"
"nfctoolkit:writetag?type=sysapp&name=<system app name as listed above>"
  •  launch any app by name or publisher name:
//launches the store page search in NFC Toolkit and searches for the app/publisher
"nfctoolkit:writetag?type=launchapp&appname=<app name or publisher name>"

On top of that, I added an uri scheme that allows a plain launch of NFC Toolkit:

"nfctoolkit:home"

I updated my custom uri scheme test app as well for you. Download it here: CustomUriSchemeTestApp

Happy coding everyone!

 

 

 

Posted by msicc in Archive, 5 comments

Experiment: using uservoice.com 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: https://www.uservoice.com/plans/?ref=top_pricing. 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>.uservoice.com”. 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: https://msiccdev.uservoice.com/knowledgebase

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:

wp_ss_20140106_0001

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:

wp_ss_20140106_0002

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 Dev Stories, windev, 0 comments

A simple approach to remove QueryStrings from NavigationContext on Windows Phone

QuerystringsRemove

Like most of you know, I am currently adding a lot of new features to my NFC Toolkit for Windows Phone.

Today, my coding session is all about uri schemes again. I successfully added some new uri schemes that you will be able to use soon.

However, if you start an app via an uri scheme, you will have  QueryStrings in your NavigationContext on the desired ApplicationPage. If a user continues to use your app, navigates away from the launched page and back to it, the code based on your QueryStrings will be called again.

As I am a daily Windows Phone user by myself, I know this is somewhat annoying. So I searched for a solution. I first thought about removing entries in the BackStack, but that would need a lot of code if you are running an application that has more than two pages – you’ll need to add methods to check if you are coming from an uri scheme, clear the BackStack, pass the parameters to the next page, get back to your MainPage, check the parameters again. Totally unusable in my opinion.

The NavigationContext.QueryString property has a Remove() method as I found out while researching a bit more – that’s what I am using now to get the result I want – make the app running like it was launched normally without uri scheme after the action has taken place.

I found some examples that are using the method in the  OnNavigatedTo() event. I don’t think that’s the right way, as I often happen to have some more code in this event, and it will probably break other functionality. I am using the OnNavigatedFrom() event.

Add this lines of code for every QueryString you want to remove (depending on your method structure, it is ok to remove only the QueryString you rely on in your further code, additional parameters can be still there ):

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
   if (NavigationContext.QueryString.ContainsKey("key1"))
   {
      NavigationContext.QueryString.Remove("key1");                                
   }
   if (NavigationContext.QueryString.ContainsKey("key2"))
   {
       NavigationContext.QueryString.Remove("key2");
   }            
   base.OnNavigatedFrom(e);
}

This way, if you are navigating to another page in your app or even if the user uses the Windows Button, the corresponding QueryString will be removed – and your users are able to use the app as they would have launch it without an uri scheme.

However, that’s not all. When your app get’s Tombstoned, the UriMapper will map the uri scheme again on Activation – not what you might want. To get around this, I use a simple Boolean, set it to true when I am coming back from Tombstoning:

private void Application_Activated(object sender, ActivatedEventArgs e)
{
    if (!e.IsApplicationInstancePreserved)
    {
        wasTombstoned = true;  
    }
}

Now the only thing you will need to to is to add

&& App.wasTombstoned == false

as second argument to your QueryString clause – that’s it!

I am not sure if this is a good approach or not, but it works. It allows you to launch your uri scheme, and enables the user to use your app after that as it would have been launched normally. If you have other ways to get the same result, feel free to leave a comment below.

Otherwise, I hope this post is helpful for some of you.

Happy coding!

Posted by msicc in Dev Stories, windev, 5 comments

A year in the like of MSicc – my review of 2013

dev smurf

2013 was a year with a lot of surprises. It was a year full of community work for me as well as a huge learning year in development. But my year had also dark clouds on heaven. This post is my personal review of 2013 – you can like my impressions or not.

I started the year with releasing my first Windows 8 app ever, along with an huge update to my blog reader app for Windows Phone. I wrote several blog posts and started also development of my NFC Toolkit app for Windows Phone (Archive: January). I also ran a beta test for my NFC Toolkit, and finished my series about the parts that should help other developers  to write a blog reader app for both Windows and Windows Phone (Archive February & Archive March).

Then in April, the first time I had dark clouds hanging deeply in my life, affecting all parts – family, community work and also my 9to5 job. My wife had once again problems with her back, caused by slipped discs. It went as far as she needed to rest in hospital for a pain therapy. Luckily this therapy was helping her and our life went back to normality (knocking on wood).

I also started a new series on the WinPhanDev blog – Why we started developing (WWSDEV). We are collecting stories from developers, and posting them over there to motivate other developers and keep the community spirit alive. Just have a look, we have really great stories over there.

In the last days of April/beginning of May, Iljia engaged me to start using Windows Azure Mobile Services to make an app idea reality: TweeCoMinder was born. It is a very special and unique app, interesting for those that don’t want to miss their special counts on Twitter, supported by real push notifications via WAMS for both Live Tiles and Toast Notifications. I learned a lot during setting up my WAMS for the app, and I did also write some blog posts about that (AzureDev posts).

Because of TweeCoMinder, I stopped developing my NFC app for that time, and did only bug fixing updates to my other apps.

In August (at least in the spare time I had), I moved my blog completely to run in a Windows Azure VM. I did it to get more control over the whole system and to learn more about running a web service. I still need to write my blog posts about setting the VM with LAMP on Azure, but I just didn’t have time for that until now. In August/September I also had again very very dark clouds hanging around, with my wife was very ill (you can’t even imagine how happy I am about the fact she has this part behind her). But our daily live is still affected by this – we just learned to arrange us with the new situation.

In October, I got back to my NFC Toolkit to finish it finally. The app has some cool and unique features utilizing NFC tags, and I am quite satisfied with my download numbers. NFC Toolkit is my main project for the moment.

But also on my 9to5 job I came to write code. I was asked to write an internal app for Windows Phone (Telefónica has a partnership with Microsoft, and so the company is flooded with Windows Phones). I used this to learn more about speech recognition on Windows Phone, as this is part of the application (Make your app listening to the user’s voice).

And finally, I also started with my very first Android app using Xamarin while porting the Windows Phone app I wrote before. I recently started to blog about my experiences with Xamarin (read more here).

In between all those projects, I made a basic reader app for the fan blog “This is Nokia”, using a PCL project for both Windows Phone 8 and Windows 8. I also wrote a simple car dashboard app to integrate it in my NFC Toolkit app as well as Mix, Play & Share, which was written on a lonely Saturday night while my kids where sleeping an my wife was at her best friend.

Through the year, I learned a lot of coding, but also a lot about people. I made some very positive experiences – but also bad ones. I am always willing to help (if my still growing knowledge enables me to do so) – but sharing a feature rich app to another person isn’t helping – if you want to learn about development, there are plenty ways to do so. We have really great developers that blog about their experiences in our community, and by understanding how to code, you truly learn. Just using an already working app and restyling it, is the wrong way.

Well, that is what my year was about – a lot of coding, learning and again coding.

Dear followers, friends, WinPhans & WinPhanDevs – thank you for being with me this year. Let’s make 2014 an even more exciting year.

I wish you all “a good slide into the new year”, as we say here in Germany. May god bless you and your families also in the new year.

Posted by msicc in Editorials, 0 comments

Merry Xmas, everyone!

 

Merry-Christmas

 

This year was an amazing year. We got a lot of new devices, great apps, and a lot of development work was done.

Now, with Xmas around the corner, I want to wish all of you a

Merry Christmas!

After the xmas days, I will start a new series here on my blog, together with my review post of 2013.

Enjoy your family time, and may god bless you all!

Posted by msicc in Archive, 0 comments

[Updated] Why Windows Phone apps deserve a custom uri scheme (and how to add a simple launch uri)

app2app_Windows_Phone

Microsoft introduced custom uri schemes or uri associations in Windows Phone 8 along with the ability to launch apps based on a file type.

Sadly, this feature is not used across a broad range of apps yet. Why am I so interested in that point? I am going to explain you.

First, there is one big issue: You can share any app via NFC, and launch any app from the Store via NFC tag that has a launch app record. But you cannot launch any apps from your app – just those that have implemented a custom uri scheme. On the other two big operating systems, sharing between apps is meanwhile a standard feature used by a lot of developers.

Most of the settings pages have one of those uri schemes, for example the Wi-Fi settings page can be launched with this simple line of code:

await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings-wifi:"));

I don’t know if other developers just don’t know about this feature or if they don’t think it is necessary. I talked to a lot of users of my app NFC Toolkit for Windows Phone 8, and all asked me to add the possibility to launch a desired app at the end of my profiles (if you don’t know, my profiles launch programmable sequence of settings pages).

Searching for a solution to satisfy my user, I spent a few days with researching of all possibilities and talking to other developers. Some of them wanted use cases for adding that feature, here are three:

  • Every day I leave for work, I disable Wi-Fi, activate Bluetooth and switch the cellular connection from 2G to 3G/4G. I often use Nokia Music to listen to music while driving to work (about 45 minutes). This is one of the use cases.
  • The second scenario should be also familiar to some of you: I switch off all data connections because otherwise, my phone would ring very often during the night. In the morning, I switch them back on and check for news with a feed reader app. This would fit perfectly into a profile that I save on a NFC tag or launch via secondary tile.
  • Third one: there are a lot of blog reader apps out there. Sure, Windows Phone has social networks built in – but only Facebook (user only), Twitter and LinkedIn. What if I want to share to another network, for example Geeklist? Then I have to copy and paste instead of just hitting the share button.

There are more use cases, but I am leaving you with these three for the moment.

Back to the conversations I had with my users. They want and deserve a great user experience. This blog post is part of my efforts to provide users their deserved user experience.

Sadly, for a handful of developers it is not as easy to gain some attention for this. This is why I am trying to get DVLUP on board. By creating a challenge for this, more developers would join to earn the XP. The winners in this case are the users out there, because this way, their user experience will be improved. I know this should be done by Microsoft. In the meantime, it is up to us developers to improve. That’s why I ask you to vote for my idea case on DVLUP here: http://www.dvlup.com/Feedback?query=custom+uri+scheme+to+all+apps%21# (the first entry in the list is the one to vote).

There is one reason left why you should add a custom uri scheme to your app. This point is for you, the developer reading this article. You have a free possibility to promote your app across other apps. The most important point: it takes only 5 minutes to add a simple launch uri scheme.

Do you already have a custom uri scheme for your app? Great, then add it to this list: URI Association Schemes List – Nokia Developer Wiki. This way, other developers can use them to interact with your app and bring you new users, too.

To close this article, I want to show you how to add a simple custom uri launch scheme. I have done this with my app Mix Play & Share recently (update submitted, will add it to the list above as soon as it certified).

A simple launch uri – the code

First, open your WMAppManifest.xml by right-clicking on it and Open with… =>XML (Text) Editor.

After the </Tokens> Element, add the following code:

<Extensions>
     <Protocol Name="your-custom-uri-scheme-here" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" />
</Extensions>

Save and close the Document.

Add a new class to your project. Add the following code in your class:

    class UriSchemeMapper : UriMapperBase
    {
        private string tempUri;

        public override Uri MapUri(Uri uri)
        {
            tempUri = System.Net.HttpUtility.UrlDecode(uri.ToString());

            // updated code begins here:
            if (tempUri.Contains("your-custom-uri-scheme-here"))
            {
                return new Uri("/MainPage.xaml", UriKind.Relative);
            }
            //updated code ends here
            return uri;
        }
    }

To make your app using this custom uri scheme, you just have to add another line of code after the declaration of your RootFrame in App.xaml.cs:

//Handle custom uri scheme
RootFrame.UriMapper = new UriSchemeMapper();

That’s all, your app now is able to be launched by other apps!

You can also add more advanced custom uri schemes (up to 10 per app), to read more about it, check MSDN: http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206987(v=vs.105).aspx#BKMK_URIassociations

I hope after reading this post, you understand why I think it is important to add a custom uri scheme. With the simple code above, you’re done in 5 minutes.

Update 12/14/2013:

I needed to update the UriMapper class above, because without handling a scheme without parameters we will have no guarantee that the app launches. In my tests it works sometimes and sometimes not, but to make sure your app launches, please handle this case properly.

 

Until then, happy coding!

Posted by msicc in Dev Stories, windev, 9 comments