The issue is when wcf service is sending the list of class objects to client, the values are null. Any help or guidance is appreciated.
My service interface is
IPswdService.cs
namespace GetPasswordsSvc
{
[ServiceContract]
public interface IPswdService
{
[OperationContract]
List<dbVal> GetData(int value);
}
[DataContract]
public class dbVal
{
public string Group;
public string Title;
public string Username;
} ;
}
GetPasswords.svc.cs
namespace GetPasswordsSvc
{
public class PswdService : IPswdService
{
public List<dbVal> GetData(int value)
{
List<dbVal> kpdata= (from entry in db.RootGroup.GetEntries(true)
select new dbVal
{
Group = entry.ParentGroup.Name,
Title = entry.Strings.ReadSafe("Title"),
Username = entry.Strings.ReadSafe("UserName"),
}).ToList();
List<dbVal> l = kpdata.ToList();
return l;
}
======================================
WCF Client code
SvcRef.PswdServiceClient wcfClient = new SvcRef.PswdServiceClient();
wcfClient.Open();
List<GetPasswords.dbVal> dbValues = wcfClient.GetData(0);
==============================================
The client config file is
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IPswdService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://xxxxxxx:444/GetPasswords.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IPswdService" contract="SvcRef.IPswdService"
name="BasicHttpBinding_IPswdService" />
</client>
</system.serviceModel>
Hard to tell exactly what the cause is, but jus glancing at your service data contract, I can see that you've missed out the DataMember attribute on your data contarct fields, your data contract should be:
[DataContract]
public class dbVal
{
[DataMember]
public string Group;
[DataMember]
public string Title;
[DataMember]
public string Username;
}
Related
I have written an ajax function & WCF class for uploading files to a folder in a server, but unfortunately images are getting uploaded to the folder but aren't opening. When I try to open them they give an error that its corrupt , same thing happens when i upload .doc, pdf or .excel files.
But works fine with .txt files only.
This is my WCF Interface class
[ServiceContract]
public interface IFileUpload
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "Upload/{fileName}")]
String UploadFile(String fileName, Stream data);
Implementation of the class
public class FileUpload : IFileUpload
{
public String UploadFile(String fileName, Stream streamData)
{
String fileId = fileName;
Logger.Info("file Name" + fileName);
string FilePath = Path.Combine(HostingEnvironment.MapPath("~/Uploads"), fileName);
Logger.Info("file path" + FilePath);
int length = 0;
using (FileStream writer = new FileStream(FilePath,
FileMode.Create))
{
int readCount;
var buffer = new byte[8192];
while ((readCount = streamData.Read(buffer, 0, buffer.Length)) != 0)
{
writer.Write(buffer, 0, readCount);
length += readCount;
}
streamData.Close();
}
return "fileId";
}
Ajax function for file submission from UI
$.ajax({
url: fileUpload + $scope.filename,
method: "POST",
cache: false,
data: data,
contentType: "application/octet-stream",
enctype: 'multipart/form-data',
processData: false
}).success(function (response) {
document.getElementById('file2').value = "";
console.log("File uploaded successfully");
}).error(function (xhr, rrr, error) {
console.log("Error while uploading the file: - " + error);
})
The Web.config script binding configuration
<bindings>
<webHttpBinding>
<binding name="webBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
<binding name="FileWorker.webHttpBinding" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647" transferMode="Streamed">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
<binding name="webBindingHTTPS" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="Transport">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
<bindings>
I have researched everywhere but nothing seems to work
I have WCF service hosted in SharePoint that works fine some time ago, but it doesn't work now and I don't understand why it happened. I try post file to the service and get error 400(badrequest) if file less 16Kb no errors. I change my config file so
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IDocumentSetService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/_vti_bin/documentset.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IDocumentSetService" contract="Sitronics.AFK.BoD.SharePoint.Services.Services.IDocumentSetService" name="BasicHttpBinding_IDocumentSetService" />
</client>
</system.serviceModel>
I need modify maxArrayLength on the server side, how can I do it? Service host configured in the following way
public class DocumentSetServiceFactory : MultipleBaseAddressBasicHttpBindingServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var sh = base.CreateServiceHost(serviceType, baseAddresses);
sh.Opening += sh_Opening;
return sh;
}
public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
{
var sh = base.CreateServiceHost(constructorString, baseAddresses);
sh.Opening += sh_Opening;
return sh;
}
void sh_Opening(object sender, EventArgs e)
{
var sh = (ServiceHostBase)sender;
LoggingService.LogDebug("DocumentServiceHost:Opening");
if (sh.Description != null)
{
LoggingService.LogDebug("DocumentServiceHost:Description is not null");
foreach (var endPoint in sh.Description.Endpoints)
{
LoggingService.LogDebug(string.Format("DocumentServiceHost:FOR ENDPOINT {0}", endPoint.Address));
var bec = endPoint.Binding.CreateBindingElements();
var transport = bec.Find<TransportBindingElement>();
if (transport != null)
{
LoggingService.LogDebug(string.Format("DocumentServiceHost:TRANSPORT {0}",transport.Scheme));
transport.MaxReceivedMessageSize = 5242880;
transport.MaxBufferPoolSize = 5242880;
}
}
}
}
}
I implemenented the following interface in my WCF Service
[ServiceContract]
public interface IPrepaidService
{
[OperationContract]
PrepaidSubscriberInfo GetSubscriberInfo(string ctn);
[OperationContractAttribute(AsyncPattern = true)]
IAsyncResult BeginGetSubscriberInfo(string ctn, AsyncCallback cb, object state);
PrepaidSubscriberInfo EndGetSubscriberInfo(IAsyncResult r);
}
this way
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class PrepaidService : IPrepaidService
{
public PrepaidSubscriberInfo GetSubscriberInfo(string ctn)
{
PrepaidSubscriberInfo result = null;
try
{
result = new PrepaidSubscriberInfo();
...
}
catch (Exception ex) { throw new Exception(ex.ToString(), ex); }
return result;
}
public IAsyncResult BeginGetSubscriberInfo(string ctn, AsyncCallback cb, object state)
{
Task<PrepaidSubscriberInfo> task = Task<PrepaidSubscriberInfo>.Factory.StartNew(_ => GetSubscriberInfo(ctn), state);
if (cb != null) task.ContinueWith(res => cb(task));
return task;
}
public PrepaidSubscriberInfo EndGetSubscriberInfo(IAsyncResult ar)
{
return ((Task<PrepaidSubscriberInfo>)ar).Result;
}
}
I generated the proxy and config file:
c:\temp>svcutil http://localhost/Service.svc /async
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="MetadataExchangeHttpBinding_IPrepaidService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="None">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/Service.svc"
binding="wsHttpBinding" bindingConfiguration="MetadataExchangeHttpBinding_IPrepaidService"
contract="IPrepaidService" name="MetadataExchangeHttpBinding_IPrepaidService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
I'm trying to call asynchronous methods on the WCF client this way
static void Main(string[] args)
{
ChannelFactory<IPrepaidServiceChannel> factory = new ChannelFactory<IPrepaidServiceChannel>("MetadataExchangeHttpBinding_IPrepaidService");
factory.Open();
IPrepaidServiceChannel channelClient = factory.CreateChannel();
IAsyncResult arAdd = channelClient.BeginGetSubscriberInfo("xxx", AddCallback, channelClient);
IAsyncResult arAdd2 = channelClient.BeginGetSubscriberInfo("xxx", AddCallback, channelClient);
IAsyncResult arAdd3 = channelClient.BeginGetSubscriberInfo("yyy", AddCallback, channelClient);
IAsyncResult arAdd4 = channelClient.BeginGetSubscriberInfo("yyy", AddCallback, channelClient);
Console.WriteLine("1");
Console.ReadKey();
}
static void AddCallback(IAsyncResult ar)
{
var result = ((IPrepaidService)ar.AsyncState).EndGetSubscriberInfo(ar);
Console.WriteLine("Result: {0}", result);
}
but the WCF client is always calling the GetSubscriberInfo() method on the WCF Service instead of its asynchronous version
BeginGetSubscriberInfo and EndGetSubscriberInfo. When I remove [OperationContract] PrepaidSubscriberInfo GetSubscriberInfo(string ctn);
the client calls asynchronous version.
Sorry guys for bad formatting but I couldn't manage with this UI
The client and service can perform/not perform async independently. The client calls async simply means from the client perspective the calls are async the service doesn't even have to support async
The service will prefer sync over async so if you want your service to be invoked async then remove the sync version from its version of the contract
Please help me!!!
I am trying to build an application which uses callbacks contracts.My app work fine both the client and the server on the same machine, but when i try to access the service from other machine i got an exception timeout(the operation din not complete within the allotted timeout).The client reads some values throw the service from the database which is on the server.I don't know where is my mistake.I have tried to put the client in a virtual machine, and the service(and database) on the real machine.
Here is my Server config file:
<binding name="TrainService" closeTimeout="00:02:00" openTimeout="00:02:00"
receiveTimeout="00:10:00" sendTimeout="00:02:00" bypassProxyOnLocal="false"
transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" />
<security mode="None">
<message clientCredentialType="None" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsDualHttpBinding>
<wsHttpBinding>
<binding name="WSHttpBinding_ITrainService" closeTimeout="00:02:00"
openTimeout="00:02:00" receiveTimeout="00:10:00" sendTimeout="00:02:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="None" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8732/Design_Time_Addresses/WCFandEFService/TrainService/"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ITrainService"
contract="TrainServiceRef.ITrainService" name="WSHttpBinding_ITrainService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="net.tcp://localhost:8080/TcpService" binding="netTcpBinding"
contract="TrainServiceRef.ITrainService" name="NetTcpBinding_ITrainService" />
<endpoint address="http://localhost:8082/InterlockingService/Host/line"
binding="wsDualHttpBinding" bindingConfiguration="LineService"
contract="InterlockingServiceReference.ILineService" name="LineService">
<identity>
<userPrincipalName value="Romina-PC\Romina" />
</identity>
</endpoint>
<endpoint address="http://localhost:8082/InterlockingService/Host/trains"
binding="wsDualHttpBinding" bindingConfiguration="TrainService"
contract="InterlockingServiceReference.ITrainService" name="TrainService">
<identity>
<userPrincipalName value="Romina-PC\Romina" />
</identity>
</endpoint>
</client>
</system.serviceModel>
My client config file:
-->
<binding name="TrainService" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="52428800" maxReceivedMessageSize="6553600"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="1638400"
maxBytesPerRead="4096" maxNameTableCharCount="1638400" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" />
<security mode="None">
<!--<message clientCredentialType="None" negotiateServiceCredential="true"
algorithmSuite="Default" />-->
</security>
</binding>
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8082/InterlockingService/Host/line"
binding="wsDualHttpBinding" bindingConfiguration="LineService"
contract="InterlockingServiceRef.ILineService" name="LineService">
<identity>
<userPrincipalName value="Romina-PC\Romina" />
</identity>
</endpoint>
<endpoint address="http://localhost:8082/InterlockingService/Host/trains"
binding="wsDualHttpBinding" bindingConfiguration="TrainService"
contract="InterlockingServiceRef.ITrainService" name="TrainService">
<identity>
<userPrincipalName value="Romina-PC\Romina" />
</identity>
</endpoint>
</client>
</system.serviceModel>
Thank you.
Those are the contracts: public interface ITrainServiceCallBack
{
[OperationContract (IsOneWay=true)]
void OnTrainChangeState(TrainData train);
}
//[ServiceContract(Name = "LineService", CallbackContract = typeof(ILineServiceCallBack))]
[ServiceContract(CallbackContract = typeof(ITrainServiceCallBack))]
public interface ITrainService
{
[OperationContract]
TrainData GetTrainData(string trainName);
[OperationContract]
bool ChangeTrainState_bool(ref TrainData train);
[OperationContract]
void ChangeTrainState(ref Trains_Detail train);
[OperationContract]
bool SubscribeToTrainChangeEvent();
[OperationContract]
bool UnSubscribeFromTrainChangeEvent();
[OperationContract]
TrainData TranslateTrainEntityToTrainData(Trains_Detail trainEntity);
[OperationContract]
IEnumerable<Trains_Detail> GetTrains();
[OperationContract]
IEnumerable<Trains_Detail> GetTrains_ByStation(int Statie_plecare, int Statie_sosire);
}
Method implementation:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Data;
namespace WCFandEFService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "ProductService" in both code and config file together.
//[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public partial class InterlockingService : ITrainService
{
static List<ITrainServiceCallBack> subscribers_train = new List<ITrainServiceCallBack>();
public bool TrainExists(string nrTren, InterlockingEntities database)
{
// Check to see whether the specified product exists in the database
int numTrain = (from t in database.Trains_Details
where string.Equals(t.Nr_tren, nrTren)
select t).Count();
return numTrain > 0;
}
public TrainData TranslateTrainEntityToTrainData(Trains_Detail trainEntity)
{
TrainData train = new TrainData();
train.nrTren=trainEntity.Nr_tren;
train.ora_Plecare= trainEntity.Ora_plecare;
train.ora_Sosire=trainEntity.Ora_sosire;
train.statie_Plecare=trainEntity.Statie_plecare;
train.statie_Sosire=trainEntity.Statie_sosire;
train.rang=trainEntity.Rang;
train.observatii=trainEntity.Observatii;
train.RowVersion=trainEntity.RowVersion;
return train;
}
#region ILineService Members
public IEnumerable<Trains_Detail> GetTrains()
{
InterlockingEntities context = new InterlockingEntities();
IEnumerable<Trains_Detail> result =
(from t in context.Trains_Details
//where l.Station == station
select t);
return result;
}
public IEnumerable<Trains_Detail> GetTrains_ByStation(int Statie_plecare,int Statie_sosire)
{
InterlockingEntities context = new InterlockingEntities();
IEnumerable<Trains_Detail> result =
(from t in context.Trains_Details
where t.Statie_plecare==Statie_plecare && t.Statie_sosire==Statie_sosire
select t);
return result;
}
public TrainData GetTrainData(string trainNr)
{
InterlockingEntities context = new InterlockingEntities();
Trains_Detail trainInDB =
(from t
in context.Trains_Details
where String.Compare(t.Nr_tren, trainNr) == 0
select t).FirstOrDefault();
if (trainInDB == null)
{
throw new Exception("No line cu numele " + trainInDB.Nr_tren);
}
context.Detach(trainInDB);
return TranslateTrainEntityToTrainData(trainInDB);
}
public bool ChangeTrainState_bool(ref TrainData train)
{
InterlockingEntities context = new InterlockingEntities();
String trainName = train.nrTren;
//int lineStation = line.station;
Trains_Detail trainInDB =
(from t
in context.Trains_Details
where String.Compare(t.Nr_tren, trainName) == 0
select t).FirstOrDefault();
if (trainInDB == null)
{
throw new Exception("No train cu numele " + trainInDB.Nr_tren);
}
context.Detach(trainInDB);
trainInDB.Nr_tren = train.nrTren;
trainInDB.Ora_plecare=train.ora_Plecare;
trainInDB.Ora_sosire=train.ora_Sosire;
trainInDB.Statie_plecare=train.statie_Plecare;
trainInDB.Statie_sosire=train.statie_Sosire;
trainInDB.Rang=train.rang;
trainInDB.RowVersion = train.RowVersion;
context.Attach(trainInDB);
context.ObjectStateManager.ChangeObjectState(trainInDB, System.Data.EntityState.Modified);
context.SaveChanges();
train.RowVersion = trainInDB.RowVersion;
context.Dispose();
raiseTrainChangeState(TranslateTrainEntityToTrainData(trainInDB));
return true;
}
public void ChangeTrainState(ref Trains_Detail train)
{
using (var context = new InterlockingEntities())
{
context.Attach(train);
context.ObjectStateManager.ChangeObjectState(train, EntityState.Modified);
context.SaveChanges();
}
}
}
public bool SubscribeToTrainChangeEvent()
{
try
{
ITrainServiceCallBack callback = OperationContext.Current.GetCallbackChannel<ITrainServiceCallBack>();
if (!subscribers_train.Contains(callback))
{
subscribers_train.Add(callback);
}
return true;
}
catch (Exception)
{
return false;
}
}
public bool UnSubscribeFromTrainChangeEvent()
{
try
{
ITrainServiceCallBack callback = OperationContext.Current.GetCallbackChannel<ITrainServiceCallBack>();
subscribers_train.Remove(callback);
return true;
}
catch (Exception)
{
return false;
}
}
#endregion
private void raiseTrainChangeState(TrainData train)
{
subscribers_train.AsParallel().ForAll(callback =>
{
if (((ICommunicationObject)callback).State == CommunicationState.Opened)
{
callback.OnTrainChangeState(train);
}
else
{
subscribers_train.Remove(callback);
}
});
}
}
}
The operation contract(s) in the Callback contract should be marked IsOneWay = true, and should return void - not all the operation contracts in the service.
Also, I had a similar problem using duplex contracts over NetTcpBinding. I resolved this by setting the OperationTimeout value on the proxy (in my case, to 5 minutes). I set it programatically by casting my channel to the IContextChannel interface on the client when creating the channel. You should probably be able to do the same in the client config file.
My code:
((IContextChannel)myChannel).OperationTimeout = new Timespan(0, 5, 0);
Your endpoint address in the client and the server specifies "localhost" as the machine name. If they're in different machines, the client won't be able to talk to the service. Try changing it to the actual machine name where the server is located.
Update: here's an example of a WSDualHttpBinding working with non-one-way operations on both contract and callback contract. WSDualHttpBinding does not require that operations on the callback contract to be one way. PollingDuplexHttpBinding (for Silverlight) does, but that's another story.
using System;
using System.IO;
using System.Reflection;
using System.ServiceModel;
using System.Threading;
public class StackOverflow_6216605_751090
{
[ServiceContract(CallbackContract = typeof(ITestCallback))]
public interface ITest
{
[OperationContract]
int Add(int x, int y);
[OperationContract]
void CallMe(int numberOfTimes);
}
[ServiceContract]
public interface ITestCallback
{
[OperationContract]
string Hello(string name);
}
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service : ITest
{
public int Add(int x, int y)
{
Console.WriteLine("In a Request/Reply operation on server: {0} + {1}", x, y);
return x + y;
}
public void CallMe(int numberOfTimes)
{
Console.WriteLine("In another request/reply operation on server, which will call the client.");
ITestCallback callback = OperationContext.Current.GetCallbackChannel<ITestCallback>();
ThreadPool.QueueUserWorkItem(delegate
{
for (int i = 0; i < numberOfTimes; i++)
{
Console.WriteLine("Received from client: {0}", callback.Hello("Server"));
}
});
}
}
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class ClientCallback : ITestCallback
{
static int count = 0;
public string Hello(string name)
{
Console.WriteLine("In a client operation, name = {0}", name);
return string.Format("[{0}] Hello, {1}", ++count, name);
}
}
static void PrintUsage()
{
string programName = Path.GetFileName(Assembly.GetEntryAssembly().CodeBase);
Console.WriteLine("Usage: {0} <options>", programName);
Console.WriteLine("Examples:");
Console.WriteLine(" Starting the server: {0} -server", programName);
Console.WriteLine(" Starting the client: {0} -client <serverMachineName>", programName);
}
public static void Main(string[] args)
{
if (args.Length < 1)
{
PrintUsage();
return;
}
if (args[0].Equals("-server", StringComparison.OrdinalIgnoreCase))
{
string serviceAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(serviceAddress));
host.AddServiceEndpoint(typeof(ITest), new WSDualHttpBinding(WSDualHttpSecurityMode.None), "");
host.Open();
Console.WriteLine("Host opened, press ENTER to close");
Console.ReadLine();
host.Close();
}
else if (args.Length > 1 && args[0].Equals("-client", StringComparison.OrdinalIgnoreCase))
{
string serviceAddress = "http://" + args[1] + ":8000/Service";
ClientCallback clientCallback = new ClientCallback();
DuplexChannelFactory<ITest> factory = new DuplexChannelFactory<ITest>(
clientCallback,
new WSDualHttpBinding(WSDualHttpSecurityMode.None),
new EndpointAddress(serviceAddress));
ITest proxy = factory.CreateChannel();
Console.WriteLine("Simple Request/Reply: {0}", proxy.Add(3, 4));
Console.WriteLine("Now calling an operation on the server which will cause callbacks");
proxy.CallMe(10);
Console.WriteLine("Press ENTER to close");
Console.ReadLine();
}
else
{
PrintUsage();
}
}
}
Check if you have marked your operation contract as one way. Its usual to get a timeout in dual http binding where people fail to mark the contract as one way.
[OperationContract(IsOneWay = true)]
EDIT
Please place the following line in the service contract's behavior.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
For our reference, consider posting your service contract structure and the operation contract's implementation.
I am experimenting with creating a proof of concept upload WCF service. I have found the following partly in blog posts around the net:
namespace GreenWebMediaService
{
[ServiceContract]
public interface IMediaServer
{
[OperationContract]
void UploadData(UploadFile data);
}
// Use a data contract as illustrated in the sample below
// to add composite types to service operations.
[DataContract]
public class UploadFile
{
public UploadFile() { }
[MessageHeader]
public string MetaData { get; set; }
[MessageBodyMember]
public Stream data { get; set; }
}
}
i start it (hosting in Visual Studio) and make a reference from a newly created windows forms application, this is my reference, from app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMediaServer" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00"
sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536" messageEncoding="Text"
textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192"
maxArrayLength="16384" maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:49689/MediaServer.svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IMediaServer"
contract="mediaServer.IMediaServer"
name="BasicHttpBinding_IMediaServer" />
</client>
</system.serviceModel>
</configuration>
when i make a instance of it and refer to it like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
IMediaServer mediaServer = new mediaServer.MediaServerClient();
UploadFile file = new UploadFile();
mediaServer.UploadData(null);
}
}
When i access the "file" variable, it only has a "file.ExtensionData" property whereas i would have expected to have access to the properties i made in my "UploadFile" class. What am i missing? I have tried to make a tick in the configure dialog in visual studio as i found this information in other threads, still no luck: see my dialog here: http://screencast.com/t/NzhhNzM3Y2Q (sorry i dont know how long screencast.com will keep this image)
You are combining a DataContract with MessageHeader and MessageBodyMember attributes. You should either use
DataContract, DataMember or
MessageContract, MessageHeader, MessageBodyMember,
not a combination of these. So your UploadFile declaration should look like this:
[DataContract]
public class UploadFile
{
[DataMember] public string MetaData { get; set; }
[DataMember] public Stream data { get; set; }
}
or like this:
[MessageContract]
public class UploadFile
{
[MessageHeader] public string MetaData { get; set; }
[MessageBodyMember] public Stream data { get; set; }
}
I see two problems in your code. The first problem is definition of DataContract. It is completely wrong. As Ronald already pointed you are combining DataContract and MessageContract. You have to use second Ronald's suggestion (first will not work):
[MessageContract]
public class UploadFileRequest // Good naming convention for message contracts
{
// Streaming over HTTP demands only single body member of type Stream
// any other data have to be passed as custom headers - that is the reason
// why mentioned data contract doesn't work.
[MessageHeader] public string MetaData { get; set; }
[MessageBodyMember] public Stream Data { get; set; }
}
Second problem is Stream as body member for your request. It is only possible when you use Streamed or StreamedRequest transfer mode on your BasicHttpBinding. This information has to be set on the client binding definition manually - it is not transfered in WSDL / metadata and it is not interoperable feature.