Configure a WCF client's MaxItemsInObjectGraph when using Unity - c#

For a toolkit that uses a remote WCF service, I have configured a ChannelFactory<IMyService> in a UnityContainer.
Now I want to configure this channel's endpoint behavior through code (using Unity) to apply this behavior:
<behaviors>
<endpointBehaviors>
<behavior name="BigGraph">
<dataContractSerializer maxItemsInObjectGraph="1000000" />
</behavior>
</endpointBehaviors>
</behaviors>
I found this example on MSDN (http://msdn.microsoft.com/en-us/library/ms732038.aspx)
ChannelFactory<IDataService> factory = new ChannelFactory<IDataService>(binding, address);
foreach (OperationDescription op in factory.Endpoint.Contract.Operations)
{
vardataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>() as DataContractSerializerOperationBehavior;
if (dataContractBehavior != null)
{
dataContractBehavior.MaxItemsInObjectGraph = 100000;
}
}
IDataService client = factory.CreateChannel();
but now I am stuck trying to do this in a Unity configuration. Should I look into Interception?

We are using a build policy extension in unity to add behaviors on the service host. On the client we have a ServiceFactory.
/// <summary>
/// Factory for creating application service proxies used on the workstation
/// </summary>
/// <typeparam name="TInterface">Interface for the service contract</typeparam>
public class ServiceFactory<TInterface> where TInterface : class
{
private readonly List<IEndpointBehavior> m_Behaviors = new List<IEndpointBehavior>();
/// <summary>
/// Add a behavior that is added to the proxy endpoint when the channel is created.
/// </summary>
/// <param name="behavior">An <see cref="IEndpointBehavior"/> that should be added</param>.
public void AddBehavior(IEndpointBehavior behavior)
{
m_Behaviors.Add(behavior);
}
/// <summary>
/// Creates a channel of type <see cref="CommunicationObjectInterceptor{TInterface}"/> given the endpoint address which
/// will recreate its "inner channel" if it becomes in a faulted state.
/// </summary>
/// <param name="url">The endpoint address for the given channel to connect to</param>.
public TInterface CreateChannel(string url)
{
// create the channel using channelfactory adding the behaviors in m_Behaviors
}
}
Then we configure unity with an InjectionFactory
new InjectionFactory(c =>
{
var factory = new ServiceFactory<TInterface>();
factory.AddBehavior(c.Resolve<IClientTokenBehavior>());
return factory.CreateChannel(url);
});
By doing it this way you can also resolve your behavior through unity if you have some dependencies.

I think you should add one more level of indirection so you don't need to mess with interception or something like that. This problem can be easily solved by creating a new class for wraping up the WCF channel. For instance,
public class MyServiceClient : IMyService
{
public MyServiceClient(IChannelFactory<IMyService> channel)
{
}
public void DoSomething() //DoSomething is the implementation of IMyService
{
//Initialize the behavior in the channel
//Calls channel.DoSomething
}
}

Related

How to use IDispatchMessageInspector in a WCF Service?

I am trying to use IDispatchMessageInspector in a WCF service implementation to access custom header values.
Something like:
public class MyService : IMyService
{
public List<string> GetNames()
{
var headerInspector = new CustomHeaderInspector();
// Where do request & client channel come from?
var values = headerInspector.AfterReceiveRequest(ref request, clientChannel, OperationContext.Current.InstanceContext);
}
}
I've implemented my own IDispatchMessageInspector class.
public class CustomHeaderInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
var prop = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
var userName = prop.Headers["Username"];
return userName;
}
}
How do I pass
System.ServiceModel.Channels.Message and
System.ServiceModel.IClientChannel
to AfterReceiveRequest called from the service implementation?
EDIT:
Many articles like this one or this one, give examples on how to implement your own ServiceBehavior. So your service implementation looks like this:
[MyCustomBehavior]
public class MyService : IMyService
{
public List<string> GetNames()
{
// Can you use 'MyCustomBehavior' here to access the header properties?
}
}
So with this, can I access MyCustomBehavior somehow within the service operation method to access custom header values?
You have to configure the
<extensions>
<behaviorExtensions>
<add
name="serviceInterceptors"
type="CustomHeaderInspector , MyDLL, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
/>
</behaviorExtensions>
</extensions>
Then the extension will be handled in your WCF stack. The service itself has no notion of the serviceInterceptors and you do not have to do something like in your first code block. The WCF stack will inject you Inspector.
MSDN: system.servicemodel.dispatcher.idispatchmessageinspector
I'm using IClientMessageInspector for same goal.
Here is how you can apply them from code:
var serviceClient = new ServiceClientClass(binding, endpointAddress);
serviceClient.Endpoint.Behaviors.Add(
new MessageInspectorEndpointBehavior<YourMessageInspectorType>());
/// <summary>
/// Represents a run-time behavior extension for a client endpoint.
/// </summary>
public class MessageInspectorEndpointBehavior<T> : IEndpointBehavior
where T: IClientMessageInspector, new()
{
/// <summary>
/// Implements a modification or extension of the client across an endpoint.
/// </summary>
/// <param name="endpoint">The endpoint that is to be customized.</param>
/// <param name="clientRuntime">The client runtime to be customized.</param>
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new T());
}
/// <summary>
/// Implement to pass data at runtime to bindings to support custom behavior.
/// </summary>
/// <param name="endpoint">The endpoint to modify.</param>
/// <param name="bindingParameters">The objects that binding elements require to support the behavior.</param>
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
// Nothing special here
}
/// <summary>
/// Implements a modification or extension of the service across an endpoint.
/// </summary>
/// <param name="endpoint">The endpoint that exposes the contract.</param>
/// <param name="endpointDispatcher">The endpoint dispatcher to be modified or extended.</param>
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
// Nothing special here
}
/// <summary>
/// Implement to confirm that the endpoint meets some intended criteria.
/// </summary>
/// <param name="endpoint">The endpoint to validate.</param>
public void Validate(ServiceEndpoint endpoint)
{
// Nothing special here
}
}
And here is sample implementation of MessageInspector I'm using to pass client version to server, and retrieve server version in custom headers:
/// <summary>
/// Represents a message inspector object that can be added to the <c>MessageInspectors</c> collection to view or modify messages.
/// </summary>
public class VersionCheckMessageInspector : IClientMessageInspector
{
/// <summary>
/// Enables inspection or modification of a message before a request message is sent to a service.
/// </summary>
/// <param name="request">The message to be sent to the service.</param>
/// <param name="channel">The WCF client object channel.</param>
/// <returns>
/// The object that is returned as the <paramref name="correlationState " /> argument of
/// the <see cref="M:System.ServiceModel.Dispatcher.IClientMessageInspector.AfterReceiveReply(System.ServiceModel.Channels.Message#,System.Object)" /> method.
/// This is null if no correlation state is used.The best practice is to make this a <see cref="T:System.Guid" /> to ensure that no two
/// <paramref name="correlationState" /> objects are the same.
/// </returns>
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
request.Headers.Add(new VersionMessageHeader());
return null;
}
/// <summary>
/// Enables inspection or modification of a message after a reply message is received but prior to passing it back to the client application.
/// </summary>
/// <param name="reply">The message to be transformed into types and handed back to the client application.</param>
/// <param name="correlationState">Correlation state data.</param>
public void AfterReceiveReply(ref Message reply, object correlationState)
{
var serverVersion = string.Empty;
var idx = reply.Headers.FindHeader(VersionMessageHeader.HeaderName, VersionMessageHeader.HeaderNamespace);
if (idx >= 0)
{
var versionReader = reply.Headers.GetReaderAtHeader(idx);
while (versionReader.Name != "ServerVersion"
&& versionReader.Read())
{
serverVersion = versionReader.ReadInnerXml();
break;
}
}
ValidateServerVersion(serverVersion);
}
private static void ValidateServerVersion(string serverVersion)
{
// TODO...
}
}
public class VersionMessageHeader : MessageHeader
{
public const string HeaderName = "VersionSoapHeader";
public const string HeaderNamespace = "<your namespace>";
private const string VersionElementName = "ClientVersion";
public override string Name
{
get { return HeaderName; }
}
public override string Namespace
{
get { return HeaderNamespace; }
}
protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
{
writer.WriteElementString(
VersionElementName,
Assembly.GetExecutingAssembly().GetName().Version.ToString());
}
}
I believe you don't need to implement custom IDispatchMessageInspector to retrieve custom headers, it can be done from service operation method like this:
var mp = OperationContext.Current.IncomingMessageProperties;
var property = (HttpRequestMessageProperty)mp[HttpRequestMessageProperty.Name];
var userName = property.Headers["Username"];
It makes sense to implement custom dispatch message inspector if you want to abort message processing, for example if credentials are missing - you can just throw FaultException in this case.
But if you still want to pass value from dispatch message inspector to service operation method - probably it can be passed through some singleton along with call identifier (session id), to be extracted later by method, or using wcf extensions
What I did to access the details I set the following inside IDispatchMessageInspector.AfterReceiveRequest
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(username, "Membership Provider"), roles);
I've omitted the authentication code from this.
To access the value from the service method, you can call
Thread.CurrentPrincipal.Identity.Name
On the MSDN page that you linked to there is also a description how an inspector can be inserted and also an example of that. To quote:
Typically, message inspectors are inserted by a service behavior, an endpoint behavior, or a contract behavior. The behavior then adds the message inspector to the DispatchRuntime.MessageInspectors collection.
Later on you have the following examples:
Implementing custom IDispatchMessageInspector
Implementing custom IServiceBehavior that adds the inspector to the runtime.
Configuration of the behavior via .config file.
That should be enough to get you started. Otherwise feel free to ask :)
If you just want to get access to headers from within your service, you could try OperationContext.Current.IncomingMessageHeaders.

