zoukankan      html  css  js  c++  java
  • SharePoint2010 Custom Service

    Create Custom Service Class

    Service类用来定义这个自定义“Service”,也是各种功能的入口点。它继承SPIisWebService,并实现IServiceAdministration(以接入到管理系统中)。

    [Guid("E828358E-E24C-4D78-BE87-C69D458766F4")]

    public class KaneboyService : SPIisWebService, IServiceAdministration

    Service类通常实现二个构造函数:

    • 默认构造函数
    • 一个参数为SPFarm对象的构造函数

    public KaneboyService() { }

    public KaneboyService(SPFarm farm) : base(farm) { }

    IServiceAdministration的方法:

    • CreateApplication():创建一个SPServiceApplication对象。只有在通过运行psconfig.exe或farm configuration wizard创建Service Application时才会调用它(所以对于自定义SPService,它通常不会有机会被调用)。
    • CreateProxy():创建一个SPServiceApplicationProxy对象。与CreateApplication()类似。
    • GetApplicationTypeDescription():返回对此Service的描述信息。
    • GetApplicationTypes():返回Service Application的类型。
    • GetCreateApplicationLink():如果希望可以在管理中心的“管理服务应用程序”中新建此Service Application实例,那么需要实现此方法并返回新建Service Application页面的URL。

    Create Custom Service Instance Class

    Service Instance用来描述运行在每个SPServer上的Service实例。它继承SPIisWebServiceInstance。

    public class KaneboyServiceInstance : SPIisWebServiceInstance

    Service Instance类的构造函数:

    • 默认构造函数
    • 参数如下的构造函数:
      • 一个SPServer对象,表示运行此Service实例的Server
      • 所对应的SPIisWebService对象

    public KaneboyServiceInstance() : base() { }

    public KaneboyServiceInstance(SPServer server, SPIisWebService service) : base(server, service) { }

    Service Instance类需要实现的方法:

    • TypeName属性:描述此Service Instance的名称,显示在管理UI。

    Create Custom Service Application Class

    Service Application类是对Service Application的实现。它继承SPIisWebServiceApplication,并通常实现Service Contract接口。

    [IisWebServiceApplicationBackupBehavior]

    [ServiceBehavior(

            InstanceContextMode = InstanceContextMode.PerSession,

            ConcurrencyMode = ConcurrencyMode.Multiple,

            IncludeExceptionDetailInFaults = true)]

    [Guid("933A11F0-7265-4694-97C0-FE04BFB370A5")]

    public class KaneboyServiceApplication : SPIisWebServiceApplication, IKaneboyServiceContract

    Service Application类的构造函数:

    • 默认构造函数
    • 带下列参数的构造函数:
      • Service Application名称
      • 所对应的SPIisWebService对象
      • 所使用的SPIisWebServiceApplicationPool对象

    public KaneboyServiceApplication() : base() { }

    private KaneboyServiceApplication(String name, KaneboyService service, SPIisWebServiceApplicationPool appPool) : base(name, service, appPool) { }

    Service Application需要告诉系统,如何连接到WCF Service,所以它需要实现:

    • InstallPath属性:返回.svc所在的目录。
    • VirtualPath属性:返回.svc文件的名称。

    如果在Provision这个Service Application的时候,还需要Provision数据库或其他资源,可以重载Provision()和Unprovision()方法。

    创建(并Provision)一个Service Application不能直接使用它的构造函数,而是需要使用如下步骤:

    • 创建Service Application至少需要用到如下信息:
      • Service Application名称
      • 它所对应的SPService对象
      • 它所使用的SPIisWebServiceApplicationPool对象
      • 通过SPService.Applications.GetValue(),确定这个Service Application是否有其他实例存在。
      • 使用它的构造函数,新建一个实例对象。
      • 调用SPServiceApplication.Update()保存新建的实例。
      • 调用SPServiceApplication.AddServiceEndpoint()为Service Application新建WCF Endpoint。

    serviceApp.AddServiceEndpoint("http", SPIisWebServiceBindingType.Http);

    serviceApp.AddServiceEndpoint("https", SPIisWebServiceBindingType.Https, "secure");

    • 调用SPServiceApplication.Provision()以Provision它。

    创建并Provision 自定义Service Application的方法,可以放到Service Application类中,以static method提供。管理员可以使用管理中心UI(位于”ADMIN”中的自定义.aspx,路径由IServiceAdministration.GetCreateApplicationLink()指定)或自定义powershell cmdlets来完成这个操作,所以在管理中心UI或自定义cmdlets中,需要调用这个static method。

    WCF Artifacts

    首先,需要一个自定义Host Factory类,继承自ServiceHostFactory。

    public class KaneboyServiceHostFactory : ServiceHostFactory

    它重载CreateServiceHost()方法,创建并返回一个ServiceHost对象。

    public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)

    {

    ServiceHost serviceHost = new ServiceHost(typeof(KaneboyServiceApplication), baseAddresses);

    serviceHost.Configure(SPServiceAuthenticationMode.Claims);

    return serviceHost;

    }

    在”WebServices”这个mapped folder下面,需要放置自定义Service Application的.svc文件和定义WCF channel的web.config。.svc只需要通过标签告知Service和Factory类即可。

    <%@ServiceHost Language="C#" Debug="true"

                   Service="KaneboyServiceApp1.KaneboyServiceApplication, $SharePoint.Project.AssemblyFullName$"

                   Factory="KaneboyServiceApp1.KaneboyServiceHostFactory, $SharePoint.Project.AssemblyFullName$" %>

    web.config里面需要定义Service Application将使用的channel。

    <configuration>

      <system.serviceModel>

        <services>

          <service name="KaneboyServiceApp1.KaneboyServiceApplication">

            <endpoint

              address=""

              contract="KaneboyServiceApp1.IKaneboyServiceContract"

              binding="customBinding"

              bindingConfiguration="CustomServiceHttpBinding" />

            <endpoint

              address="secure"

              contract="KaneboyServiceApp1.IKaneboyServiceContract"

              binding="customBinding"

              bindingConfiguration="CustomServiceHttpsBinding" />

           </service>

        </services>

        <bindings>

          <customBinding>

            …

          </customBinding>

        </bindings>

      </system.serviceModel>

      <system.webServer>

        <security>

          …

        </security>

      </system.webServer>

    </configuration>

    Register Service on Farm

    将Service注册到Farm里面,需要创建Service和Service Instance对象,并将它们Persist到Config DB中(通过调用Update())。注册可以通过一个Farm Feature的activate事件来实现。在新建Service和Service Instance对象之前,可以通过调用SPFarm.Services.GetValue()来确认是否Farm中已经注册了此服务。在Farm Feature的deactivate事件中,可以将相关的Service和Service Instance删除。

    Create and Provision Service Application

    新建Service Application的实例,可以使用管理中心UI(“管理服务应用程序”)或自定义powershell cmdlets来实现。如果是通过管理中心UI,可以在“ADMIN”中新建一个.aspx,并将其路径在Service类中通过IServiceAdministration.GetCreateApplicationLink()告知系统。

    无论哪种方法,最关键的是,如何将Service Application所使用的SPIisWebServiceApplicationPool对象传递给新建Service Application的代码。如果是使用.aspx,可以使用” ~/_admin/IisWebServiceApplicationPoolSection.ascx”控件,然后通过IisWebServiceApplicationPoolSection.GetOrCreateApplicationPool()得到用户选择的App Pool。如果是使用cmdlets,那么就通过SPIisWebServiceApplicationPoolPipeBind类来得到App Pool信息。(Check MSDN to get detail information.)

    ------------------ “Server”(App Server)与”Client”(WFE)的分割线 ----------------------

    WCF Artifacts

    在”WebClients”这个mapped folder下面,将一个”client.config”文件放置到一个自定义目录中,此文件中包含了告知Service Application Proxy通过哪个channel连接到Service Application的配置信息。

    <configuration>

      <system.serviceModel>

        <client>

          <endpoint

            name="http"

            contract="KaneboyServiceApp1.IKaneboyServiceContract"

            binding="customBinding"

            bindingConfiguration="CustomServiceHttpBinding" />

          <endpoint

            name="https"

            contract="KaneboyServiceApp1.IKaneboyServiceContract"

            binding="customBinding"

            bindingConfiguration="CustomServiceHttpsBinding" />

        </client>

        <bindings>

          <customBinding>

                …

          </customBinding>

        </bindings>

      </system.serviceModel>

    </configuration>

    Create Custom Service Proxy Class

    Service Proxy类用来描述service consumer。它继承SPIisWebServiceProxy,并实现IServiceProxyAdministration。

    [SupportedServiceApplication("933A11F0-7265-4694-97C0-FE04BFB370A5", "1.0.0.0", typeof(KaneboyServiceApplicationProxy))]

    [Guid("44203351-1E42-413E-BAAA-42A4A0788A8D")]

    public class KaneboyServiceProxy : SPIisWebServiceProxy, IServiceProxyAdministration

    Service Proxy类的构造函数:

    • 默认构造函数
    • 参数为SPFarm对象的构造函数

    IServiceProxyAdministration的方法:

    • CreateProxy():创建一个SPServiceApplicationProxy。
    • GetProxyTypeDescription():返回对此Service Proxy的描述。
    • GetProxyTypes():返回Service Application Proxy的类型。

    Create Custom Service Application Proxy Class

    Service Application Proxy类定义了连接到Service Application的接口,Service Consumer通过它实现对Service的调用。它继承SPIisWebServiceApplicationProxy类。

    [IisWebServiceApplicationProxyBackupBehavior]

    [System.Runtime.InteropServices.Guid("6339C282-E7D3-4B0D-94DF-2D09773FDF80")]

    public class KaneboyServiceApplicationProxy : SPIisWebServiceApplicationProxy

    Service Application Proxy类的构造函数:

    • 默认构造函数
    • 包含以下参数的构造函数:
      • Service Application Proxy的名称
      • 所对应的Service Proxy对象
      • Service Application的Endpoint URL

    public KaneboyServiceApplicationProxy() : base() {}

    public KaneboyServiceApplicationProxy(String name, KaneboyServiceProxy serviceProxy, Uri serviceEndpointUri) : base(name, serviceProxy, serviceEndpointUri)

    {

    _loadBalancer = new SPRoundRobinServiceLoadBalancer(serviceEndpointUri);

    }

    由于Service Application通常需要Load Balance的能力,所以Service Application Proxy通常会包含一个SPServiceLoadBalancer类型field,它可以使用SharePoint内置提供的SPRoundRobinServiceLoadBalancer类来实例化。SPRoundRobinServiceLoadBalancer类需要给出Service Application的URL来进行构造。

    Service Application Proxy要实现的方法:

    • 一个根据Service Application的Url,获取Endpoint Configuration名称(对应到client.config中”<Endpoint>”节点的”name”属性)的方法(如“GetEndpointConfigurationName()”),Endpoint Configuration的名称通常是“http”和“https”。
    • 一个创建并返回ChannelFactory<T>的方法(如“CreateChannelFactory()”),它需要读取client.config中的信息。

    private ChannelFactory<T> CreateChannelFactory<T>(string endpointConfigName)

    {

    // open client.config

    string clientConfigPath = SPUtility.GetGenericSetupPath(@"WebClientsKaneboyServiceApp1");

    Configuration clientConfig = OpenClientConfiguration(clientConfigPath);

    ConfigurationChannelFactory<T> factory = new ConfigurationChannelFactory<T>(endpointConfigName, clientConfig, null);

    // configure the channel factory for IDFx claims auth

    factory.ConfigureCredentials(SPServiceAuthenticationMode.Claims);

    return factory;

    }

    • 一个获取Channel(Service Contract接口)的方法,通过调用ChannelFactory. CreateChannelActingAsLoggedOnUser<T>(),来获取Channel。

    private IKaneboyServiceContract GetChannel(Uri address)

    {

        // get the endpoint config name

        string endpointConfigName = GetEndpointConfigurationName(address);

        ChannelFactory<IKaneboyServiceContract> channelFactory = CreateChannelFactory<IKaneboyServiceContract>(endpointConfigName);

        IKaneboyServiceContract channel  = channelFactory.CreateChannelActingAsLoggedOnUser<IKaneboyServiceContract>(new EndpointAddress(address));

        return channel;

    }

    结合以上的Helper方法,就可以拿到可以透过WCF远程调用Service Application的Channel对象。

    创建(并Provision)一个Service Application Proxy的步骤如下:

    • 调用Service Application Proxy构造函数,新建实例。
    • 调用SPServiceApplicationProxy.Update(true)将对象persist到ConfigDB中。
    • 调用SPServiceApplicationProxy.Provision()。

    类似Service Application,创建Service Application Proxy的方法可以放到此类中,以static method的方式提供。

    Create and Provision Service Application Proxy

    新建并Provision Service Application Proxy,类似Service Application,可以使用管理中心UI或自定义powershell cmelets实现。

    如果是使用管理中心UI,可以在创建并Provision了Service Application之后,紧接着创建Service Application Proxy。如果是创建cmdlets,可以使用SPServiceApplicationPipeBind来得到其所对应的Service Application。

    Invoke Service

    通过Service Application Proxy调用Service Application所提供的功能,步骤如下:

    • 获取SPServiceApplicationProxy对象,可以通过SPServiceContext.GetDefaultProxy()来获得。
    • 调用SPServiceApplicationProxy对象所持有的SPServiceLoadBalancer对象的BeginOperation()获取一个SPServiceLoadBalancerContext对象,然后通过使用SPServiceLoadBalancerContext.EndpointAddress拿到这次请求需要调用的Endpoint Url。使用此Url,并通过调用Service Application Proxy中的Helper方法,拿到IChannel对象,也就是实现了Service Contract的对象。
    • 调用IChannel上的方法
    • 使用IChannel.Close()关闭连接。
    • 调用SPServiceLoadBalancer.EndOperation()告知完成了Load Balance操作。
  • 相关阅读:
    常用JSR-303数据校验
    SpringBoot配置文件及自动配置原理
    SpringBoot自动装配原理
    Centos安装TensorFlow和Keras
    Batch梯度下降
    梯度下降法的注意点
    读取流量
    Linux开机启动服务
    Shell分割字符得到数组
    Linux下无图形界面安装Matlab
  • 原文地址:https://www.cnblogs.com/hero8377/p/3171922.html
Copyright © 2011-2022 走看看