Un progetto SharePoint 2013 in Visual Studio 2012 non supporta nativamente i file con estensione svc, questo causa la non sostituzione automatica dei token, come ???variable:SharePoint???, durante il deploy.

Nativamente la sostituzione dei token funziona solo sui file con estensione: XML,ASCX,ASPX,Webpart,DWP.

Per aggiungere altre estensioni di file devi modificare il file di progetto .cdproj aggiungendo il tag TokenReplacementFileExtensions:

File: nomeProgetto.cdproj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    ...
    <SandboxedSolution>False</SandboxedSolution>

    <!-- add here -->
    <TokenReplacementFileExtensions>ashx;svc</TokenReplacementFileExtensions>
  </PropertyGroup>
  ..
</Project>
nell'esempio ho aggiunto le estensioni .ashx e .svc.

Fatto questo, per creare un servizio WCF, è sufficiente riaprire Visual Studio 2012 e:
  • creare una solution vuota di SharePoint 2013
  • aggiungere le refenrence alle dll
    - Microsoft.SharePoint.Client.Runtime 15.0.0.0 (C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI)
    - System.ServiceModel 4.0.0.0
    - System.ServiceModel.Web 4.0.0.0
  • aggiungere il folder mapped ISAPI
  • aggiungere un file di testo cambiando l'estensione in svc (es: ProvaService.svc)
  • aggiungere un file di testo .svc.cs (es: ProvaService.svc.cs)
  • aggiungere un file di testo .cs per l'interfaccia del WCF (es: IProvaService.cs)
A questo punto durante il deploy o la creazione del package si avrà la sostituzione dei token.
I file seguenti sono solo un esempio di struttura.

File: ProvaService.svc
<%@ ServiceHost Language="C#" Debug="true"
    Service="Sgart.IT.ProvaService, $SharePoint.Project.AssemblyFullName$"  
    CodeBehind="ProvaService.svc.cs"
    Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory, Microsoft.SharePoint.Client.ServerRuntime, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

File: ProvaService.svc.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SharePoint.Client.Services;
using System.ServiceModel.Activation;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace Sgart.IT
{
  [BasicHttpBindingServiceMetadataExchangeEndpointAttribute]
  [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
  public class ProvaService : IProvaService
  {
    public HDTasks RequestMy()
    {
      HDTasks result = new HDTasks();

      try
      {
        //TODO: riempire l'oggetto result

        //result.ReturnValue = items.Count;
        result.Success = true;
      }
      catch (Exception ex)
      {
        //LoggingService.WriteError("Error encountered in wcf Request/My: " + ex.Message);
        result.AddError(ex);
      }
      return result;
    }
  }
}

File: IProvaService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Web;

namespace Sgart.IT
{
    [ServiceContract]
    public interface IProvaService
    {
        /// <returns></returns>
        [OperationContract]
        [WebGet(UriTemplate = "Requests/My", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        HDTasks RequestMy();
    }

    [DataContract]
    public class ServiceStatus
    {
        public ServiceStatus()
        {
            Success = false;
            Errors = new List<string>();
            ReturnValue = -1;
        }
        [DataMember(Name = "success")]
        public bool Success { get; set; }
        [DataMember(Name = "errors")]
        public List<string> Errors { get; set; }
        [DataMember(Name = "returnValue")]
        public int ReturnValue { get; set; }

        public void AddError(string message)
        {
            Errors.Add(message);
            Success = false;
        }
        public void AddError(Exception ex)
        {
            Errors.Add(ex.Message);
            Success = false;
        }
    }

    [DataContract]
    public class HDTasks : ServiceStatus
    {
        [DataMember(Name = "items")]
        public List<string> Items;

        public HDTasks()
        {
            Items = new List<string>();
        }
    }
}


Un servizio come questo può essere interrogato via JQuery tramite una url del tipol http://sharepoint/site1/_vti_bin/Isa...c/Request/My e restituisce un oggetto JSON. I parametri ritornati sono le proprietà decorate con l'attributo DataMember.