Server Configuration
Hosting WCF services in IIS
Just like any regular WCF smart client you need to define in your configuration file your WCF configuration (addresses, bindings, contracts, etc.). If ever you want to host your WCF services in IIS rather than in another process, you'll need to generate svc files which indicates IIS where the service implementation is.
For instance:
| Sample.Customer.svc | Copy Code |
|---|---|
<%@ServiceHost language="C#" Debug="true" Service="Sample.Services.CustomerService"%> |
|
Please note that this can be automated using a template and the Template Producer, so if ever you add a new entity in your model, a svc file will automatically be generated.
| [Template]entity.svc | Copy Code |
|---|---|
[%@ template language="CSharp" output="false"%]
[%@ namespace name="System" %]
[%@ namespace name="CodeFluent.Model" %]
[%@ namespace name="CodeFluent.Producers.CodeDom" %]
[%@ namespace name="CodeFluent.Model.UI" %]
[%@ namespace name="CodeFluent.Model.UI.ControlDefinitions" %]
[%@ namespace name="CodeFluent.Producers.CodeDom.UI" %]
[%@ namespace name="System.IO" %]
[%
Entity entity = null;
if (Context["inTemplate"] == null)
{
Context["inTemplate"] = true; // anything would do, other than null
foreach(Entity e in Producer.Project.Entities)
{
//if (!CodeFluent.Producers.CodeDom.UI.Web.WebServiceProducer.IsEnabled(e))
// continue;
if (!Node.IsServiceEnabled(e.Element))
continue;
// build a new target path & re-run ourselves
string targetPath = Path.Combine(
Path.GetDirectoryName(TargetPath),
Path.GetFileName(TargetPath).Replace("entity", e.ClrFullTypeName));
using (GeneratedFile file = new GeneratedFile(Producer.Project, targetPath))
{
if ((file.HasBeenChanged) && ((e.ProductionFlags & ProductionFlags.Overwrite) == 0))
{
Producer.RaiseProduction(Producer, file.CreateFileSkipEvent("entity.svc"));
continue;
}
// note: we don't care about the output="false" here
Producer.RaiseProduction(Producer, ProductionEventArgs.CreateFileTemplateGenerateEvent(targetPath, Template.FilePath));
file.Open(Producer, Producer.OutputEncoding);
// add the entity to the context
Context["entity"] = e;
// update targetPath
Context["TargetPath"] = targetPath;
// go recursive, and this will jump to the else part of this file
Template.Run(file.Writer, Context);
}
}
}
else
{
entity = (Entity)Context["entity"];
%]
<%@ServiceHost language="C#" Debug="true" Service="[%=entity.ServiceClrFullTypeName%]"%>
[% }%]
|
|
ClientAccessPolicy.xml or CrossDomain.xml
To prevent cross-site request forgery, Silverlight allows only site-of-origin communication by default for all requests other than images and media. For example, a Silverlight control hosted at http://contoso.com/mycontrol.aspx can access only services on that same domain by default – for example http://contoso.com/service.svc, but not a service at http://fabrikam.com/service.svc. This prevents a malicious Silverlight control hosted on the http://contoso.com domain from calling unauthorized operations on a service hosted on the http://fabrikam.com domain.
To enable cross-site server calls you need to place on your server a ClientAccessPolicy.xml or a CrossDomain.xml file which enable such behaviors. This is standard to Silverlight developments and more information is available here: http://msdn.microsoft.com/en-us/library/cc197955(VS.95).aspx.
Client Configuration
ServiceReferences.ClientConfig
On the client side, you must define the services the application should consume. This is standard WCF configuration, nothing specific to CodeFluent Entities is required.
The WCF configuration should be placed in the ServiceReferences.ClientConfig file.
| ServiceReferences.ClientConfig | Copy Code |
|---|---|
<configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBindingNoSecurity" textEncoding="utf-8"> <security mode="None" /> </binding> </basicHttpBinding> </bindings> <client> <endpoint name="Sample.Customer" address="http://localhost/Sample/Services/Sample.Customer.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBindingNoSecurity" contract="Sample.Proxy.ICustomerService"/> </client> </system.serviceModel> </configuration> |
|
Please note that this could be automated using a template and the Template Producer, here's a sample templated version of the ServiceReferences.ClientConfig file:
| [Template]ServiceReferences.ClientConfig | Copy Code |
|---|---|
<?xml version="1.0" ?> <!-- [%=Producer.GetSignature()%] --> <configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBindingNoSecurity" textEncoding="utf-8"> <security mode="None" /> </binding> </basicHttpBinding> </bindings> <client> [%foreach(Entity entity in Producer.Project.Entities){ if (!Node.IsServiceEnabled(entity.Element)) continue;%] <endpoint name="[%=entity.ClrFullTypeName%]" address="http://localhost/[%=Producer.Project.DefaultNamespace%]/Services/[%=entity.ClrFullTypeName%].svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBindingNoSecurity" contract="[%=entity.ProxyServiceInterface.ClrFullTypeName%]" /> [% if (entity.HasPublicBinaryLargeObjectProperties) { %] <endpoint name="[%=entity.ClrFullTypeName%]/BinaryService" address="http://localhost/[%=Producer.Project.DefaultNamespace%]/Services/[%=entity.ClrFullTypeName%]/BinaryService" binding="basicHttpBinding" bindingConfiguration="BasicHttpBindingNoSecurity" contract="CodeFluent.Runtime.BinaryServices.ICodeFluentBinaryService" /> [% }} %] </client> </system.serviceModel> </configuration> |
|