WCF RIA Service timeout - c#

I have context like that:
[EnableClientAccess()]
public class MyRiaService : LinqToEntitiesDomainService<EntityFrameworkContext>
Using Silverlight client I am initiating heavy database operation wich takes more than 1 minute. As a result I am getting timeout exception:
Uncaught Error: Unhandled Error occured in Silverlight Application:
Submit operation failed. for HTTP request to https://localhost/MyProject/ClientBin/myservice.svc/binary has exceeded the allotted timeout. The time allotted to this operation may have been a portion of a longer timeout.
Stack Trace:
at System.Windows.Ria.OperationBase.Complete(Exception error)
at System.Windows.Ria.SubmitOperation.Complete(Exception error)
at System.Windows.Ria.DomainContext.CompleteSubmitChanges(IAsyncResult asyncResult)
at System.Windows.Ria.DomainContext.<>c_DisplayClassd.b_5(Object )
I would be happy to change send timeout there, but I don't know, how.
I've tried this:
((WebDomainClient<LibraryDomainContext.ILibraryDomainServiceContract>)this.DomainClient).ChannelFactory.Endpoint.Binding.SendTimeout = new TimeSpan(0, 5, 0);
But I don't have property DomainClient.

The timeout of the connection can be set on the client side on the endpoint of the domain service. But how to get hold of that? By creating an extension method for domain contexts:
public static class DomainServiceExtensions
{
/// <summary>
/// This method changes the send timeout for the specified
/// <see cref="DomainContext"/> to the specifified <see cref="TimeSpan"/>.
/// </summary>
/// <param name="domainContext">
/// The <see cref="DomainContext"/> that is to be modified.
/// </param>
/// <param name="newTimeout">The new timeout value.</param>
public static void ChangeTimeout(this DomainContext domainContext,
TimeSpan newTimeout)
{
// Try to get the channel factory property from the domain client
// of the domain context. In case that this property does not exist
// we throw an invalid operation exception.
var channelFactoryProperty = domainContext.DomainClient.GetType().GetProperty("ChannelFactory");
if(channelFactoryProperty == null)
{
throw new InvalidOperationException("The 'ChannelFactory' property on the DomainClient does not exist.");
}
// Now get the channel factory from the domain client and set the
// new timeout to the binding of the service endpoint.
var factory = (ChannelFactory)channelFactoryProperty.GetValue(domainContext.DomainClient, null);
factory.Endpoint.Binding.SendTimeout = newTimeout;
}
}
The interesting question is when this method will be invoked. Once the endpoint is in use, the timeout can no longer be changed. So set the timeout immediately after creating the domain context:
The DomainContext-class itself is sealed, but luckily the class is also marked as partial - as is the method OnCreated() that can be extended quite easily that way.
public partial class MyDomainContext
{
partial void OnCreated()
{
this.ChangeTimeout(new TimeSpan(0,10,0));
}
}
Pro Tipp: When implementing partial classes the namespaces of all parts of the class must be identical. The code listed here belongs to the client side project (e.g. with the namespace RIAServicesExample), the partial class shown above needs to reside in the server side namespace nonetheless (e.g. RIAServicesExample.Web).

Related

HttpContext.Current is null in an asynchronous Callback

