本文将带领大家使用SharePoint Designer创建基于WCF服务的外部内容类型。
步骤
1、检查你的WCF服务已经宿主并可用。本文将使用封装AdventureWorks2000数据库的Contact表得到的WCF服务。 首先打开你的IIS管理器,导航到宿主你的WCF服务的网站,确保其正常运行。
2、打开IE浏览器并导航到该服务的.svc文件。 你应该能够看到类型如下的页面,表示该WCF服务正在工作。
WCF的检查工作结束。现在我们开始基于该WCF在SPD中创建我们的外部内容类型。
3、打开SharePoint Designer 2010并点击“打开网站”大按钮。
4、输入你的SharePoint站点URL地址并回车。SPD将会连接到该站点并获取信息。
5、从左侧导航窗格中点击外部内容类型。可以看到顶部的功能区也进行了相应的改变,反映当前的工作状态。
6、在功能区中,点击新建中的外部内容类型。
7、打开的摘要页面中,可以编辑和管理外部内容类型。
这里有一些类似超链接的标签,点击可设置值 。最上面的两个是名称和显示名称,设置其值为:
名称:联系人
显示名称:联系人
接下来,我们选择一个外部数据源来进行连接。点击链接“点击此处发现数据源并定义操作”。
8、进入操作设计器视图。点击添加连接按钮。
9、选择数据源类型为 “WCF服务”
10、WCF连接窗口打开。这里我们需要填写有关我们WCF服务的一些连接信息,以便SharePoint Designer进行连接。根据上面我们检查到的WCF宿主情况,这里我填入:
服务元数据URL:http://contact/service.svc?WSDL
服务终结点URL:http://contact/service.svc
11、配置好WCF连接后,点击确定。这时将尝试连接到你的WCF服务。如果一切正常,你会看到所有可用的Web方法。
12、我们需要创建相应的BCS操作。本例中,我们将使用GetContactFinder作为“读取列表”操作,使用GetContactSpecificFinder作为“读取项”操作。
13、右击 GetContactFinder并选择“新建读取列表”操作。
14、在弹出的向导中,“返回参数” 一节中会提示一个错误信息,“应至少指定一个标识符”。选择ContactID并勾选“映射到标识符”。在标识符下拉框中选中ContactID。点击完成,创建好了读取列表操作。
15、右击GetContactSpecificFinder并选择新建“读取项”操作。
16、在操作属性窗口中,输入参数一节我们需要映射该输入参数到标识符。选中contactid并在右侧的面板中勾上“映射到标识符”,并在标识符下拉框中选中ContactID。点击下一步。
17、在返回参数一节,也包含一条错误提示指出需要映射标识符。为了修复该错误,在左侧选择ContactID,右侧勾选“映射到标识符” 并在标识符下拉框中选中ContactID。点击完成按钮。
18、现在,右侧的ECT操作中已经有两个操作了。你也可以根据需要添加其他操作,如创建,更新等等。
19、按“Ctrl+S”键保存该ECT。
20、我们可以打开SharePoint站点,创建外部列表绑到我们的外部内容类型。
21、它会调用“读取列表”操作 (WCF中的Finder方法)来获取数据。
22、选中任意一条数据,然后点击“项目”功能区,其中的“查看项目”操作会调用WCF的Specific Finder方法,在弹出框中显示选中的项。
附上本例中涉及的WCF相关代码,以备参考。
1、IAdventureWorks2000WCFService.cs
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
[ServiceContract]
public interface IAdventureWorks2000WCFService
{
[OperationContract]
List < Contact > GetContactFinder();
[OperationContract]
Contact GetContactSpecificFinder(Int32 contactid);
[OperationContract]
List < Int32 > GetContactIdEnumerator();
}
[DataContract]
public class Contact
{
[DataMember]
public Int32 ContactID
{
get ;
set ;
}
[DataMember]
public String Salutation
{
get ;
set ;
}
[DataMember]
public String FirstName
{
get ;
set ;
}
[DataMember]
public String MiddleName
{
get ;
set ;
}
[DataMember]
public String LastName
{
get ;
set ;
}
[DataMember]
public Boolean NameStyle
{
get ;
set ;
}
[DataMember]
public String Phone
{
get ;
set ;
}
[DataMember]
public String Suffix
{
get ;
set ;
}
[DataMember]
public String EmailAddress
{
get ;
set ;
}
[DataMember]
public String Password
{
get ;
set ;
}
[DataMember]
public Int32 EmailPromotion
{
get ;
set ;
}
[DataMember]
public DateTime ModifiedDate
{
get ;
set ;
}
[DataMember]
public Guid rowguid
{
get ;
set ;
}
[DataMember]
public String AdditionalContactInfo
{
get ;
set ;
}
}
2、 AdventureWorks2000WCFService.cs
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
public class AdventureWorks2000WCFService : IAdventureWorks2000WCFService
{
private const string connectionString = @" Persist Security Info=False;User ID=xxx;Password=xxx;Server=localhost;Connect Timeout=30;Initial Catalog=AdventureWorks2000 " ;
AdventureWorks2000WCFService()
{
}
public List < Contact > GetContactFinder()
{
List < Contact > contactList = new List < Contact > ();
const string sqlQuery = @" Select * From dbo.[Contact] " ;
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
SqlCommand comm = new SqlCommand(sqlQuery, sqlConnection);
DataSet dataSet = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter(comm);
adapter.Fill(dataSet, @" dbo.[Contact] " );
foreach (DataRow dr in dataSet.Tables[ 0 ].Rows)
{
Contact contact = new Contact();
contact.ContactID = dr[ " ContactID " ] is DBNull ? 0 : (Int32)dr[ " ContactID " ];
contact.Salutation = dr[ " Salutation " ] is DBNull ? string .Empty : (String)dr[ " Salutation " ];
contact.FirstName = dr[ " FirstName " ] is DBNull ? string .Empty : (String)dr[ " FirstName " ];
contact.MiddleName = dr[ " MiddleName " ] is DBNull ? string .Empty : (String)dr[ " MiddleName " ];
contact.LastName = dr[ " LastName " ] is DBNull ? string .Empty : (String)dr[ " LastName " ];
contact.NameStyle = dr[ " NameStyle " ] is DBNull ? false : (Boolean)dr[ " NameStyle " ];
contact.Phone = dr[ " Phone " ] is DBNull ? string .Empty : (String)dr[ " Phone " ];
contact.Suffix = dr[ " Suffix " ] is DBNull ? string .Empty : (String)dr[ " Suffix " ];
contact.EmailAddress = dr[ " EmailAddress " ] is DBNull ? string .Empty : (String)dr[ " EmailAddress " ];
contact.Password = dr[ " Password " ] is DBNull ? string .Empty : (String)dr[ " Password " ];
contact.EmailPromotion = dr[ " EmailPromotion " ] is DBNull ? 0 : (Int32)dr[ " EmailPromotion " ];
contact.ModifiedDate = dr[ " ModifiedDate " ] is DBNull ? DateTime.MinValue : (DateTime)dr[ " ModifiedDate " ];
contact.rowguid = dr[ " rowguid " ] is DBNull ? Guid.Empty : (Guid)dr[ " rowguid " ];
contact.AdditionalContactInfo = dr[ " AdditionalContactInfo " ] is DBNull ? string .Empty : (String)dr[ " AdditionalContactInfo " ];
contactList.Add(contact);
}
}
return contactList;
}
public Contact GetContactSpecificFinder(Int32 contactid)
{
Contact contact = new Contact();
const string sqlQuery = @" Select * From dbo.[Contact] Where (ContactID=@ContactID) " ;
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
SqlCommand comm = new SqlCommand(sqlQuery, sqlConnection);
comm.Parameters.AddWithValue( " @ContactID " , contactid);
DataSet dataSet = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter(comm);
adapter.Fill(dataSet, @" dbo.[Contact] " );
if (dataSet.Tables[ 0 ].Rows.Count > 0 )
{
DataRow dr = dataSet.Tables[ 0 ].Rows[ 0 ];
contact.ContactID = dr[ " ContactID " ] is DBNull ? 0 : (Int32)dr[ " ContactID " ];
contact.Salutation = dr[ " Salutation " ] is DBNull ? string .Empty : (String)dr[ " Salutation " ];
contact.FirstName = dr[ " FirstName " ] is DBNull ? string .Empty : (String)dr[ " FirstName " ];
contact.MiddleName = dr[ " MiddleName " ] is DBNull ? string .Empty : (String)dr[ " MiddleName " ];
contact.LastName = dr[ " LastName " ] is DBNull ? string .Empty : (String)dr[ " LastName " ];
contact.NameStyle = dr[ " NameStyle " ] is DBNull ? false : (Boolean)dr[ " NameStyle " ];
contact.Phone = dr[ " Phone " ] is DBNull ? string .Empty : (String)dr[ " Phone " ];
contact.Suffix = dr[ " Suffix " ] is DBNull ? string .Empty : (String)dr[ " Suffix " ];
contact.EmailAddress = dr[ " EmailAddress " ] is DBNull ? string .Empty : (String)dr[ " EmailAddress " ];
contact.Password = dr[ " Password " ] is DBNull ? string .Empty : (String)dr[ " Password " ];
contact.EmailPromotion = dr[ " EmailPromotion " ] is DBNull ? 0 : (Int32)dr[ " EmailPromotion " ];
contact.ModifiedDate = dr[ " ModifiedDate " ] is DBNull ? DateTime.MinValue : (DateTime)dr[ " ModifiedDate " ];
contact.rowguid = dr[ " rowguid " ] is DBNull ? Guid.Empty : (Guid)dr[ " rowguid " ];
contact.AdditionalContactInfo = dr[ " AdditionalContactInfo " ] is DBNull ? string .Empty : (String)dr[ " AdditionalContactInfo " ];
}
}
return contact;
}
public List < Int32 > GetContactIdEnumerator()
{
List < Int32 > ids = new List < Int32 > ();
const string sqlQuery = @" Select ContactID from dbo.[Contact] " ;
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
SqlCommand comm = new SqlCommand(sqlQuery, sqlConnection);
DataSet dataSet = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter(comm);
adapter.Fill(dataSet, @" dbo.[Contact] " );
foreach (DataRow dr in dataSet.Tables[ 0 ].Rows)
{
ids.Add(dr[ " ContactID " ] is DBNull ? 0 : (Int32)dr[ " ContactID " ]);
}
}
return ids;
}
}
3、Service.svc
4、Web.config
<!--
Note: As an alternative to hand editing this file you can use the
web admin tool to configure settings for your application. Use
the Website->Asp.Net Configuration option in Visual Studio.
A full list of settings and comments can be found in
machine.config.comments usually located in
\Windows\Microsoft.Net\Framework\v2.x\Config
-->
< configuration >
< configSections >
< sectionGroup name ="system.web.extensions" type ="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" >
< sectionGroup name ="scripting" type ="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" >
< section name ="scriptResourceHandler" type ="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission ="false" allowDefinition ="MachineToApplication" />
< sectionGroup name ="webServices" type ="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" >
< section name ="jsonSerialization" type ="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission ="false" allowDefinition ="Everywhere" />
< section name ="profileService" type ="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission ="false" allowDefinition ="MachineToApplication" />
< section name ="authenticationService" type ="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission ="false" allowDefinition ="MachineToApplication" />
< section name ="roleService" type ="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission ="false" allowDefinition ="MachineToApplication" />
</ sectionGroup >
</ sectionGroup >
</ sectionGroup >
</ configSections >
< appSettings />
< connectionStrings />
< system.web >
<!--
Set compilation debug="true" to insert debugging
symbols into the compiled page. Because this
affects performance, set this value to true only
during development.
-->
< compilation debug ="true" >
< assemblies >
< add assembly ="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
< add assembly ="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
< add assembly ="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
< add assembly ="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
</ assemblies >
</ compilation >
<!--
The <authentication> section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
< authentication mode ="Windows" />
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
< pages >
< controls >
< add tagPrefix ="asp" namespace ="System.Web.UI" assembly ="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</ controls >
</ pages >
< httpHandlers >
< remove verb ="*" path ="*.asmx" />
< add verb ="*" path ="*.asmx" validate ="false" type ="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
< add verb ="*" path ="*_AppService.axd" validate ="false" type ="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
< add verb ="GET,HEAD" path ="ScriptResource.axd" type ="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate ="false" />
</ httpHandlers >
< httpModules >
< add name ="ScriptModule" type ="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</ httpModules >
</ system.web >
< system.codedom >
< compilers >
< compiler language ="c#;cs;csharp" extension =".cs" warningLevel ="4" type ="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
< providerOption name ="CompilerVersion" value ="v3.5" />
< providerOption name ="WarnAsError" value ="false" />
</ compiler >
< compiler language ="vb;vbs;visualbasic;vbscript" extension =".vb" warningLevel ="4" type ="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
< providerOption name ="CompilerVersion" value ="v3.5" />
< providerOption name ="OptionInfer" value ="true" />
< providerOption name ="WarnAsError" value ="false" />
</ compiler >
</ compilers >
</ system.codedom >
< system.web.extensions >
< scripting >
< webServices >
<!--
Uncomment this section to enable the authentication service. Include
requireSSL="true" if appropriate.
<authenticationService enabled="true" requireSSL = "true|false"/>
-->
<!--
Uncomment these lines to enable the profile service, and to choose the
profile properties that can be retrieved and modified in ASP.NET AJAX
applications.
<profileService enabled="true"
readAccessProperties="propertyname1,propertyname2"
writeAccessProperties="propertyname1,propertyname2" />
-->
<!--
Uncomment this section to enable the role service.
<roleService enabled="true"/>
-->
</ webServices >
<!--
<scriptResourceHandler enableCompression="true" enableCaching="true" />
-->
</ scripting >
</ system.web.extensions >
<!--
The system.webServer section is required for running ASP.NET AJAX under Internet
Information Services 7.0. It is not necessary for previous version of IIS.
-->
< system.webServer >
< validation validateIntegratedModeConfiguration ="false" />
< modules >
< add name ="ScriptModule" preCondition ="integratedMode" type ="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</ modules >
< handlers >
< remove name ="WebServiceHandlerFactory-Integrated" />
< add name ="ScriptHandlerFactory" verb ="*" path ="*.asmx" preCondition ="integratedMode" type ="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
< add name ="ScriptHandlerFactoryAppServices" verb ="*" path ="*_AppService.axd" preCondition ="integratedMode" type ="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
< add name ="ScriptResource" preCondition ="integratedMode" verb ="GET,HEAD" path ="ScriptResource.axd" type ="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</ handlers >
< directoryBrowse enabled ="true" />
</ system.webServer >
< system.serviceModel >
< services >
< service name ="AdventureWorks2000WCFService" behaviorConfiguration ="ServiceBehavior" >
<!-- Service Endpoints -->
< endpoint address ="" binding ="basicHttpBinding" contract ="IAdventureWorks2000WCFService" >
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
< identity >
< dns value ="contact" />
</ identity >
</ endpoint >
< endpoint address ="mex" binding ="mexHttpBinding" contract ="IMetadataExchange" />
</ service >
</ services >
< behaviors >
< serviceBehaviors >
< behavior name ="ServiceBehavior" >
< dataContractSerializer maxItemsInObjectGraph ="2147483647" />
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
< serviceMetadata httpGetEnabled ="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
< serviceDebug includeExceptionDetailInFaults ="false" />
</ behavior >
</ serviceBehaviors >
</ behaviors >
</ system.serviceModel >
</ configuration >
参考资料
spd external content type from wcf
Large List Throttling for External Lists in SharePoint 2010
BCS PowerShell: Introduction and Throttle Management