Simplest service in one .svc file
<%@ ServiceHost Language="C#" Debug="true" Service="WcfServiceSimpleNs.WcfServiceSimple" %>
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace WcfServiceSimpleNs
{
[ServiceContract]
public interface IWcfServiceSimple
{
[OperationContract]
string GetData(int value);
}
public class WcfServiceSimple : IWcfServiceSimple
{
public string GetData(int value)
{
return string.Format("Simplest: Argument passed: {0}", value);
}
}
}
More info and samples on: www.devarchweb.net
What type of application pool needs to be used Make sure that you select the AppPool with Integrated Pipeline modeMore info and samples on: www.devarchweb.net
Minimum config file Note: if you do not have any service listed in your config at all, when debugging from Visual Studio with IIS Express<configuration>
<system.serviceModel>
<services>
<!-- Note: the service name must match the configuration name for the service implementation. -->
<service
name="WcfServiceSimpleNs.WcfServiceSimple"
behaviorConfiguration="MyServiceTypeBehaviors" >
<endpoint
address=""
binding="wsHttpBinding"
contract="WcfServiceSimpleNs.IWcfServiceSimple" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
More info and samples on: www.devarchweb.net
Disable WSDL<serviceMetadata httpGetEnabled="false" />
More info and samples on: www.devarchweb.net
From which file reads service its configuration (selfhosted and IIS) Be aware that the when the service is hosted by IIS then the service reads its System.ServiceModel configurationMore info and samples on: www.devarchweb.net
What is called ABC Address - specify location of the service. Client will need to set this to URL of the service.More info and samples on: www.devarchweb.net
Binding types basicHttpBinding - SOAP 1.1 (weak security; great on intercompatilibilityMore info and samples on: www.devarchweb.net
What are the deployment options 1. one embeded file (described above)<%@ ServiceHost Language="C#" Debug="true" Service="WcfServiceSimpleNs.WcfServiceSimple" %>
using System;
...
namespace WcfServiceSimpleNs
{
public interface IWcfServiceSimple { ... }
public class WcfServiceSimple : IWcfServiceSimple { ... }
}
More info and samples on: www.devarchweb.net
Create self host for WCF service 1. Create console application // Must be executed with VS running As Administrator
static void Main(string[] args)
{
Uri baseSvcAddress = new Uri("http://localhost:9000/MyServiceHost");
// Create the host
using (ServiceHost host = new ServiceHost(typeof(WcfServiceSimple), baseSvcAddress))
{
// Enable metadata
ServiceMetadataBehavior svcMetadataBehavior = new ServiceMetadataBehavior();
svcMetadataBehavior.HttpGetEnabled = true;
svcMetadataBehavior.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(svcMetadataBehavior);
// base service address will be used.
host.Open();
Console.WriteLine("The service is running at {0}", baseSvcAddress);
Console.WriteLine("Press 'Enter' to stop the service.");
Console.ReadLine();
// Close the host.
host.Close();
}
}
More info and samples on: www.devarchweb.net
How to create WCF service client Consuming WCF service:// create client using defined configuration from
using (var client = new WcfServiceSimpleClient("BasicHttpBinding_IWcfServiceSimple"))
{
// call a service method with 1 argument
string result = client.GetData(2);
}
More info and samples on: www.devarchweb.net
Create client without service reference and app.config It is possible to create a client and call his methods without specifying parameters in config file// create channel
var myBinding = new WebHttpBinding();
var myEndpoint = new EndpointAddress("http://myurl.net");
var channelFactory = new ChannelFactory<IMyInterface>(myBinding, myEndpoint);
channelFactory.Endpoint.Behaviors.Add(new WebHttpBehavior());
IComplianceFacade client = null;
client = channelFactory.CreateChannel();
// make the call
client.MyMethod();
// close channel
channelFactory.Close();
More info and samples on: www.devarchweb.net
How to debug the WCF service from Visual Studio - In Visual Studio, in Solution Explorer, click on the .svc file.More info and samples on: www.devarchweb.net
What is the purpose of web.config|web.debug.config|web.release.config The same section in web.config gets replaced with content of web.release.config or web.release.config<connectionStrings>
<add name="MyDB"
connectionString="Data Source=.;Initial Catalog=DevelopmentDB;Integrated Security=True" />
</connectionStrings>
</code>
<connectionStrings>
<add name="MyDB"
connectionString="Data Source=ProductionSQLServer;Initial Catalog=ProductionDB;Integrated Security=True"
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
More info and samples on: www.devarchweb.net
Format of transmitted data - simple types For the method below using simple data typespublic string MyMethod(int myIntValue, string myStringValue)
{
return string.Format("Arguments passed: {0} {1}", myIntValue, myStringValue);
}
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IWcfServiceSimple/MyMethod</Action>
</s:Header>
<s:Body>
<MyMethod xmlns="http://tempuri.org/">
<myIntValue>2</myIntValue>
<myStringValue>abc</myStringValue>
</MyMethod>
</s:Body>
</s:Envelope>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<MyMethodResponse xmlns="http://tempuri.org/">
<MyMethodResult>Arguments passed: 2 abc</MyMethodResult>
</MyMethodResponse>
</s:Body>
</s:Envelope>
More info and samples on: www.devarchweb.net
Format of transmitted data - composite types For the method below using composite data types[DataContract]
public class MyCompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
public MyCompositeType GetDataUsingDataContract(MyCompositeType composite)
{
return composite;
}
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IWcfServiceSimple/GetDataUsingDataContract</Action>
</s:Header>
<s:Body>
<GetDataUsingDataContract xmlns="http://tempuri.org/">
<composite xmlns:d4p1="http://schemas.datacontract.org/2004/07/WcfServiceSimple" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<d4p1:BoolValue>false</d4p1:BoolValue>
<d4p1:StringValue>abc</d4p1:StringValue>
</composite>
</GetDataUsingDataContract>
</s:Body>
</s:Envelope>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<GetDataUsingDataContractResponse xmlns="http://tempuri.org/">
<GetDataUsingDataContractResult xmlns:a="http://schemas.datacontract.org/2004/07/WcfServiceSimple" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:BoolValue>false</a:BoolValue>
<a:StringValue>abc</a:StringValue>
</GetDataUsingDataContractResult>
</GetDataUsingDataContractResponse>
</s:Body>
</s:Envelope>
More info and samples on: www.devarchweb.net
How to enable exception details (2 options) 1. In code[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class WcfServiceSimple : IWcfServiceSimple
<system.serviceModel>
<services>
<service name="ServiceNamespace.ServiceClassName" behaviorConfiguration ="DebugEnabled">
</service>
</services>
<behaviors>
<serviceBehaviors >
<behavior name="DebugEnabled">
<serviceDebug includeExceptionDetailInFaults="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
</system.serviceModel>
More info and samples on: www.devarchweb.net
How to configure large WCF messages<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="largeMessageBinding"
receiveTimeout="00:10:00"
sendTimeout="00:10:00"
maxReceivedMessageSize="1000485760"
>
<readerQuotas maxArrayLength="1000485760"/>
</binding>
</netTcpBinding>
</bindings>
<services>
<service
name="largeMessageService"
<endpoint
binding="netTcpBinding"
bindingConfiguration="largeMessageBinding"
... />
</service>
<services>
</system.serviceModel>
More info and samples on: www.devarchweb.net
What happens if new field is added to composite type or an old field is renamed If you add a new field as last field to a composite type on the service side and do not update the composite type on the client side, you can still callMore info and samples on: www.devarchweb.net
How to inject WCF service with Unity (2.options) Install Unity Nuget packagepublic interface IExternalRepository
{
int GetData();
}
public class ExternalRepository : IExternalRepository
{
public int GetData()
{
int result = // read from a database
return result;
}
}
public class MyUnityService : IWcfServiceSimple
{
public string GetData()
{
return _externalRepository.GetData();
}
}
using Microsoft.Practices.Unity;
public class DependencyFactory
{
private static IUnityContainer _container { get; set; }
static DependencyFactory()
{
_container = new UnityContainer();
container.RegisterType<IExternalRepository, ExternalRepository>();
}
public static T Resolve<T>()
{
T result = default(T);
if (_container.IsRegistered(typeof(T)))
{
result = _container.Resolve<T>();
}
return result;
}
}
public class MyUnityService : IWcfServiceSimple
{
private readonly IExternalRepository _externalRepository;
public MyUnityService() : this(DependencyFactory.Resolve<IExternalRepository>())
{
}
public MyUnityService(IExternalRepository externalRepository)
{
_externalRepository = externalRepository;
}
public string GetData()
{
return _externalRepository.GetData();
}
}
<%@ ServiceHost Language="C#" Debug="true" Factory="WcfServiceSimpleNs.WcfServiceHostFactory"
Service="WcfServiceSimpleNs.WcfServiceSimple2" CodeBehind="WcfServiceSimple2.svc.cs" %>
public partial class WcfServiceHost : ServiceHost
{
public WcfServiceHost(IUnityContainer container, Type serviceType, params Uri[] baseAddresses)
: base(container.Resolve(serviceType), baseAddresses)
{
}
public WcfServiceHost(IUnityContainer container, Type serviceType)
: base(container.Resolve(serviceType))
{
}
}
public class WcfServiceHostFactory : ServiceHostFactory
{
private readonly IUnityContainer _container;
public WcfServiceHostFactory()
{
_container = new UnityContainer();
_container.RegisterType<IExternalRepository, ExternalRepository>();
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new WcfServiceHost(_container, serviceType, baseAddresses);
}
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class WcfServiceSimple2 : IWcfServiceSimple2
{
}
More info and samples on: www.devarchweb.net
Turn off authentication<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="CustomBinding">
<security mode="None">
<message establishSecurityContext="false"/>
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<service>
<endpoint
...
binding="wsHttpBinding"
bindingConfiguration="CustomBinding"
>
</endpoint>
</service>
....
<system.serviceModel>
WSHttpBinding wsb = new WSHttpBinding(SecurityMode.Message, false);
wsb.Security.Transport.ClientCredentialType = MessageCredentialType.None;
wsb.Security.Message.EstablishSecurityContext = false;
More info and samples on: www.devarchweb.net
install certificate in local machine storage The standard installation with double click on the certificate file is not the right installation procedureMore info and samples on: www.devarchweb.net
ASP.net configuration in Visual Studio 2013 Start IIS express (not as admin) - works with .net 4More info and samples on: www.devarchweb.net
Assign certificate to client in codeusing System.Security.Cryptography.X509Certificates;
var store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certificatesFound = store.Certificates.Find(X509FindType.FindBySubjectName, (object)"MyCertificateName", true);
store.Close();
channelFactory.Credentials.ClientCertificate.Certificate = certificatesFound[0];
More info and samples on: www.devarchweb.net
Add http header to request Adding a header to request requires to implement IClientMessageInspector and IEndpointBehaviorpublic class HttpHeaderEndpointBehavior : IEndpointBehavior
{
private readonly IDictionary<string, string> _headers;
public HttpHeaderEndpointBehavior(IDictionary<string, string> headers)
{
_headers = headers;
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
var inspector = new HttpHeaderClientMessageInspector(_headers);
clientRuntime.MessageInspectors.Add(inspector);
}
// implementation of abstract nmethods
public void Validate(ServiceEndpoint endpoint) { }
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
}
public class HttpHeaderClientMessageInspector : IClientMessageInspector
{
private readonly IDictionary<string, string> _headers;
public HttpHeaderClientMessageInspector(IDictionary<string, string> headers)
{
_headers = headers;
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
HttpRequestMessageProperty httpRequestMessage;
object httpRequestMessageObject;
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject))
{
httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
if (httpRequestMessage != null)
{
foreach (var h in _headers)
{
httpRequestMessage.Headers[h.Key] = h.Value;
}
}
}
return null;
}
public void AfterReceiveReply(ref Message reply, object correlationState) { }
}
// add header to channel factory before creating the channel
// HttpHeaderEndpointBehavior will be called before each request
var headerDict = new Dictionary<string, string>();
headerDict.Add("MyHeaderKey", "MyHeaderValue");
facadeChannelFactory.Endpoint.Behaviors.Add(new HttpHeaderEndpointBehavior(headerDict));