How to unit test a circuit breaker?

I am using an external service for metatagging my pages. I implemented circuit breaker as well as fallback for it and is working perfectly. Now I want to write unit tests for it. Any thoughts?
I am pasting some part of my code for your review:
Unity Registration
.RegisterType<ITaggerRepository>(new InjectionFactory(c => Framework.CrossCutter.ApplyAspectsTo((ITaggerRepository)c.Resolve<CachedTaggerRepository>(), "TaggerRepository").Configure<ISlaAspectConfiguration<ITaggerRepository>>(config => config.Fallback = new TaggerRepositoryFallback())
.Proxy));
Fallback implementation:
public class TaggerRepositoryFallback : ITaggerRepository
{
/// <summary>
/// Requests the tags.
/// </summary>
/// <param name="request">The request.</param>
/// <returns>Tagger response</returns>
public TaggerResponse RequestTags(TaggerRequest request)
{
return new TaggerResponse
{
Url = request.PageUrl,

How do I capture incoming and outgoing XML from WCF service end

In my solution I have three projects. One is a WCF service, another is a Winforms app from where I am calling the web service, and the last is a class library where class has been design extending soap extension class.
My objective is to capture response & request xml when I am calling the WCF service from my Winforms app. I am getting object reference not set error when I am trying to capture xml.
Here is my class library source code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
using System.Net;
using System.Xml;
namespace SoapLogger
{
public class TraceExtension : SoapExtension
{
private Stream oldStream;
private Stream newStream;
private static XmlDocument xmlRequest;
/// <summary>
/// Gets the outgoing XML request sent to PayPal
/// </summary>
public static XmlDocument XmlRequest
{
get { return xmlRequest; }
}
private static XmlDocument xmlResponse;
/// <summary>
/// Gets the incoming XML response sent from PayPal
/// </summary>
public static XmlDocument XmlResponse
{
get { return xmlResponse; }
}
/// <summary>
/// Save the Stream representing the SOAP request
/// or SOAP response into a local memory buffer.
/// </summary>
/// <param name="stream">
/// <returns></returns>
public override Stream ChainStream(Stream stream)
{
oldStream = stream;
newStream = new MemoryStream();
return newStream;
}
/// <summary>
/// If the SoapMessageStage is such that the SoapRequest or
/// SoapResponse is still in the SOAP format to be sent or received,
/// save it to the xmlRequest or xmlResponse property.
/// </summary>
/// <param name="message">
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
xmlRequest = GetSoapEnvelope(newStream);
CopyStream(newStream, oldStream);
break;
case SoapMessageStage.BeforeDeserialize:
CopyStream(oldStream, newStream);
xmlResponse = GetSoapEnvelope(newStream);
break;
case SoapMessageStage.AfterDeserialize:
break;
}
}
/// <summary>
/// Returns the XML representation of the Soap Envelope in the supplied stream.
/// Resets the position of stream to zero.
/// </summary>
/// <param name="stream">
/// <returns></returns>
private XmlDocument GetSoapEnvelope(Stream stream)
{
XmlDocument xml = new XmlDocument();
stream.Position = 0;
StreamReader reader = new StreamReader(stream);
xml.LoadXml(reader.ReadToEnd());
stream.Position = 0;
return xml;
}
/// <summary>
/// Copies a stream.
/// </summary>
/// <param name="from">
/// <param name="to">
private void CopyStream(Stream from, Stream to)
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}
#region NoOp
/// <summary>
/// Included only because it must be implemented.
/// </summary>
/// <param name="methodInfo">
/// <param name="attribute">
/// <returns></returns>
public override object GetInitializer(LogicalMethodInfo methodInfo,
SoapExtensionAttribute attribute)
{
return null;
}
/// <summary>
/// Included only because it must be implemented.
/// </summary>
/// <param name="WebServiceType">
/// <returns></returns>
public override object GetInitializer(Type WebServiceType)
{
return null;
}
/// <summary>
/// Included only because it must be implemented.
/// </summary>
/// <param name="initializer">
public override void Initialize(object initializer)
{
}
#endregion NoOp
}
Here is how I am calling the web service from my Winforms app:
private void button1_Click(object sender, EventArgs e)
{
using (ServiceRef.TestServiceSoapClient oService = new ServiceRef.TestServiceSoapClient())
{
textBox1.Text = oService.HelloWorld("Sudip");
var soapRequest = SoapLogger.TraceExtension.XmlRequest.InnerXml;
var soapResponse = SoapLogger.TraceExtension.XmlResponse.InnerXml;
}
}
These two lines are causing the object reference error
var soapRequest = SoapLogger.TraceExtension.XmlRequest.InnerXml;
var soapResponse = SoapLogger.TraceExtension.XmlResponse.InnerXml;
I just could not figure out why I am getting error.
The Winforms app has an app.config where I register my class library assembly to capture the xml. Here is my app.config details
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="TestServiceSoap"/> </basicHttpBinding>
</bindings> <client> <endpoint address="http://localhost:6804/Service1.asmx"
binding="basicHttpBinding" bindingConfiguration="TestServiceSoap"
contract="ServiceRef.TestServiceSoap" name="TestServiceSoap"/>
</client>
</system.serviceModel>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<webServices> <soapExtensionTypes>
<add type="SoapLogger.TraceExtension,SoapLogger" priority="1" group="0" />
</soapExtensionTypes> </webServices>
</system.web>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup> </configuration>
When I search google just to know how to capture request/response xml then I got this kind of many article. I followed many but nothing works.
This url I followed to get the job done http://jramirezdev.net/blog/c-tip-capturar-los-mensajes-soap-de-un-servicio-asmx-que-hemos-referenciado
What kind of mistake am I making not clear. I set the break point at every method in my class library method but when web service call no method got executed in the class library. I don't want to use any tool like wireshark, fiddler to capture the request/response xml rather want to do same thing programatically.
So please guide me what is my mistake? Why am I getting object reference not set error? Please have a look at my code or go to the url link and tell me what is wrong in my approach
Simply we can trace the request message as.
OperationContext context = OperationContext.Current;
if (context != null && context.RequestContext != null)
{
Message msg = context.RequestContext.RequestMessage;
string reqXML = msg.ToString();
}
Configure WCF Tracing
Send/receive some messages
Get the SvcTraceViewer.exe log viewer and open the trace output.
Profit.
The error was caused because xmlRequest/xmlResponse have not been initialized when you access them. Hence, try to check null, or create default instances for them.
From your code they are only initialized in the ProcessMessage(SoapMessage message){}, make sure that the method is called before you call
var soapRequest = SoapLogger.TraceExtension.XmlRequest.InnerXml;
var soapResponse = SoapLogger.TraceExtension.XmlResponse.InnerXml;
Hope this helps.
EDIT:
After closely examining your code, I realized that the extension you wrote (SoapExtension) was for ASP.NET XML web services, and it had no business with a WCF service.
To inspect the request and reply in a WCF service, you can extend your dispatcher on the service side by implementing System.ServiceModel.Dispatcher.IDispatchMessageInspector.
You can find the example here http://msdn.microsoft.com/en-us/library/ms733104%28v=vs.100%29.aspx
There is an another way to see XML SOAP - custom MessageEncoder. The main difference from IDispatchMessageInspector / IClientMessageInspector is that it works on lower level, so it captures original byte content including any malformed xml.
In order to implement tracing using this approach you need to wrap a standard textMessageEncoding with custom message encoder as new binding element and apply that custom binding to endpoint in your config.
Also you can see as example how I did it in my project -
wrapping textMessageEncoding, logging encoder, custom binding element and config.

Can't call my service method

I'm getting this error:
The communication object,
System.ServiceModel.ChannelFactory`1[FxCurveService.IFxCurveService],
cannot be used for communication because it is in the Faulted state.
When I call this code:
using (var client = new WCFServiceChannelFactory<IFxCurveService>(new Uri("http://ksqcoreapp64int:5025/")))
{
guid = client.Call(svc => svc.ReserveSnapshot(fxCurveKey));
DiscountFactorNew[] dfs = client.Call(svc => svc.GetDiscountFactors(guid, dates, from));
Assert.IsTrue(guid != null);
}
It errors here - client.Call(svc => svc.ReserveSnapshot(fxCurveKey));
I have no idea why it is doing this. I am passing the right parameters, inputting the correct address for the service, what else should I be checking here?
Btw, WCFServiceChannelFactory is our own class we use to take care of making service calls. Outline here:
public class WCFServiceChannelFactory<T> : IDisposable
{
public WCFServiceChannelFactory();
public WCFServiceChannelFactory(Uri uri);
public T Channel { get; }
public System.ServiceModel.ChannelFactory<T> ChannelFactory { get; }
public Type ChannelType { get; }
public void Call(Action<T> f);
public R Call<R>(Func<T, R> f);
public void Dispose();
}
The thing is, the problem is not with this, as this is working in the same exact fashion in every other project but this one. Basically, I have to pass the Uri directly in mine, where as others derive it from a .config file in the project, which I was unable to do here. That's the only difference.
Thanks.
You can't access details of the exception if the channel is disposed. So the lovely using pattern construction is not recommended when accessing a WCF service. In fact, the Exception properties requires to have access to the channel to extract some information about the exception (don't know if MS missed that point, or if there are technical reasons behind).
I've written a small class to simplify the call to WCF proxies (this site helps me to understand the problem and to write the class) :
using System;
using System.ServiceModel;
namespace Utility
{
public class ServiceHelper
{
/// <summary>
/// WCF proxys do not clean up properly if they throw an exception. This method ensures that the service
/// proxy is handeled correctly. Do not call TService.Close() or TService.Abort() within the action lambda.
/// </summary>
/// <typeparam name="TService">The type of the service to use</typeparam>
/// <param name="action">Lambda of the action to performwith the service</param>
[System.Diagnostics.DebuggerStepThrough]
public static void UsingProxy<TService>(Action<TService> action)
where TService : ICommunicationObject, IDisposable, new()
{
var service = new TService();
bool success = false;
try
{
action(service);
if (service.State != CommunicationState.Faulted)
{
service.Close();
success = true;
}
}
finally
{
if (!success)
{
service.Abort();
}
}
}
/// <summary>
/// WCF proxys do not clean up properly if they throw an exception. This method ensures that the service
/// proxy is handeled correctly. Do not call TService.Close() or TService.Abort() within the action lambda.
/// </summary>
/// <typeparam name="TIServiceContract">The type of the service contract to use</typeparam>
/// <param name="action">Action to perform with the client instance.</param>
/// <remarks>In the configuration, an endpoint with names that maches the <typeparamref name="TIServiceContract"/> name
/// must exists. Otherwise, use <see cref="UsingContract<TIServiceContract>(string endpointName, Action<TIServiceContract> action)"/>. </remarks>
[System.Diagnostics.DebuggerStepThrough]
public static void UsingContract<TIServiceContract>(Action<TIServiceContract> action)
{
UsingContract<TIServiceContract>(
typeof(TIServiceContract).Name,
action
);
}
/// <summary>
/// WCF proxys do not clean up properly if they throw an exception. This method ensures that the service
/// proxy is handeled correctly. Do not call TService.Close() or TService.Abort() within the action lambda.
/// </summary>
/// <typeparam name="TIServiceContract">The type of the service contract to use</typeparam>
/// <param name="action">Action to perform with the client instance.</param>
/// <param name="endpointName">Name of the endpoint to use</param>
[System.Diagnostics.DebuggerStepThrough]
public static void UsingContract<TIServiceContract>(
string endpointName,
Action<TIServiceContract> action)
{
var cf = new ChannelFactory<TIServiceContract>(endpointName);
var channel = cf.CreateChannel();
var clientChannel = (IClientChannel)channel;
bool success = false;
try
{
action(channel);
if (clientChannel.State != CommunicationState.Faulted)
{
clientChannel.Close();
success = true;
}
}
finally
{
if (!success) clientChannel.Abort();
}
}
}
}
Then you can simply do something like this (depending if you have a service reference or the contracts :
ServiceHelper.UsingContract<IFxCurveService>(svc=>
{
guid = svc.ReserveSnapshot(fxCurveKey);
DiscountFactorNew[] dfs = svc.GetDiscountFactors(guid, dates, from));
Assert.IsTrue(guid != null);
}),
This helpers ensure the correct closing of channels, whithout disposing it. You will be able to see the actual exception then. Edit your post when you'll find the actual exception.
(Maybe your service factory is already using this technique. If not, do not hesitate to update it like my class).
[edit] You still have to play with config. here is a probably working config for you :
contract="The.Correct.Namespace.IFxCurveService"
name="IFxCurveService" />
I am using 4.0 and i have configured it like as follow:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="defaultBasicHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None"/>
<!--<message clientCredentialType="Certificate" algorithmSuite="Default" />-->
</security>
</binding>
</webHttpBinding>
</bindings>
<client>
<endpoint address="https://abc1234.abc.nsroot.net/MyService/MyService.svc"
binding="webHttpBinding"
bindingConfiguration="defaultBasicHttpBinding"
contract="IMyService"
name="TestJeph"/>
</client>
</system.serviceModel>
FYI: I am calling the WCF Rest service, does it matter?
the following is my service interface that i have created in the web app solution:
namespace anothertest
{
using System;
using System.ServiceModel;
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName = "IMyService")]
public interface IMyService
{
[OperationContract]
test.WebService.Entity.BusinessEntity[] GetAllActiveBusiness();
}
public class ProductClient : ClientBase<IMyService>, IMyService
{
#region Members
public test.WebService.Entity.BusinessEntity[] GetAllActiveBusiness()
{
return Channel.GetAllActiveBusiness();
}
#endregion
}
}
the following is the code to call the service:
anothertest.Utility.ServiceHelper.UsingContract<anothertest.IMyService>
("TestJeph",
svc=>
{
string test = svc.UpdateCMPStatus("test", "me");
});
Are you targeting .Net 3.5 or .Net 4.0 ? In .Net 4.0 you get lots of defaults for the configuration of the service. In .Net 3.5 you are going to have to configure the endpoint completely in either in the App.config or programatically. For example what binding is the enpoint using ? If you are using .Net 4.0 then you are going to get a BasicHttpBinding by default since you specified an http uri. In .Net 3.5 you are going to fault as there will be no binding configured.

Adding a WCF Service Reference falls back to XmlSerializer

We are consuming an ASMX service by adding a WCF "Service Reference" to our project. When we do this, by default it is supposed to use the DataContractSerializer and if something goes wrong, it will fall back to the XmlSerializer.
I've tried forcing the DataContractSerializer when generating the proxy classes, but when I do that, they are incomplete and missing all of the custom classes used by the webservice (leaving only the interface for the Soap, SoapChannel, and the SoapClient class).
Well, something is going wrong and it is falling back to the use the XmlSerializer. I do not see any errors or warnings when I generate the reference.
How can I find out what is causing the DataContractSerializer to fail and fall back to the XmlSerializer?
Long story short is that we were unable to force VS to use the DataContractSerializer. Instead we ended up writing our own WCF Service Contracts that represented the webservice. When we consume the service we are instead creating the ChannelFactory generically by using our OWN Service Contracts. Below is the code that we used to create the channel.
/// <summary>
/// A generic webservice client that uses BasicHttpBinding
/// </summary>
/// <remarks>Adopted from: http://blog.bodurov.com/Create-a-WCF-Client-for-ASMX-Web-Service-Without-Using-Web-Proxy/
/// </remarks>
/// <typeparam name="T"></typeparam>
public class WebServiceClient<T> : IDisposable
{
private readonly T channel;
private readonly IClientChannel clientChannel;
/// <summary>
/// Use action to change some of the connection properties before creating the channel
/// </summary>
public WebServiceClient(string endpointUrl, string bindingConfigurationName)
{
BasicHttpBinding binding = new BasicHttpBinding(bindingConfigurationName);
EndpointAddress address = new EndpointAddress(endpointUrl);
ChannelFactory<T> factory = new ChannelFactory<T>(binding, address);
this.clientChannel = (IClientChannel)factory.CreateChannel();
this.channel = (T)this.clientChannel;
}
/// <summary>
/// Use this property to call service methods
/// </summary>
public T Channel
{
get { return this.channel; }
}
/// <summary>
/// Use this porperty when working with Session or Cookies
/// </summary>
public IClientChannel ClientChannel
{
get { return this.clientChannel; }
}
public void Dispose()
{
this.clientChannel.Dispose();
}
}

Categories