In Part 2, I wanted to add support for communicating with Live Search APIs. These APIs are allowed to be called cross domain. The way I made sure is http://soap.search.live.com/crossdomain.xml. Here is the link to documentation of this APIs.
Getting basic service integrated is very straight forward, thanks to VS integration for web services. Right Click on References and clicked on “Add Service Reference”. It adds all the necessary client wrappers that let you call web service like any other objects in your app. I set the namespace to be SearchService so all these wrapper classes are available in Search.SearchService, Search being the root namespace for the application.
Code for talking to webservice looks something like this….
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Windows;
5: using System.Windows.Controls;
6: using System.Windows.Documents;
7: using System.Windows.Input;
8: using System.Windows.Media;
9: using System.Windows.Media.Animation;
10: using System.Windows.Shapes;
11: using Search.SearchService;
12: using System.Collections.ObjectModel;
13: using System.ServiceModel;
14: using System.Net;
15: using System.Xml;
16: using System.IO;
17:
18: namespace Search
19: {
20: public class SearchResultCollection : ObservableCollection<SearchService.Result>
21: {
22: }
23:
24: public partial class Page : UserControl
25: {
26: private Storyboard _progress;
27: private SearchResultCollection _imagesearchresultcollection;
28: Result[] _imageresults;
29: Boolean _searchcompleted;
30:
31:
32: public Page()
33: {
34: InitializeComponent();
35: _progress = LayoutRoot.FindName("SearchProgressAnimation") as Storyboard;
36: _progress.Completed += new EventHandler(_progress_Completed);
37: }
38:
39: void _progress_Completed(object sender, EventArgs e)
40: {
41: if (_searchcompleted == true)
42: {
43: _progress.Stop();
44: }
45: else
46: {
47: _progress.Begin();
48: }
49: }
50:
51: private void Button_Click(object sender, RoutedEventArgs e)
52: {
53: _searchcompleted = false;
54: _progress.Begin();
55: GetLiveData();
56: }
57:
58:
59:
60: private void GetLiveData()
61: {
62: try
63: {
64: //Initialize web service
65: string searchquery = txtSearch.Text;
66: BasicHttpBinding binding = new BasicHttpBinding();
67: EndpointAddress address = new EndpointAddress("http://soap.search.msn.com/webservices.asmx");
68: MSNSearchPortTypeClient searchservice = new MSNSearchPortTypeClient(binding, address);
69: SearchRequest searchrequest = new SearchRequest();
70: SourceRequest[] sr = new SourceRequest[3];
71:
72: sr[0] = new SourceRequest();
73: sr[0].Source = SourceType.Image;
74: sr[0].ResultFields = ResultFieldMask.Url | ResultFieldMask.Title | ResultFieldMask.Description | ResultFieldMask.Image;
75: sr[0].Count = 50;
76:
77: searchrequest.Query = searchquery;
78: searchrequest.Requests = sr;
79: searchrequest.AppID = "Enter your key here";
80: searchrequest.CultureInfo = "en-US";
81: searchservice.SearchCompleted += new EventHandler<Search.SearchService.SearchCompletedEventArgs>(searchservice_SearchCompleted);
82: searchservice.SearchAsync(searchrequest);
83: }
84: catch (WebException webx)
85: {
86: txtSearch.Text = webx.ToString();
87: _searchcompleted = true;
88: }
89: }
90:
91: void searchservice_SearchCompleted(object sender, Search.SearchService.SearchCompletedEventArgs e)
92: {
93: if (e.Error != null)
94: txtSearch.Text = e.Error.Message;
95: else
96: {
97: _imagesearchresultcollection = new SearchResultCollection();
98: _imageresults = e.Result.Responses[0].Results;
99: for (int counter = 0; counter < _imageresults.Length; counter++)
100: {
101: if (_imageresults[counter].Image.ImageURL.Contains("jpg") || _imageresults[counter].Image.ImageURL.Contains("png"))
102: _imagesearchresultcollection.Add(_imageresults[counter]);
103: }
104: }
105: _searchcompleted = true;
106: }
107: }
108: }
To add the progress UI, I was thinking of writing a control but then I changed my mind and I thought it would look much cooler if the brush that is background for the page can be animated (it looks like a focus so when it animates, it looks sort of like somebody is looking with a flashlight.
I have used Blend to do everything here.
<Storyboard x:Name="SearchProgressAnimation" RepeatBehavior="1x"> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(Panel.Background).
(Brush.RelativeTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"
BeginTime="00:00:00"> <SplineDoubleKeyFrame KeyTime="00:00:01" Value="90.145"/> <SplineDoubleKeyFrame KeyTime="00:00:02" Value="180.143"/> <SplineDoubleKeyFrame KeyTime="00:00:03" Value="270.128"/> <SplineDoubleKeyFrame KeyTime="00:00:04" Value="359.946"/> </DoubleAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Shape.Fill).
(LinearGradientBrush.StartPoint)"
BeginTime="00:00:00"> <SplinePointKeyFrame KeyTime="00:00:01" Value="0.716000020503998,0.439000010490417"/> <SplinePointKeyFrame KeyTime="00:00:02" Value="0.382999986410141,0.684000015258789"/> <SplinePointKeyFrame KeyTime="00:00:03" Value="0.0759999975562096,0.231000006198883"/> <SplinePointKeyFrame KeyTime="00:00:04" Value="0.726000010967255,0.395999997854233"/> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Shape.Fill).
(LinearGradientBrush.EndPoint)"
BeginTime="00:00:00"> <SplinePointKeyFrame KeyTime="00:00:01" Value="0.0769999995827675,0.228000000119209"/> <SplinePointKeyFrame KeyTime="00:00:02" Value="0.409999996423721,-0.017000000923872"/> <SplinePointKeyFrame KeyTime="00:00:03" Value="0.717000007629395,0.435999989509583"/> <SplinePointKeyFrame KeyTime="00:00:04" Value="0.0670000016689301,0.270999997854233"/> </PointAnimationUsingKeyFrames> </Storyboard>
Only thing I do to run this storyboard is in Button Click event, before I make a call to webservice, I start the storyboard and when call returns (or throws exception), I stop the animation. One problem I hit was I needed to run the animation atleast once otherwise when service call returns, it looks really choppy. I am not sure if there is a better way to do this but the way I ended up doing it was I kept the animation 1x and then I keep on running it till service API returns.
1: void _progress_Completed(object sender, EventArgs e)
2: {
3: if (_searchcompleted == true)
4: {
5: _progress.Stop();
6: }
7: else
8: {
9: _progress.Begin();
10: }
11: }
Here is the link to working project.
Pingback: Chris Love's Official Blog - Professional ASP.NET : Links of the Week
Pingback: Wrapper Counters and the rest of the world » Blog Archive » What others have been saying about wrapper counter
Pingback: Wrapper Counters and the rest of the world » Blog Archive » Quick Roundup
Pingback: Wrapper Counters and the rest of the world » Blog Archive » Quick scan of the net - wrapper counter
Pingback: Wrapper Counters and the rest of the world » Blog Archive » ‘wrapper counter’ on the web
Hey there.. thanks for this, I was just trying to write something similar. However, I get the same thing with your code as mine… I’m everything runs, but not results come back in the e.results… any ideas?
This design is spectacular! You definitely know how to
keep a reader entertained. Between your wit and your videos, I was almost moved to
start my own blog (well, almost…HaHa!) Fantastic job.
I really loved what you had to say, and more than that, how you presented it.
Too cool!
This post is truly a pleasant one it helps new the web people, who are wishing for blogging.