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
Related
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;
}
}
}
}
}
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;
}
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.
The code below suppose to run a self hosted with custom authentication WCF Service which needs to provide its services to a Silverlight 4 client (See code below).
The result is that the infamous clientaccesspolicy Security Error communication exception is thrown even though the clientaccesspolicy.xml is visible in browser and shows no SSL error. The clientaccesspolicy.xml breakpoint is not hit.
I realize I only need to specify the entry but I've tried
various games with the clientaccesspolicy.xml which didnt work.
Your help is appreciated
1) This is the app.config and code for the service:
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<system.serviceModel>
<client />
<bindings>
<basicHttpBinding>
<binding name="slBindingWithUserNamePassValidator">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
<webHttpBinding>
<binding name="capService" crossDomainScriptAccessEnabled="true">
<security mode="Transport" />
</binding>
<binding name="capServiceNoSSL" crossDomainScriptAccessEnabled="true">
<security mode="None" />
</binding>
</webHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="svcBehavior" name="WCF_Self_Hosted_UserName_Validator.Service1">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="capService" behaviorConfiguration="capServiceBehavior"
contract="WCF_Self_Hosted_UserName_Validator.ICAPService" />
<endpoint address="" binding="webHttpBinding" bindingConfiguration="capServiceNoSSL" behaviorConfiguration="capServiceBehavior"
contract="WCF_Self_Hosted_UserName_Validator.ICAPService" />
<endpoint address="MyCustomValidationService" binding="basicHttpBinding" bindingConfiguration="slBindingWithUserNamePassValidator"
contract="WCF_Self_Hosted_UserName_Validator.IService1">
</endpoint>
<host>
<baseAddresses>
<add baseAddress="https://(somesite):9999/" />
<add baseAddress="http://(somesite):9998/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="svcBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="capServiceBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>
The code for the service:
Using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.IdentityModel.Selectors;
using System.IO;
using System.ServiceModel.Web;
namespace WCF_Self_Hosted_UserName_Validator
{
class Program
{
static void Main(string[] args)
{
MyServiceHost host = new MyServiceHost(new Service1());
host.Open();
Console.WriteLine("Host open...");
Console.ReadLine();
}
}
public class MyServiceHost : ServiceHost
{
SecurityValidator _securityValidator = null;
public MyServiceHost(IService1 svc) : base(svc)
{
Credentials.UserNameAuthentication.UserNamePasswordValidationMode = System.ServiceModel.Security.UserNamePasswordValidationMode.Custom;
_securityValidator = new SecurityValidator();
Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = _securityValidator;
Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "my-fqdn-valid-cert.dot.something");
}
}
public class SecurityValidator : UserNamePasswordValidator
{
public SecurityValidator()
{
}
public override void Validate(string userName, string password)
{
try
{
if (userName != "1" && password != "1")
throw new FaultException("auth error");
}
catch (Exception ex)
{
throw ex;
}
}
}
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetPrivateInfo();
}
[ServiceContract]
public interface ICAPService
{
[OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
Stream GetClientAccessPolicy();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service1 : IService1, ICAPService
{
public string GetPrivateInfo()
{
return "Some info " + DateTime.Now.ToShortTimeString();
}
public System.IO.Stream GetClientAccessPolicy()
{
WebOperationContext ctx = new WebOperationContext(OperationContext.Current);
string txtCap = #"<?xml version=""1.0"" encoding=""utf-8"" ?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers=""*"">
<domain uri=""*""/>
<domain uri=""http://*""/>
<domain uri=""https://*""/>
</allow-from>
<grant-to>
<resource include-subpaths=""true"" path=""/""/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>";
WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
MemoryStream response = new MemoryStream(Encoding.UTF8.GetBytes(txtCap));
return response;
}
}
}
2) We have a CA signed SSL cert in the MY container of the LOCAL MACHINE and used netsh
netsh http add sslcert ipport=0.0.0.0:9999 certhash=aabbcc_thumbprint
appid={my_app_id_guid} clientcertnegotiation=enable
The above executes succesfully and the host loads properly and allows creating a new silverlight project.
3) The silverlight project is a just an new silveright project with add service reference and the following code:
namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
ServiceReference1.Service1Client c = new ServiceReference1.Service1Client();
c.ClientCredentials.UserName.UserName = "1";
c.ClientCredentials.UserName.Password = "1";
c.GetPrivateInfoCompleted += new EventHandler<ServiceReference1.GetPrivateInfoCompletedEventArgs>(c_GetPrivateInfoCompleted);
c.GetPrivateInfoAsync();
}
void c_GetPrivateInfoCompleted(object sender, ServiceReference1.GetPrivateInfoCompletedEventArgs e)
{
if (e.Error == null)
{
this.Content = new TextBlock() { Text = e.Result };
}
else
{
this.Content = new TextBlock() { Text = e.Error.GetBaseException().Message };
}
}
}
}
4) This is the ServiceReferences.ClientConfig generated
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="TransportWithMessageCredential" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://(TheAddress)/MyCustomValidationService"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" />
</client>
</system.serviceModel>
</configuration>
Blockquote
netsh http add sslcert ipport=0.0.0.0:9999 certhash=aabbcc_thumbprint appid={my_app_id_guid} clientcertnegotiation=enable
You've used the netsh with the clientcertnegotiation flag that means the server requires client certificate. When Silverlight calls the clientaccesspolicy, it does not send a client certificate, and that is why you get the exception.
If you don't need the client certificate remove this flag.
I'm not sure if SL is able to send a client certificate when fetching the clientaccesspolicy, but if your web page also access that site the browser should use the certificate you gave it. So yo ucan try adding a link to the secured site in your hosting html/aspx which will require you to select a certificate and then SL will use that certificate