Trying to access the HttpContext.Current in a method call back so can I modify a Session variable, however I receive the exception that HttpContext.Current is null. The callback method is fired asynchronously, when the _anAgent object triggers it.
I'm still unsure of the solution to this after viewing similar questions on SO.
A simplified version of my code looks like so:
public partial class Index : System.Web.UI.Page
protected void Page_Load()
{
// aCallback is an Action<string>, triggered when a callback is received
_anAgent = new WorkAgent(...,
aCallback: Callback);
...
HttpContext.Current.Session["str_var"] = _someStrVariable;
}
protected void SendData() // Called on button click
{
...
var some_str_variable = HttpContext.Current.Session["str_var"];
// The agent sends a message to another server and waits for a call back
// which triggers a method, asynchronously.
_anAgent.DispatchMessage(some_str_variable, some_string_event)
}
// This method is triggered by the _webAgent
protected void Callback(string aStr)
{
// ** This culprit throws the null exception **
HttpContext.Current.Session["str_var"] = aStr;
}
[WebMethod(EnableSession = true)]
public static string GetSessionVar()
{
return HttpContext.Current.Session["str_var"]
}
}
Not sure if necessary but my WorkAgent class looks like so:
public class WorkAgent
{
public Action<string> OnCallbackReceived { get; private set; }
public WorkAgent(...,
Action<string> aCallback = null)
{
...
OnCallbackReceived = aCallback;
}
...
// This method is triggered when a response is received from another server
public BackendReceived(...)
{
...
OnCallbackReceived(some_string);
}
}
What happens in the code:
Clicking a button calls the SendData() method, inside this the _webAgent dispatches a message to another server and waits for reply (in the mean time the user can still interact with this page and refer to the same SessionID). Once received it calls the BackendReceived() method which, back in the .aspx.cs page calls the Callback() method.
Question:
When the WorkAgent triggers the Callback() method it tries to access HttpContext.Current which is null. Why is that the case when if I continue on, ignoring the exception, I can still obtain the same SessionID and the Session variable using the ajax returned GetSessionVar() method.
Should I be enabling the aspNetCompatibilityEnabled setting?Should I be creating some sort of asynchronous module handler? Is this related to Integrated/Classic mode?
Here's a class-based solution that is working for simple cases so far in MVC5 (MVC6 supports a DI-based context).
using System.Threading;
using System.Web;
namespace SomeNamespace.Server.ServerCommon.Utility
{
/// <summary>
/// Preserve HttpContext.Current across async/await calls.
/// Usage: Set it at beginning of request and clear at end of request.
/// </summary>
static public class HttpContextProvider
{
/// <summary>
/// Property to help ensure a non-null HttpContext.Current.
/// Accessing the property will also set the original HttpContext.Current if it was null.
/// </summary>
static public HttpContext Current => HttpContext.Current ?? (HttpContext.Current = __httpContextAsyncLocal?.Value);
/// <summary>
/// MVC5 does not preserve HttpContext across async/await calls. This can be used as a fallback when it is null.
/// It is initialzed/cleared within BeginRequest()/EndRequest()
/// MVC6 may have resolved this issue since constructor DI can pass in an HttpContextAccessor.
/// </summary>
static private AsyncLocal<HttpContext> __httpContextAsyncLocal = new AsyncLocal<HttpContext>();
/// <summary>
/// Make the current HttpContext.Current available across async/await boundaries.
/// </summary>
static public void OnBeginRequest()
{
__httpContextAsyncLocal.Value = HttpContext.Current;
}
/// <summary>
/// Stops referencing the current httpcontext
/// </summary>
static public void OnEndRequest()
{
__httpContextAsyncLocal.Value = null;
}
}
}
To use it can hook in from Global.asax.cs:
public MvcApplication() // constructor
{
PreRequestHandlerExecute += new EventHandler(OnPreRequestHandlerExecute);
EndRequest += new EventHandler(OnEndRequest);
}
protected void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
HttpContextProvider.OnBeginRequest(); // preserves HttpContext.Current for use across async/await boundaries.
}
protected void OnEndRequest(object sender, EventArgs e)
{
HttpContextProvider.OnEndRequest();
}
Then can use this in place of HttpContext.Current:
HttpContextProvider.Current
There may be issues as I currently do not understand this related answer. Please comment.
Reference: AsyncLocal (requires .NET 4.6)
When using threads or an async function, HttpContext.Current is not available.
Try using:
HttpContext current;
if(HttpContext != null && HttpContext.Current != null)
{
current = HttpContext.Current;
}
else
{
current = this.CurrentContext;
//**OR** current = threadInstance.CurrentContext;
}
Once you set current with a proper instance, the rest of your code is independent, whether called from a thread or directly from a WebRequest.
Please see the following article for an explanation on why the Session variable is null, and possible work arounds
http://adventuresdotnet.blogspot.com/2010/10/httpcontextcurrent-and-threads-with.html
quoted from the from the article;
the current HttpContext is actually in thread-local storage, which explains why child threads don’t have access to it
And as a proposed work around the author says
pass a reference to it in your child thread. Include a reference to HttpContext in the “state” object of your callback method, and then you can store it to HttpContext.Current on that thread

Error when I use the Task-based Asynchronous Pattern in the client of duplex WCF service

