Picture Search Teil 1: Suche mit Bing
Picture Search ist eine Windows Store Sample App. Wie der Name sagt, kann man mit dieser App Bilder suchen – mit Hilfe von Services wie Bing Search (oder zukünftig auch anderen wie Flickr). In diesem Blog wird dieser Artikel-Serie wird diese App Schritt für Schritt aufgebaut – gestartet mit der Server-seitigen Implementierung über Windows-runtime Komponenten bis User Interface mit einer Grid View Control und Search und Share Contracts.
Der erste Teil dieser Serie zeigt die Server-seitige Implementierung mit Hilfe der ASP.NET Web API, das ganze gehostet unter Windows Azure. Dieses Service wird dann im nächsten Teil von einer Windows Store App verwendet.
Erstellen des Services mit der ASP.NET Web API
Gestartet wird mit einer ASP.NET MVC 4 Web Application:
Bei diesem Template gibt es das Web API Project Template:
Dieses Projekt-Template erzeugt eine ValuesController Klasse im Verzeichnis Controller. In der Sample App wird diese Klasse aber nicht verwendet, stattdessen wird ein BingSearchController erstellt:
Der BingSearchController definiert die Get Methode für einen HTTP GET Request. Bei diesem GET Request wird der Suchbegriff im URL Request mitegegeben. Die Methode retourniert eine Liste von PictureInformation Objekten. In der Implementierung wird die SearchManager Klasse genutzt die selbst einen Request zum Bing Service macht.
{
SearchManager mgr = new SearchManager();
IEnumerable<PictureInformation> result = await mgr.SearchImagesAsync(id);
return result;
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, „Courier New“, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Das default routing und die Get Methode in der BingSearchController Klasse bestimmt die URL http://<server>/api/bingsearch/<searchTerm>.
Für die Implementierung ses Controllers werden noch die Klassen SearchManager und PictureInformation benötigt.
Das Data Transfer Objekt
Die Klasse PictureInformation ist ein einfacher Datenhalter mit Title, Url, und ThumbnailUrl.
{
public string Title { get; set; }
public string Url { get; set; }
public string ThumbnailUrl { get; set; }
public string Source { get; set; }
}
Contract für Image Requests
Das Picture Search Service kann unterschiedliche Picture Search Provider verwenden, z.B. Bing und Flickr. Im Buch Professional C# 2012 and .NET 4.5 gibt es Implementierungen von beiden dieser Services. Dieses Sample verwendet nur Bing Search.
Um unterschiedliche Implementierungen einfach zu bewerkstelligen wird das interface IImageRequest definiert. Mit diesem Interface retourniert der Search Provider einen Link zur Suchabfrage. Dieser Link beinhaltet den Suchbegriff. Sowohl Bing als auch Flickr liefern bei der Suche XML zurück. dieser XML Content kann über die Parse Methode des IImageRequest Interfaces in eine Collection von PictureInformation Objekte umgewandelt werden.
{
string SearchTerm { get; set; }
string Url { get; }
IEnumerable<PictureInformation> Parse(string xml);
ICredentials Credentials { get; }
}
Bing Search Request
Die Klasse BingRequest implementiert das Interface IImageRequest – für eine Suche mittels Bing. Um diese Klasse verwendet werden zu können ist es notwendig den Application Identifier einzutragen. Dieser Identifier ist mit einer Registrierung bei der Bing Search API im Windows Azure Marketplace verfügbar: https://datamarket.azure.com/dataset/bing/search. Bis zu 5000 Transaktionen sind im Monat kostenlos.
Die wichtigsten Teile dieser Klasse sind die Url Property und die Parse Methode. Die Url Property liefert den Link zum Bing Service inklusive des Suchbegriffs. Die Parse Methode konvertiert XML in eine Objektliste – mit Hilfe von LINQ to XML.
{
private const string AppId = "Enter your Bing App-id here!";
public BingRequest()
{
Count = 50;
Offset = 0;
}
private string searchTerm;
public string SearchTerm
{
get { return searchTerm; }
set { searchTerm = value; }
}
public string Url
{
get
{
return string.Format("https://api.datamarket.azure.com/Data.ashx/Bing/Search/v1/Image?Query=%27{0}%27&$top={1}&$skip={2}&$format=Atom", SearchTerm, Count, Offset);
}
}
public int Count { get; set; }
public int Offset { get; set; }
public IEnumerable<PictureInformation> Parse(string xml)
{
XElement respXml = XElement.Parse(xml);
XNamespace d = XNamespace.Get("http://schemas.microsoft.com/ado/2007/08/dataservices");
XNamespace m = XNamespace.Get("http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
return (from item in respXml.Descendants(m + "properties")
select new PictureInformation
{
Title = new String(item.Element(d + "Title").Value.Cast<char>().Take(50).ToArray()),
Url = item.Element(d + "MediaUrl").Value,
ThumbnailUrl = item.Element(d + "Thumbnail").Element(d + "MediaUrl").Value,
Source = "Bing"
}).ToList();
}
public ICredentials Credentials
{
get
{
return new NetworkCredential(AppId, AppId);
}
}
}
Aufruf von Bing Search
Vom Web API Controller wird die SearchManager Klasse verwendet. In der SearchImagesAsync Methode erfolgt ein asynchroner GET Request zum Bing Service. Für den Request wird die Klasse HttpClient verwendet, eine neue Klasse mit .NET 4.5. Diese Klasse bietet nur asynchrone Methoden um den aufrufenden Thread nicht zu blockieren.
{
public async Task<IEnumerable<PictureInformation>> SearchImagesAsync(string searchTerm)
{
var request = new BingRequest();
request.SearchTerm = searchTerm;
var client = new HttpClient(
new HttpClientHandler
{
Credentials = request.Credentials
});
HttpResponseMessage response = await client.GetAsync(request.Url);
string resp = await response.Content.ReadAsStringAsync();
IEnumerable<PictureInformation> images = null;
await Task.Run(() =>
{
images = request.Parse(resp);
});
return images;
}
}
Statt der Methode GetAsync und folgend ReadAsStringAsync kann auch die einfachere Methode GetStringAsync verwendet werden.
Aufruf vom Search Service
Mit der Implementierung vom ASP.NET Web API Service kann die Bildersuche bereits gestartet werden. Simple HTTP GET Requests können einfach mit Hilfe eines Web Browsers gemacht werden. Der Request /api/bingsearch/Ferrari">http://<server>/api/bingsearch/Ferrari liefert beim IE JSDON Daten, z.B. diese Collection die durch die PictureInformation Klasse definiert wurde:
[{"Title":"Voici une belle photo de Ferrari de qualité",
"Url":"http://images-et-photos.com/files/ferrari1.jpg",
"ThumbnailUrl":"http://ts1.mm.bing.net/th?id=H.4902048858114356&pid=15.1",
"Source":"Bing"},
{"Title":"Name: ferrari pictures.jpgViews: 110204Size:337.4",
"Url":"http://www.whitegadget.com/attachments/pc-wallpapers/75212d1315377041-ferrari-ferrari-pictures.jpg",
"ThumbnailUrl":"http://ts2.mm.bing.net/th?id=I.4894034425284685&pid=15.1&W=160&H=120",
"Source":"Bing"},
{"Title":"Ferrari Enzo Ferrari Photos:",
"Url":"http://world-viewer.com/data_images/ferrari-enzo-ferrari/ferrari-enzo-ferrari-04.jpg",
"ThumbnailUrl":"http://ts3.mm.bing.net/th?id=I.4935837306587618&pid=15.1&W=160&H=120",
"Source":"Bing"},
Im nächsten Artikel dieser Serie erstelle ich eine Windows Runtime Komponente die dieses Web Service aufruft.
Christian
Weitere Informationen für die Web API und Windows Store Apps in meinen Workshops und meinem Buch Professional C# 2012 and .NET 4.5.
Trackbacks & Pingbacks