Create a Custom Entity Object
One of the things you may notice when reviewing the
properties of the WebResult External Content Type in SharePoint
Designer is that no fields are defined. Of course, there is a perfectly
reasonable explanation for this. If you look back at the return types
for the ReadLst and ReadItem methods, you’ll see that they return values of type IEnumerable<string> and string,
respectively. While this is a valid configuration, SharePoint Designer
can’t break down a single string into multiple fields; therefore, no
fields are shown.
This is where the Entity object comes into play. An
Entity object, as you’ll remember, defines an individual row of data;
it stores individual field data as properties. To show individual
fields in SharePoint, we need to create an appropriate object.
We added a service reference
to allow us to communicate with the Bing service. By examining the
details of the service contract, we can determine what fields are
returned from the service. From the Bing Web Service definition
Language (WSDL), we see that the Search method returns an array of WebResult elements:
<xsd:complexType name="WebResult">
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="1" name="Title" type="xsd:string" />
<xsd:element minOccurs="0" maxOccurs="1" name="Description" type="xsd:string" />
<xsd:element minOccurs="0" maxOccurs="1" name="Url" type="xsd:string" />
<xsd:element minOccurs="0" maxOccurs="1" name="CacheUrl" type="xsd:string" />
<xsd:element minOccurs="0" maxOccurs="1" name="DisplayUrl" type="xsd:string" />
<xsd:element minOccurs="0" maxOccurs="1" name="DateTime" type="xsd:string" />
<xsd:element minOccurs="0" maxOccurs="1"
name="SearchTags" type="tns:ArrayOfWebSearchTag" />
<xsd:element minOccurs="0" maxOccurs="1"
name="DeepLinks" type="tns:ArrayOfDeepLink" />
</xsd:sequence>
</xsd:complexType>
By creating an object with a property for each of
these elements, we’ll be able to pass the results back to our client
application without any loss of data. However, rather than create a new
entity class from scratch, we can simply hook up our metadata to the Microsoft.Bing.WebResult
object that was created automatically when we added the service
reference. This eliminates the unnecessary step of reading the data
from the proxy class into a custom entity class before passing it back
to the client.
Tip
Although we could jump straight in and change the return types of our ReadList and ReadItem
methods, it’s always a good idea to make changes to the metadata first,
since these changes are automatically cascaded to the Entity Service.
Following this procedure helps to eliminate mismatches in data types
since the assembly won’t build if a type copied from the metadata model
into the Entity Service code isn’t valid.
Open
the BdcModel1.bdcm model to display the Entity viewer. Since we want to
change the data type for the return parameter of the ReadItem and ReadList methods, start by expanding the ReadItem
method in the BDC Explorer pane. Select the WebResult Type Descriptor,
and then in the Properties pane, change the Type Name to BingConnectivity.Microsoft.Bing.WebResult, BdcModel1.
Repeat this process for the ReadList method, except change the Type Name for the WebResultList Type Descriptor to System.Collections.Generic .IEnumerable`1[[BingConnectivity.Microsoft.Bing.WebResult, BdcModel1]] and the Type Name for Type Descriptor WebResult to BingConnectivity.Microsoft .Bing.WebResult, BdcModel1.
Save
the changes to the model, and then return to the WebResultService
class. You’ll notice that the method signatures have been updated
accordingly.
As
a result of these updates, our project no longer builds, because our
code returns items of the wrong type. To fix this, update the ReadList method as follows:
public static IEnumerable<WebResult> ReadList(string query)
{
//We can't perform a web search with no query
if (!string.IsNullOrEmpty(query))
{
//Get an instance of the Bing proxy class
BingPortTypeClient client;
SearchRequest request = GetRequestProxy(out client);
//Setup the request parameters
request.Query = query;
try
{
//Execute the search
SearchResponse response = client.Search(request);
return response.Web.Results;
}
catch(System.Exception)
{
return null;
}
}
else
{
return null;
}
}
To resolve the errors in the ReadItem method, update the code as follows:
public static WebResult ReadItem(string itemUrl)
{
if (!string.IsNullOrEmpty(itemUrl))
{
BingPortTypeClient client;
SearchRequest request = GetRequestProxy(out client);
request.Query = itemUrl;
SearchResponse response = client.Search(request);
//Since urls are globally unique this query will only return one result
return response.Web.Results.Single();
}
else
{
return null;
}
}
Our project will now build correctly.