Defining a Quick Card Target Page

,

When an app is launched from a quick card, a deep-link URI is used to deliver information about the quick card to the app via query string parameters. All deep-link URIs for search extensibility follow the same format and do not include the name of your app page. You must redirect navigation from the quick card to the appropriate page in your app.

The following is an example of a deep-link search URI:

/SearchExtras?PlaceName=Azteca Mexican Restaurants&PlaceAddress=3040 148th Ave NE, Redmond, WA, 98052&Category=Bing_Places_Food_and_Dining

Redirection to a dedicated landing page can be achieved in a couple of ways. The first is by defining a URI Mapping within the app’s App.xaml file, as shown in the following excerpt:

<Application.Resources>
        <nav:UriMapper x:Key="UriMapper"
xmlns:nav="clr-namespace:System.Windows.Navigation;assembly=Microsoft.Phone">
            <nav:UriMapper.UriMappings>
                <nav:UriMapping Uri="/SearchExtras"
                                MappedUri="/SearchLandingView.xaml" />
            </nav:UriMapper.UriMappings>
        </nav:UriMapper>
    </Application.Resources>

In this example, the UriMapper is defined within the Application Resources. To make your app use the custom URI mapper, it must be assigned to the RootFrame’s UriMapper property, as demonstrated in the following excerpt from the App.xaml.cs file:

void InitializePhoneApplication()
{
    ...

    /* Assign the quick card URI-mapper class to the application frame. */
    RootFrame.UriMapper = (UriMapperBase)Resources["UriMapper"];
    ...
}

An alternative approach to configuring the UriMapper is to define the UriMapper within the Application.RootVisual element in the App.xaml. You can see how this is performed in the WPUnleashed.Example project of the WPUnleashed solution, in the MainExamples directory of the downloadable sample code.

Another approach to achieving redirection is by creating a custom URI Mapper class, as shown in Listing 31.3. Using a custom URI mapper gives you more flexibility in being able to redirect to different pages within your app depending, for example, on the Bing search category.

The CustomUriMapper class derives from UriMapperBase and handles all navigation requests. When a request for the /SearchExtras URI arrives, the MapUri method is called, which determines if the request originates from a quick card. A URI is created to handle each particular search category.

LISTING 31.3. CustomUriMapper Class


public class CustomUriMapper : UriMapperBase
{
    const string targetPageName = "SearchLandingView.xaml";

    public override Uri MapUri(Uri uri)
    {
        if (uri == null)
        {
            return null;
        }

        string url = uri.ToString();
        /* Parse the URI when launched from a Bing Search. */
        const string searchExtrasPath = "/SearchExtras";

        if (url.StartsWith(searchExtrasPath))
        {
            string queryString = url.Substring(searchExtrasPath.Length);
            /* Uri.Query is not available for relative URIs,
                * hence the extraction of the query string from the URL. */
            IDictionary<string, string> queryDictionary
                = HttpUtilityAdvanced.ParseQueryString(queryString);

            string category;
            if (queryDictionary.TryGetValue("Category", out category))
            {
                if (category.StartsWith("Bing_Products"))
                {
                    /* Create a new URI for product cards. */
                    return CreateProductCardUri(queryDictionary);
                }

                if (category.StartsWith("Bing_Places"))
                {
                    /* Create a new URI for place cards. */
                    return CreatePlaceCardUri(queryDictionary);
                }

                if (category.StartsWith("Bing_Movies"))
                {
                    /* Create a new URI for movie cards. */
                    return CreateMovieCardUri(queryDictionary);
                }
            }
        }

        /* Return the URI when it is not related to App Connect for Search. */
        return uri;
    }

    Uri CreateProductCardUri(IDictionary<string, string> queryDictionary)
    {
        List<string> keys = new List<string> { "ProductName", "Category" };
        var result = CreateCardUri(queryDictionary, keys);
        return result;
    }

    Uri CreatePlaceCardUri(IDictionary<string, string> queryDictionary)
    {
        List<string> keys = new List<string>
            {
                "PlaceName", "PlaceLatitude", "PlaceLongitude", "PlaceAddress",
                   "Category"
            };
        var result = CreateCardUri(queryDictionary, keys);
        return result;
    }

    Uri CreateMovieCardUri(IDictionary<string, string> queryDictionary)
    {
        List<string> keys = new List<string> { "MovieName", "Category" };
        var result = CreateCardUri(queryDictionary, keys);
        return result;
    }

    Uri CreateCardUri(IDictionary<string, string> queryDictionary, List<string> keys)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append('/');
        sb.Append(targetPageName);
        if (keys.Any())
        {
            sb.Append('?');
        }

        int keyCount = keys.Count;

        for (int i = 0; i < keyCount; i++)
        {
            string key = keys[i];

            string itemValue;
            queryDictionary.TryGetValue(key, out itemValue);
            sb.Append(key);
            sb.Append("=");
            sb.Append(itemValue);

            if (i < keyCount - 1)
            {
                sb.Append("&");
            }
        }

        return new Uri(sb.ToString(), UriKind.Relative);
    }
}


A custom class named HttpUtilityAdvanced is used to parse the URI query string into a dictionary of string key/value pairs. When using the desktop .NET framework, the HttpUtility class contains a method for parsing query strings. Unfortunately, no such method exists for this purpose in the Windows Phone SDK. I have created a class named HttpUtilityAdvanced to fill this gap. It is located in the downloadable sample code in the WPUnleashed project. The ParseQueryString method deconstructs the specified query string and returns a dictionary of the query string key and values. See Listing 31.4.

LISTING 31.4. HttpUtilityAdvanced Class


public class HttpUtilityAdvanced
{
    public static IDictionary<string, string> ParseQueryString(string queryString)
    {
        var parameterDictionary = new Dictionary<string,
                                 string>(StringComparer.InvariantCultureIgnoreCase);

        int startIndex = queryString.IndexOf('?');
        string queryPart;
        if (startIndex > -1)
        {
            queryPart = queryString.Substring(startIndex + 1);
        }
        else
        {
            queryPart = queryString;
        }

        string[] strings = queryPart.Split('&');

        foreach (string queryItem in strings)
        {
            int equalsIndex = queryItem.IndexOf('=');
            if (equalsIndex >= 0)
            {
                string key
                      = HttpUtility.UrlDecode(queryItem.Substring(0, equalsIndex));
                string itemValue
                      = HttpUtility.UrlDecode(queryItem.Substring(equalsIndex + 1));

                parameterDictionary.Add(key, itemValue);
            }
            else
            {
                parameterDictionary.Add(queryItem, null);
            }
        }

        return parameterDictionary;
    }
}


The custom URI mapper can be assigned to the RootFrame’s UriMapper, in the App.xaml.cs file, as shown in the following excerpt:

void InitializePhoneApplication()
{
    ...

    /* Assign the quick card URI-mapper class to the application frame. */
    RootFrame.UriMapper = new CustomUriMapper();
    ...
}

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.120.161