I thought over creation file storage with use WCF.I seach in Internet and find many examples and write his service:
namespace CTFileStorage
{
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
interface CTIFileStorageClass
{
[OperationContract]
CTFileName UploadStream(CTRemoteFileInfo faInfo);
}
[MessageContract]
public class CTRemoteFileInfo : IDisposable
{
[MessageHeader(MustUnderstand = true)]
public string FileName;
[MessageHeader(MustUnderstand = true)]
public long Length;
[MessageBodyMember(Order = 1)]
public System.IO.Stream FileByteStream;
public void Dispose()
{
if (FileByteStream != null)
{
FileByteStream.Close();
FileByteStream = null;
}
}
}
[MessageContract]
public class CTFileName
{
[MessageHeader(MustUnderstand = true)]
public string FileName;
}
public class CTFileStorageClass : CTIFileStorageClass
{
public CTFileName UploadStream(CTRemoteFileInfo faFileInfo)
{
try
{
Guid guid = Guid.NewGuid();
FileStream targetStream = null;
Stream sourceStream = faFileInfo.FileByteStream;
string uploadFolder = #"D:\Storage\";
string[] paths=faFileInfo.FileName.Split('.');
string path=null;
if (paths.Length>=2)
{
path="."+paths[paths.Length-1];
}
string filePath = Path.Combine(uploadFolder, guid.ToString()+path);
using (targetStream = new FileStream(filePath, FileMode.Create,
FileAccess.Write, FileShare.None))
{
//read from the input stream in 65000 byte chunks
const int bufferLen = 65000;
byte[] buffer = new byte[bufferLen];
int count = 0;
while ((count = sourceStream.Read(buffer, 0, bufferLen)) > 0)
{
// save to output stream
targetStream.Write(buffer, 0, count);
Thread.Sleep(10);
}
targetStream.Close();
sourceStream.Close();
}
CTFileName fileName = new CTFileName() { FileName = guid.ToString() };
return fileName;
}
catch
{
return null;
}
}
}
}
WCF hosted on windows service.app.config service:`
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="binding" openTimeout="04:00:00" sendTimeout="04:00:00" receiveTimeout="04:00:00" closeTimeout="04:00:00"
allowCookies="true" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Mtom" textEncoding="utf-8" transferMode="Streamed"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<!-- This section is optional with the new configuration model
introduced in .NET Framework 4. -->
<service name="CTFileStorage.CTFileStorageClass"
behaviorConfiguration="CalculatorServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/ServiceModelSamples/service"/>
</baseAddresses>
</host>
<!-- this endpoint is exposed at the base address provided by host: http://localhost:8000/ServiceModelSamples/service -->
<endpoint address=""
binding="basicHttpBinding" bindingConfiguration="binding"
contract="CTFileStorage.CTIFileStorageClass" />
<!-- the mex endpoint is exposed at http://localhost:8000/ServiceModelSamples/service/mex -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<serviceDebug includeExceptionDetailInFaults="False"/>
<serviceThrottling
maxConcurrentCalls="1000"
maxConcurrentSessions="1000"
maxConcurrentInstances="1000"
/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>`
For modeling load create client-console application:
static void Main(string[] args)
{
Thread thread = new Thread(new ParameterizedThreadStart(Copy));
thread.Start("D:\\toad10513\\toad10513.rar");
Thread thread1 = new Thread(new ParameterizedThreadStart(Copy));
thread1.Start("D:\\toad10513\\toad105131.rar");
Thread thread2 = new Thread(new ParameterizedThreadStart(Copy));
thread2.Start("D:\\toad10513\\toad105132.rar");
Thread thread3 = new Thread(new ParameterizedThreadStart(Copy));
thread3.Start("D:\\toad10513\\toad105133.rar");
Thread thread4 = new Thread(new ParameterizedThreadStart(Copy));
thread4.Start("D:\\toad10513\\toad105134.rar");
Thread thread5 = new Thread(new ParameterizedThreadStart(Copy));
thread5.Start("D:\\toad10513\\toad105135.rar");
}
private static void Copy(object faFile)
{
string s = faFile as string;
if (s != null)
{
StorageClient.Storage.CTIFileStorageClassClient client = new Storage.CTIFileStorageClassClient();
Stream sw = File.Open(s, FileMode.Open);
Console.WriteLine(faFile.ToString());
client.UploadStream(ref s, sw.Length, sw);
sw.Close();
}
}
}
}
This application upload in storage, In different threads files size 400 MB. If using one thread upload end good. But if start 6 threads, that work only 3 threads,others lag. And after any minutes work I get exception:"Connection socket failed".
Related
I have WCF service class 'MusicServiceManager' with the constructor that takes the parameter of IAppAmbientState. I need to pass parameter value to MusicServiceManager constructor at time initializing Service Host. I don't want singleton implementation for IAppAmbientState.
Service Contract
[ServiceContract]
public interface IAlbumService
{
[OperationContract]
string TestMessage();
[OperationContract]
IEnumerable<AlbumData> GetAlbums();
[OperationContract(Name = "GetAlbumByID")]
AlbumData GetAlbum(Guid ID);
[OperationContract(Name = "GetAlbumByName")]
AlbumData GetAlbum(string name);
}
AppAmbientState
public class AppAmbientState : IAppAmbientState
{
public IContainer ServiceContainer { get; }
public AppAmbientState(
IContainer container // autofac DIC container
)
{
ServiceContainer = container;
}
}
MusicServiceManager
public class MusicServicesManager : IAlbumService
{
private readonly IAppAmbientState _appAmbientState;
public MusicServicesManager(IAppAmbientState appAmbientState)
{
this._appAmbientState= appAmbientState;
}
public AlbumData GetAlbum(Guid ID)
{
throw new NotImplementedException();
}
Service Host Configuration Class
public class ServiceHostConfiguration : IServiceHostConfiguration
{
private readonly ServiceHost hostMusicServiceManager;
public ServiceHostConfiguration()
{
var container = ContainerConfiguration.Configure();
AppAmbientState AppAmbientStateInstance = new AppAmbientState(container);
// need help here... MusicServiceManager(AppAmbientStateInstance)????
// ideally I don't want to define my base address in class
this.hostMusicServiceManager = new ServiceHost(typeof(MusicServicesManager));
}
public void InitializeService()
{
try
{
this.hostMusicServiceManager.Open();
Console.WriteLine("App Web Services Started. Press [Enter] To Exit ");
}
catch(Exception exp)
{
Console.WriteLine("App Web Services Could Not Start:: ", exp);
}
}
public void CloseService()
{
this.hostMusicServiceManager.Close();
}
}
Autofac DI Container
public static class ContainerConfiguration
{
public static IContainer Configure()
{
var builder = new ContainerBuilder();
//Application Configuration
builder.RegisterType<Application>().As<IApplication>();
builder.RegisterType<ServiceHostConfiguration>().As<IServiceHostConfiguration>();
builder.RegisterType<AppAmbientState>().As<IAppAmbientState>();
builder.RegisterType<MusicServicesManager>().As<IAlbumService>();
Here is my Demo:
This is the project directory:
Program.cs:
using Autofac;
using Autofac.Integration.Wcf;
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace AutofacTest
{
class Program
{
static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Logger>().As<ILogger>();
builder.RegisterType<Service>();
using (IContainer container = builder.Build())
{
ServiceHost host = new ServiceHost(typeof(Service));
host.AddDependencyInjectionBehavior<Service>(container);
host.Open();
Console.WriteLine("The host has been opened.");
Console.ReadLine();
host.Close();
}
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
string Test();
}
public interface ILogger
{
}
public class Service : IService
{
private readonly ILogger logger;
public Service(ILogger logger)
{
this.logger = logger;
}
public string Test()
{
return "TEst1";
}
}
public class Logger : ILogger
{
}
}
App.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<system.serviceModel>
<services>
<service name="AutofacTest.Service">
<endpoint address="" binding="basicHttpBinding" contract="AutofacTest.IService" name="TestServiceEndPoint" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" name="TestServiceMexEndPoint" />
<host>
<baseAddresses>
<add baseAddress="http://localhost/TestService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.0.0" newVersion="5.2.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Feel free to let me know if the problem persists.
I have two post methods which return json result. one is update_existing_user able to access by client but another one submit_reg_data unable to access. I didn't understand why did the update_existing_user is accessed by client and submit_reg_data doesn't access by client. but I was tried access these two methods either from postman or from firefox httpRequester I got perfect result.
interface:
namespace MFAB
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IMFABService" in both code and config file together.
[ServiceContract]
public interface IMFABService
{
[WebInvoke(Method = "POST", UriTemplate = "/submit_reg_data",
ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
[OperationContract]
Stream submit_reg_data(RegisterProp objResterProperties);
[WebInvoke(Method = "POST", UriTemplate = "/update_existing_user",
ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
[OperationContract]
Stream update_existing_user(RegisterProp RegisterProperties);
}
}
class.svc---
namespace MFAB
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "MFABService" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select MFABService.svc or MFABService.svc.cs at the Solution Explorer and start debugging.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MFABService : IMFABService
{
Validation objValidation = new Validation();
static long intLeadRegisterID = 0;
public Stream update_existing_user(RegisterProp objRegisterProperties)
{
// RegisterProp objRegisterProperties = new RegisterProp();
// objRegisterProperties = JsonHelper.JsonDeserialize<RegisterProp>(RegisterProperties);
RegisterBO objRegisterBO = new RegisterBO();
//RegisterProp objRegisterProp = new RegisterProp();
DataSet dsDetails = new DataSet();
Dictionary<string, string> jsonDictionary = new Dictionary<string, string>();
if (objRegisterProperties.Citizenship <= 0)
{
jsonDictionary.Add("SubmissionStatus", "0");
jsonDictionary.Add("002", "citizenship is required");
return SendData(jsonDictionary);
}
if (objRegisterProperties.LeadRegisterID <= 0)
{
jsonDictionary.Add("SubmissionStatus", "0");
jsonDictionary.Add("002", "LeadRegisterID is required");
return SendData(jsonDictionary);
}
//DataSet objDS = objRegisterBO.VerifyCountryCity(objRegisterProperties);
//if (objDS != null && objDS.Tables[0].Rows.Count > 0 && Convert.ToBoolean(objDS.Tables[0].Rows[0]["Result"]))
//{
objRegisterProperties.LeadStatus = string.Empty;
jsonDictionary = objValidation.ValidateProperties(objRegisterProperties);
if (jsonDictionary.Count > 0)
{
jsonDictionary.Add("SubmissionStatus", "0");
return SendData(jsonDictionary);
}
else
{
//if (objRegisterProperties.DateofBirth.Year > 1900)
//{
objRegisterProperties.RegisterID = intLeadRegisterID;
objRegisterProperties.SPType = "R";
objRegisterProperties.EnteredDate = DateTime.Now;
if (Convert.ToBoolean(objRegisterProperties.FamMngBusiness))
{
objRegisterProperties.MngBusiness = true;
objRegisterProperties.OwnBusiness = false;
objRegisterProperties.OwnCompanyName = string.Empty;
objRegisterProperties.OwnAnnualRevenue = string.Empty;
objRegisterProperties.OwnOffWebsite = string.Empty;
objRegisterProperties.OwnRevCurrencyFormat = 0;
}
else
{
objRegisterProperties.MngBusiness = false;
if (Convert.ToBoolean(objRegisterProperties.FamOwnBusiness))
{
objRegisterProperties.OwnBusiness = true;
objRegisterProperties.FamMngOffWebsite = string.Empty;
objRegisterProperties.RevCurrencyFormat = 0;
objRegisterProperties.AnnualRevenue = string.Empty;
}
else
{
objRegisterProperties.OwnBusiness = false;
objRegisterProperties.OwnCompanyName = string.Empty;
objRegisterProperties.OwnAnnualRevenue = string.Empty;
objRegisterProperties.OwnOffWebsite = string.Empty;
objRegisterProperties.FamMngOffWebsite = string.Empty;
objRegisterProperties.OwnRevCurrencyFormat = 0;
objRegisterProperties.RevCurrencyFormat = 0;
objRegisterProperties.AnnualRevenue = string.Empty;
}
}
intLeadRegisterID = objRegisterBO.AddRegisterDetails(objRegisterProperties);
if ((intLeadRegisterID > 0))
{
jsonDictionary.Add("SubmissionStatus", "1");
return SendData(jsonDictionary);
}
else
{
return ErrorjsonResultData("SubmissionStatus", "0", "010", "Technical Exception");
}
//}
//else
//{
// return ErrorjsonResultData("SubmissionStatus", "0", "052", "Enter valid DateofBirth");
//}
}
//}
//else
//{
// return ErrorjsonResultData("SubmissionStatus", "0", "002", "Please select the city from the displayed options");
//}
}
public Stream submit_reg_data(RegisterProp objRegisterProperties)
{
//RegisterProp objRegisterProperties = new RegisterProp();
//objRegisterProperties = JsonHelper.JsonDeserialize<RegisterProp>(RegisterProperties);
RegisterBO objRegisterBO = new RegisterBO();
//RegisterProp objRegisterProp = new RegisterProp();
DataSet dsDetails = new DataSet();
bool chkStatus = true;
dsDetails = objRegisterBO.FetchRegisterDetailsByEmailIDs(objRegisterProperties);
if (!(dsDetails == null))
{
if ((dsDetails.Tables[0].Rows.Count > 0))
{
chkStatus = false;
}
}
if (chkStatus)
{
Dictionary<string, string> jsonDictionary = new Dictionary<string, string>();
//DataSet objDS = objRegisterBO.VerifyCountryCity(objRegisterProperties);
//if (objDS != null && objDS.Tables[0].Rows.Count > 0 && Convert.ToBoolean(objDS.Tables[0].Rows[0]["Result"]))
//{
objRegisterProperties.LeadStatus = string.Empty;
jsonDictionary.Add("SubmissionStatus", "0");
jsonDictionary = objValidation.ValidateProperties(objRegisterProperties);
if (jsonDictionary.Count > 0)
{
return SendData(jsonDictionary);
}
else
{
jsonDictionary.Clear();
//if (objRegisterProperties.DateofBirth.Year > 1900)
//{
objRegisterProperties.RegisterID = intLeadRegisterID;
objRegisterProperties.SPType = "R";
objRegisterProperties.EnteredDate = DateTime.Now;
if (Convert.ToBoolean(objRegisterProperties.FamMngBusiness))
{
objRegisterProperties.MngBusiness = true;
objRegisterProperties.OwnBusiness = false;
objRegisterProperties.OwnCompanyName = string.Empty;
objRegisterProperties.OwnAnnualRevenue = string.Empty;
objRegisterProperties.OwnOffWebsite = string.Empty;
objRegisterProperties.OwnRevCurrencyFormat = 0;
}
else
{
objRegisterProperties.MngBusiness = false;
if (Convert.ToBoolean(objRegisterProperties.FamOwnBusiness))
{
objRegisterProperties.OwnBusiness = true;
objRegisterProperties.FamMngOffWebsite = string.Empty;
objRegisterProperties.RevCurrencyFormat = 0;
objRegisterProperties.AnnualRevenue = string.Empty;
}
else
{
objRegisterProperties.OwnBusiness = false;
objRegisterProperties.OwnCompanyName = string.Empty;
objRegisterProperties.OwnAnnualRevenue = string.Empty;
objRegisterProperties.OwnOffWebsite = string.Empty;
objRegisterProperties.FamMngOffWebsite = string.Empty;
objRegisterProperties.OwnRevCurrencyFormat = 0;
objRegisterProperties.RevCurrencyFormat = 0;
objRegisterProperties.AnnualRevenue = string.Empty;
}
}
intLeadRegisterID = objRegisterBO.AddRegisterDetails(objRegisterProperties);
if ((intLeadRegisterID > 0))
{
jsonDictionary.Add("SubmissionStatus", "1");
jsonDictionary.Add("LeadRegisterId", intLeadRegisterID.ToString());
return SendData(jsonDictionary);
}
else
{
return ErrorjsonResultData("SubmissionStatus", "0", "010", "Technical Exception");
}
//}
//else
//{
// return ErrorjsonResultData("SubmissionStatus", "0", "052", "Enter valid DateofBirth");
//}
}
//}
//else
//{
// return ErrorjsonResultData("SubmissionStatus", "0", "003", "Please select the city from the displayed options");
//}
}
else
{
return ErrorjsonResultData("SubmissionStatus", "0", "003", "A record with this email or mobile number already exists!!");
}
}
}}
web.config file--->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<connectionStrings>
<add name="DBConnStr" connectionString="server=inhydxyxertt;database=xyztre;uid=sa;password=123tgr;" providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="AppYear" value="2014" />
<add key="ApplYear" value="2014-15" />
<!--<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />-->
</appSettings>
<system.web>
<compilation debug="false" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="webBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</webHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="MFAB.UserServiceBehavior" name="MFAB.MFABService">
<endpoint address="" behaviorConfiguration="MFAB.UserServiceBehavior" binding="webHttpBinding" bindingConfiguration="webBinding" contract="MFAB.IMFABService"/>
<!--<identity>
<dns value="localhost" />
</identity>-->
<!--<endpoint address="/Submit" behaviorConfiguration="MFAB.UserServiceBehavior" binding="webHttpBinding" bindingConfiguration="webBinding" contract="MFAB.IMFABService1"/>-->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="MFAB.UserServiceBehavior">
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MFAB.UserServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" minFreeMemoryPercentageToActivateService="0" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" showFlags="Date, Time, Size, Extension, LongDate" />
<defaultDocument>
<files>
<add value="MFABService.svc" />
</files>
</defaultDocument>
</system.webServer>
</configuration>
Global.aspx---
namespace MFAB
{
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add(new ServiceRoute("", new WebServiceHostFactory(), typeof(MFABService)));
}
protected void Session_Start(object sender, EventArgs e)
{
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();
EnableCrossDmainAjaxCall();
}
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
}
protected void Application_Error(object sender, EventArgs e)
{
}
protected void Session_End(object sender, EventArgs e)
{
}
protected void Application_End(object sender, EventArgs e)
{
}
private void EnableCrossDmainAjaxCall()
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin","*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods",
"GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers",
"Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age",
"1728000");
HttpContext.Current.Response.End();
}
}
}
}
any one can guide me how to enable SSL & Certificate in case WCF TCP binding. any idea.
var baseAddress = "localhost";
var factory = new DuplexChannelFactory<IMyWCFService>(new InstanceContext(SiteServer.Instance));
factory.Endpoint.Address = new EndpointAddress("net.tcp://{0}:8000/".Fmt(baseAddress));
var binding = new NetTcpBinding(SecurityMode.Message);
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
factory.Endpoint.Binding = binding;
var u = factory.Credentials.UserName;
u.UserName = userName;
u.Password = password;
return factory.CreateChannel();
thanks
MessageCredentialType is an enum. You can set MessageCredentialType.Certificate and set certificate credentials. You should look at documentation of MessageCredentialType enum where you can find example of setting certificate credentials.
I used this example to verify that it works. whole program looked like
using System;
using System.ServiceModel;
namespace ConsoleApplication2
{
[ServiceContract(Namespace = "http://UE.ServiceModel.Samples")]
public interface ICalculator
{
[OperationContract(IsOneWay = false)]
double Add(double n1, double n2);
[OperationContract(IsOneWay = false)]
double Subtract(double n1, double n2);
[OperationContract(IsOneWay = false)]
double Multiply(double n1, double n2);
[OperationContract(IsOneWay = false)]
double Divide(double n1, double n2);
}
public class CalculatorService : ICalculator
{
public double Add(double n1, double n2)
{
double result = n1 + n2;
Console.WriteLine("Received Add({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Subtract(double n1, double n2)
{
double result = n1 - n2;
Console.WriteLine("Received Subtract({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Multiply(double n1, double n2)
{
double result = n1 * n2;
Console.WriteLine("Received Multiply({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Divide(double n1, double n2)
{
double result = n1 / n2;
Console.WriteLine("Received Divide({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
}
public class Client : ClientBase<ICalculator>, ICalculator
{
public double Add(double n1, double n2)
{
return base.Channel.Add(n1, n2);
}
public double Subtract(double n1, double n2)
{
throw new NotImplementedException();
}
public double Multiply(double n1, double n2)
{
throw new NotImplementedException();
}
public double Divide(double n1, double n2)
{
throw new NotImplementedException();
}
}
internal class Program
{
private static void Main(string[] args)
{
ServiceHost myServiceHost = new ServiceHost(typeof(CalculatorService));
// Open the ServiceHostBase to create listeners and start listening for messages.
myServiceHost.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Client c = new Client();
var res = c.Add(1, 2);
Console.ReadLine();
}
}
}
My configuration file looked like this
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<client>
<endpoint address="net.tcp://localhost:8000/servicemodelsamples/service/calc" binding="netTcpBinding" contract="ConsoleApplication2.ICalculator" behaviorConfiguration="net" >
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
</client>
<services>
<service name="ConsoleApplication2.CalculatorService" behaviorConfiguration="service">
<endpoint address="net.tcp://localhost:8000/servicemodelsamples/service/calc" binding="netTcpBinding" contract="ConsoleApplication2.ICalculator" >
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8000/servicemodelsamples/service" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<netTcpBinding>
<binding>
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="service">
<serviceCredentials>
<serviceCertificate findValue="localhost" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="net">
<clientCredentials>
<clientCertificate findValue="localhost" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
It worked for me.
Server code
public class SIIUnzipDecodeService : ISIIUnzipDecodeService
{
//Upload the large data file
public void UploadFile(RemoteFileInfo request)
{
FileStream targetStream = null;
Stream sourceStream = request.FileByteStream;
string uploadFolder = #"C:\upload\";
string filePath = #"C:\upload\1GB.zip";
//Path.Combine(uploadFolder, request.FileName);
using (targetStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
//read from the input stream in 6K chunks
//and save to output stream
const int bufferLen = 65000;
byte[] buffer = new byte[bufferLen];
int count = 0;
while ((count = sourceStream.Read(buffer, 0, bufferLen)) > 0)
{
targetStream.Write(buffer, 0, count);
}
targetStream.Close();
sourceStream.Close();
}
}
Interface.
[ServiceContract]
public interface ISIIUnzipDecodeService
{
[OperationContract]
void UnzipAndDecode(MemoryStream fileContent);
[OperationContract]
RemoteFileInfo DownloadFile(DownloadRequest request);
[OperationContract]
void UploadFile(RemoteFileInfo request);
}
[MessageContract]
public class DownloadRequest
{
[MessageBodyMember]
public string FileName;
}
[MessageContract]
public class RemoteFileInfo : IDisposable
{
[MessageHeader(MustUnderstand = true)]
public string FileName;
[MessageHeader(MustUnderstand = true)]
public long Length;
[MessageBodyMember(Order = 1)]
public System.IO.Stream FileByteStream;
public void Dispose()
{
if (FileByteStream != null)
{
FileByteStream.Close();
FileByteStream = null;
}
}
}
Can you try enable Tracing on your service. Also please post your service configuration. Make sure that you have set the below things in your service configuration:
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<basicHttpBinding>
<binding transferMode="Buffered"/>
</basicHttpBinding>
<basicHttpBinding>
<binding closeTimeout="00:30:00"
openTimeout="00:30:00" receiveTimeout="00:30:00" sendTimeout="00:30:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Text" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
Have been reading around on IErrorHandler and want to go the config route.
so, I have read the following in an attempt to implement it.
MSDN
Keyvan Nayyeri blog about the type defintion
Rory Primrose Blog
This is basically just the msdn example wrapped in a class that inherits IErrorHandler and IServiceBehaviour ... then this is wrapped in the Extension element that inherits from BehaviourExtensionElement to allegedly allow me to add the element into the web.config. What have i missed?
I have got it to compile and from the various errors i have fixed it seems like WCF is actually loading the error handler. My problem is that the exception that i am throwing to handle in the error handler doesn;t get the exception passed to it.
My service implementation simply calls a method on another class that throws ArgumentOutOfRangeException - however this exception never gets handled by the handler.
My web.config
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basic">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<extensions>
<behaviorExtensions>
<add name="customHttpBehavior"
type="ErrorHandlerTest.ErrorHandlerElement, ErrorHandlerTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<behavior name="exceptionHandlerBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
<customHttpBehavior />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="exceptionHandlerBehaviour" name="ErrorHandlerTest.Service1">
<endpoint binding="basicHttpBinding" bindingConfiguration="basic" contract="ErrorHandlerTest.IService1" />
</service>
</services>
Service Contract
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(GeneralInternalFault))]
string GetData(int value);
}
The ErrorHandler class
public class ErrorHandler : IErrorHandler , IServiceBehavior
{
public bool HandleError(Exception error)
{
Console.WriteLine("caught exception {0}:",error.Message );
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
if (fault!=null )
{
if (error is ArgumentOutOfRangeException )
{
var fe = new FaultException<GeneralInternalFault>(new GeneralInternalFault("general internal fault."));
MessageFault mf = fe.CreateMessageFault();
fault = Message.CreateMessage(version, mf, fe.Action);
}
else
{
var fe = new FaultException<GeneralInternalFault>(new GeneralInternalFault(" the other general internal fault."));
MessageFault mf = fe.CreateMessageFault();
fault = Message.CreateMessage(version, mf, fe.Action);
}
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandler = new ErrorHandler();
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
if (channelDispatcher != null)
{
channelDispatcher.ErrorHandlers.Add(errorHandler);
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
And the Behaviour Extension Element
public class ErrorHandlerElement : BehaviorExtensionElement
{
protected override object CreateBehavior()
{
return new ErrorHandler();
}
public override Type BehaviorType
{
get { return typeof(ErrorHandler); }
}
}
Here's a full working example:
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(MyFault))]
string GetData(int value);
}
[DataContract]
public class MyFault
{
}
public class Service1 : IService1
{
public string GetData(int value)
{
throw new Exception("error");
}
}
public class MyErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
{
var vfc = new MyFault();
var fe = new FaultException<MyFault>(vfc);
var fault = fe.CreateMessageFault();
msg = Message.CreateMessage(version, fault, "http://ns");
}
}
public class ErrorHandlerExtension : BehaviorExtensionElement, IServiceBehavior
{
public override Type BehaviorType
{
get { return GetType(); }
}
protected override object CreateBehavior()
{
return this;
}
private IErrorHandler GetInstance()
{
return new MyErrorHandler();
}
void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandlerInstance = GetInstance();
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
dispatcher.ErrorHandlers.Add(errorHandlerInstance);
}
}
void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
{
if (endpoint.Contract.Name.Equals("IMetadataExchange") &&
endpoint.Contract.Namespace.Equals("http://schemas.microsoft.com/2006/04/mex"))
continue;
foreach (OperationDescription description in endpoint.Contract.Operations)
{
if (description.Faults.Count == 0)
{
throw new InvalidOperationException("FaultContractAttribute not found on this method");
}
}
}
}
}
and web.config:
<system.serviceModel>
<services>
<service name="ToDD.Service1">
<endpoint address=""
binding="basicHttpBinding"
contract="ToDD.IService1" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<errorHandler />
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="errorHandler"
type="ToDD.ErrorHandlerExtension, ToDD, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
You can see if the web.config is working and loading by adding a print or a breakpoint to the ApplyDispatchBehavior, and see if that gets printed/hit when the service first opens. So is it being loaded?
I'd add a print/breakpoint at ProvideFault, as well.