Creating a WCF service to use with CRM HTML web resource

Posted on Posted in MS Dynamics, WCF

In this example we are going to create a WCF service which will be later consumed using HTML web resource (AJAX call) in CRM 2015/2013.

First we need to create a simple Class library project in Visual Studio 2013. Give solution name = FOM and porject = FOM.Core

FOM.Core will have our Interface (ServiceContract) and service class.

Add a new Interface by the name of IFOMService

Add a new Class by the name of FOMService

Add a new OperationContract and give it a name FindPerson

Your final interface should look like below

[ServiceContract]
public interface IFOMService
{

[WebGet(UriTemplate = “/findperson/{name}”,ResponseFormat = WebMessageFormat.Json,BodyStyle = WebMessageBodyStyle.Bare)]
string FindPerson(string name);
}

We are defining UriTemplare as we will be later using this to call in Web Respurce using AJAX call

Now implement method FindPerson in class FOMService created above, it should like something like below

public string FindPerson(string input)
{
return input;
}

Next we need to do is add an other project (FOM.Server) as empty web site and add reference from FOM.Core project

FOM.Server has nothing in at the moment and only has references.

In web.config we need to add several configuration to fulfil requirements but main part is to add following code

in side of <system.servicemodel>

<serviceHostingEnvironment aspNetCompatibilityEnabled=”true”>
<serviceActivations>
<add factory=”System.ServiceModel.Activation.ServiceHostFactory” relativeAddress=”./FOMService.svc”
service=”FOM.Service.FOMService”/>
</serviceActivations>
</serviceHostingEnvironment>

Below is full web.cofig code which will be used for deployment of our service on HTTPS enpoints

<?xml version=”1.0″?>

<!–
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
–>

<configuration>
<connectionStrings>
</connectionStrings>
<appSettings>
</appSettings>
<system.web>
<customErrors mode=”Off”></customErrors>
<compilation debug=”true” strict=”false” explicit=”true” targetFramework=”4.5.2″ />
<httpRuntime targetFramework=”4.5.2″ requestPathInvalidCharacters=”” requestValidationMode=”2.0″ />
<pages validateRequest=”false” />
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name=”webBinding” crossDomainScriptAccessEnabled=”true” >
<readerQuotas maxStringContentLength=”2147483647″ maxArrayLength=”2147483647″ maxBytesPerRead=”2147483647″ maxDepth=”64″ maxNameTableCharCount=”2147483647″ />
<security mode=”None” />
</binding>
</webHttpBinding>
</bindings>
<services>
<service name=”FOM.Service.FOMService” behaviorConfiguration=”MPServiceTypeBehaviors” >
<endpoint contract=”FOM.Service.IFOMService” behaviorConfiguration=”RESTFriendly”  binding=”webHttpBinding”
bindingConfiguration=”webBinding”     />
<!–bindingConfiguration=”webBinding”–>
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled=”true”>
<serviceActivations>
<add factory=”System.ServiceModel.Activation.ServiceHostFactory” relativeAddress=”./FOMService.svc”
service=”FOM.Service.FOMService”/>
</serviceActivations>
</serviceHostingEnvironment>
<behaviors>
<serviceBehaviors>
<behavior name=”MPServiceTypeBehaviors”>
<serviceDebug includeExceptionDetailInFaults=”true”/>
<serviceMetadata httpGetEnabled=”true” httpsGetEnabled=”true”/>
<useRequestHeadersForMetadataAddress>
<defaultPorts>
<add scheme=”http” port=”8001″ />
<add scheme=”https” port=”443″ />
</defaultPorts>
</useRequestHeadersForMetadataAddress>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name=”RESTFriendly”>
<webHttp/>
<!–<enableWebScript/>–>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests=”true”/>
<!–
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
–>
<directoryBrowse enabled=”true”/>
</system.webServer>
<system.diagnostics>
<sources>
<source name=”System.ServiceModel”
switchValue=”Information, ActivityTracing”
propagateActivity=”true” >
<listeners>
<add name=”xml”/>
</listeners>
</source>
<source name=”System.ServiceModel.MessageLogging”>
<listeners>
<add name=”xml”/>
</listeners>
</source>
<source name=”myUserTraceSource”
switchValue=”Information, ActivityTracing”>
<listeners>
<add name=”xml”/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name=”xml”
type=”System.Diagnostics.XmlWriterTraceListener”
initializeData=”Error.svclog” />
</sharedListeners>
</system.diagnostics>
</configuration>

Once you build and browse your service using url i.e. localhost/FieldOneMSPSService.svc you will see results

If your service is deployed on different domain than where you are calling it from you might come across domain security error and by adding following code will get rid of the error

protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader(“Access-Control-Allow-Origin”, “*”);
if (HttpContext.Current.Request.HttpMethod == “OPTIONS”)
{
HttpContext.Current.Response.AddHeader(“Access-Control-Allow-Methods”, “POST, PUT, DELETE”);

HttpContext.Current.Response.AddHeader(“Access-Control-Allow-Headers”, “Content-Type, Accept”);
HttpContext.Current.Response.AddHeader(“Access-Control-Max-Age”, “1728000”);
HttpContext.Current.Response.End();
}
}

Above code goes to Global.asax of service

* in         HttpContext.Current.Response.AddHeader(“Access-Control-Allow-Origin”, “*”); can be replaced with required URL