Monday, January 6, 2014

really adding WCF to sharepoint existing project

story is like this: we have a Sharepoint (10) solution, with already 12 (yep...) projects and we need a new service so... why another project? Sharepoint is a platform.

there are many sites explaining what and how to do it but i found them all being either too long, making it somehow too complex(msdn), or no accurate so i'll add mine.

my no.1 source: http://www.c-sharpcorner.com/UploadFile/anavijai/how-to-create-and-host-wcf-service-inside-sharepoint-2010/.

in the end its so simple: add a Sharepoint Mapped to ISAPI folder, inside create a new folder of your own service, and now you need inside there 4 files:
1. YourService.cs
2. IYourService.cs
3. YourService.svc
3. web.config (which is the main reason you want your own folder).

the inner content of the cs files copy from the url above, about the svc here is a simpler version:
<%@ServiceHost Language="C#" Debug="true" CodeBehind="fileOfClass.cs"    Service="yourNameSpace.yourClass, $SharePoint.Project.AssemblyFullName$"%>

and about the web.config i saw some mistakes so here is mine
<?xml version="1.0"?>
<configuration>
  <system.web>
    <!-- dont forget to remove this after dev is finish -->
    <customErrors mode="RemoteOnly"/>
  </system.web>
 
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="yourNameSpace.ServiceBehavior" name="yourNameSpace.yourClass">
        <endpoint address="" binding="basicHttpBinding" contract="yourNameSpace.yourInterface(like IService)">
          <identity>
            <!-- not sure yet if it will work in prod or not, after all its inner to the project, hope to update-->
            <dns value="localhost"/>
          </identity>
        </endpoint>

        <!-- this endpoint is to see service in browser, its removalbe -->
        <endpoint address="max" binding="mexHttpBinding" contract="IMetadataExchange"/>
       
        <host>
          <baseAddresses>
            <add baseAddress="http://yourServer:port(no need if its 80)/whatever you want/"/>
          </baseAddresses>
        </host>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="yourNameSpace.ServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <!-- should be false in prod -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>

  <!-- just in case -->
  <appSettings>
    <add key="someKey" value="someValue" />
  </appSettings>
 
</configuration>

now you probably read this because you want a service for your site, so here is how you open a web and log since your current web is your service, and also you shouldnt have permissions (btw when you run it start with a method bool that just return true to be sure that it works):
public string ExploreSite()
{
    try
    {
       string result = string.Empty;
       SPSecurity.RunWithElevatedPrivileges(() =>
       {
           string siteUrl = ConfigurationManager.AppSettings["siteUrl"];
           using (SPSite site = new SPSite(siteUrl))
           {
               using (SPWeb web = site.OpenWeb())
               {
                   result = web.Name;
               }
           }
           });
           return result;
    }
    catch (Exception ex)
    {
          string m = ex.Message;
          SPSecurity.RunWithElevatedPrivileges(() =>
          {
              if (EventLog.SourceExists("yourSource") == false)
              EventLog.CreateEventSource(new EventSourceCreationData("yourSource", "create"));
              while (ex.InnerException != null)
              {
                  ex = ex.InnerException;
                  m += Environment.NewLine + ex.Message;
              }
              EventLog.WriteEntry("yourSource", ex.Message, EventLogEntryType.Error);
          });
          return m;
    }
}

note:
1. to refresh the code for a client you need to rebuild and recycle the pool. for debugging the same but it seems to fail sometimes if not called before by a client (no the browser).
2. in this case you dont need to worry about problems caused by a service being in .Net 4 vs the SP10 which is 3.5, and also you dont need to work hard for your web.config as usual for WCF in 3.5 since its all inside your already existing site.

No comments:

Post a Comment