I develop download manager application that consists of two parts: 1) Duplex WCF service that performs downloading and sends downloading status data to client in real-time. 2) WPF Client that receives downloading status data from the service and displays in DataGrid. In my duplex WCF service there is a callback interface
[ServiceContract(CallbackContract = typeof(IDownloadManagerServiceCalback))]
public interface IDownloadManagerServiceCalback
{
/// <summary>
/// Returns changed downloading status to client.
/// </summary>
/// <returns>Downloading which has changed status</returns>
[OperationContract(IsOneWay = true)]
void UpdateSelectedDownload(DownloadStatus p_SelectedDownload);
}
On the client side I implement this interface:
class CallbackHandler : IDownloadManagerServiceCallback
{
/// <summary>
/// "Download status changed" event.
/// </summary>
public event EventHandler<DownloadStatusChangedEventArgs> DownloadStatusChanged;
public async Task UpdateSelectedDownload(DownloadStatus p_UpdatedDownload)
{
await Task.Run(() =>
{
// If handler was subscribed to event:
if (DownloadStatusChanged != null)
{
DownloadStatus updatedDownload = p_UpdatedDownload;
DownloadStatusChangedEventArgs updatedDownloadArgs = new DownloadStatusChangedEventArgs();
updatedDownloadArgs.Download = updatedDownload;
DownloadStatusChanged(this, updatedDownloadArgs);
}
});
}
}
When I build the solution I have the following error (text of error message i translate from Russian to English because my Visual Studio 2013 is Russianize):
DownloadManager_Client.CallbackHandler doesn’t implement member "DownloadManager_Client.DownloadManager_ServiceReference.IDownloadManagerServiceCallback.UpdateSelectedDownload(DownloadManager_Client.DownloadManager_ServiceReference.DownloadStatus)". "DownloadManager_Client.CallbackHandler.UpdateSelectedDownload(DownloadManager_Client.DownloadManager_ServiceReference.DownloadStatus)" can’t be implemented "DownloadManager_Client.DownloadManager_ServiceReference.IDownloadManagerServiceCallback.UpdateSelectedDownload(DownloadManager_Client.DownloadManager_ServiceReference.DownloadStatus)", because it doesn’t contain appropriate returned “void” type.
Here DownloadManager_Client is the name of WPF client project, DownloadManager_ServiceReference is the name of service reference to WCF service in the client project. How can I correct this error?
The interface should be defined as returning Task not void since your implementation is an async method returning a Task.
EDIT: You are in a pickle because you want to use async which require a Task to be returned however your method is marked as IsOneWay = true - you can't have both. Either IsOneWay = false and keep the async nature or keep one-way but remove the async.
Example 1 - Async method
[ServiceContract(CallbackContract = typeof(IDownloadManagerServiceCalback))]
public interface IDownloadManagerServiceCalback
{
/// <summary>
/// Returns changed downloading status to client.
/// </summary>
/// <returns>Downloading which has changed status</returns>
[OperationContract(IsOneWay = false)]
Task UpdateSelectedDownload(DownloadStatus p_SelectedDownload);
}
Then keep your original implementation returning Task
Example 2 - One-way method
[ServiceContract(CallbackContract = typeof(IDownloadManagerServiceCalback))]
public interface IDownloadManagerServiceCalback
{
/// <summary>
/// Returns changed downloading status to client.
/// </summary>
/// <returns>Downloading which has changed status</returns>
[OperationContract(IsOneWay = true)]
void UpdateSelectedDownload(DownloadStatus p_SelectedDownload);
}
In your implementation remove any await; async; tasks.
General
Async WCF methods should return Task or Task < T >. The only time you have an async void is during an event handler which is not applicable here.
As a general rule with async methods - avoid async void like the plague because an exception thrown in a try catch inside such a method can not be caught by a regular try-catch. The only exception (no pun intended is during event handlers).
Async void methods have different error-handling semantics. When an exception is thrown out of an async Task or async Task method, that exception is captured and placed on the Task object. With async void methods, there is no Task object, so any exceptions thrown out of an async void method will be raised directly on the SynchronizationContext that was active when the async void method started. More...
Would you like to know more?
Best Practices in Asynchronous Programming

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.

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