I need help converting the following netTcpBinding to an equivalent CustomBinding:
<bindings>
<netTcpBinding>
<binding name="secureNetTcp" openTimeout="00:00:25" closeTimeout="00:00:27" receiveTimeout="00:10:10" sendTimeout="00:01:00"
listenBacklog="50" maxBufferPoolSize="2097152" maxBufferSize="2097152" maxConnections="50" maxReceivedMessageSize="2097152">
<readerQuotas maxArrayLength="2097152" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="true" />
<security mode="TransportWithMessageCredential">
<message algorithmSuite="Basic256Sha256" />
</security>
</binding>
</netTcpBinding>
</bindings>
I'm mostly struggeling with the Security part of the custom binding, because I can't fathom all the different settings. And everything seems to be named differently as well (compared to netTcpBinding parameters).
In case it's necessary I'll provide the following information as well:
The service endpoint has a certificate attached to it via serviceBehavior.
In my code I provide a username/password when creating the proxy (service behavior has <userNameAuthentication userNamePasswordValidationMode="Windows" /> under serviceCredentials; For the netTcpBinding the WCF configuration editor shows ClientCredentialType=Windows, which I guess is the default value).
Update:
I have found a potential solution for my main problem - increasing ChannelInitilizationTimeout - without having to create a CustomBinding. I'll share this, incase someone stumbels upon this thread while googeling...
What I did was create a custom class that inherits from NetTcpBinding and in it's constructor used reflection to set the ChannelInitilizationTimeout property. Thus maintaining full compatibility with NetTcpBinding.
Here is the code for my custom class:
public class MyNetTcpBinding : NetTcpBinding
{
public MyNetTcpBinding()
{
var fi = typeof(NetTcpBinding).GetField("transport", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var val = (System.ServiceModel.Channels.TcpTransportBindingElement)fi.GetValue(this);
val.ChannelInitializationTimeout = TimeSpan.FromSeconds(10);
}
}
public class MyBindingElement : NetTcpBindingElement
{
protected override Type BindingElementType
{
get { return typeof(MyNetTcpBinding); }
}
}
public class MyBindingElementCollection : StandardBindingCollectionElement<MyNetTcpBinding, MyBindingElement>
{
}
After compiling this class (I created a seperate DLL project for this class), I used WCF configuration editor (under left pane "Configuration" -> Advanced -> Extensions -> binding extensions -> new -> give a name, eg. "MyNetTcp" and point to the dll file) to add my class as an extension to bindings.
Afterwards in WCF app.config just replace netTcpBinding with MyNetTcp (there are three references in total; one in <service><endpoint binding="netTcpBinding"></endpoint></service>; the other two are xml tags under <bindings><netTcpBinding></netTcpBinding></bindings>).
I will leave this question open in case someone wants to give a proper answer to the original question...
You can pass in the netTcpBinding into a custom binding and do the following.
There is no guarantee that reflection will work across versions.
http://blogs.msdn.com/b/sajay/archive/2010/01/29/how-to-create-a-custom-binding-from-a-standardbinding.aspx
Related
So, I noticed FaultException is not giving me the proper result when I use the BasicHttpBinding. When I use WSHttpBinding it works file.
The issue is, From WCF Service if I throw the FaultException like below,
var translations = new List<FaultReasonText> { new FaultReasonText("FaultReasonText 1"), new FaultReasonText("FaultReasonText 2") };
throw new FaultException<MessageServiceFault>(MessageServiceFault.Fault1, new FaultReason(translations));
When it reaches to the client the fault.Reason.Translations count is 1. That means the first one (FaultReasonText 1) only is getting back to client.
But when I use WSHttpBinding the count is 2. Where the issue is? Can anyone help me on this.
It gives me different result when I test the below code with BasicHttpBinding & WSHttpBinding bindings.
class Program
{
static void Main(string[] args)
{
try
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(MessageService), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(IMessageService), new WSHttpBinding(), "");
host.Open();
Console.WriteLine("Host opened");
ChannelFactory<IMessageService> myChannelFactory = new ChannelFactory<IMessageService>(new WSHttpBinding(), new EndpointAddress(baseAddress));
IMessageService channel = myChannelFactory.CreateChannel();
var response = channel.GetMessage();
}
catch (FaultException fault)
{
fault.Reason.Translations.ToList().ForEach(i => Console.WriteLine(i.Text));
Console.WriteLine(false);
}
}
}
[ServiceContract]
public interface IMessageService
{
[OperationContract]
[FaultContract(typeof(MessageServiceFault))]
string GetMessage();
}
public class MessageService : IMessageService
{
public string GetMessage()
{
var translations = new List<FaultReasonText> { new FaultReasonText("FaultReasonText 1"), new FaultReasonText("FaultReasonText 2") };
throw new FaultException<MessageServiceFault>(MessageServiceFault.Fault1, new FaultReason(translations));
}
}
[DataContract]
public enum MessageServiceFault
{
[EnumMember]
Fault1,
[EnumMember]
Fault2
}
EDIT:
But, this article says, You can supply a number of different text strings that get picked from depending on the user's language settings. The Translations bucket holds all of the different text strings and their associated cultural identifiers (tied together by a FaultReasonText). When no culture is specified for a fault reason or a translation search, the assumed culture is the current thread culture. For example, if you want a translation to "en-UK", we'll first look for "en-UK" and then we'll look for "en". If we still can't find a match, then we'll take the first translation in the list, which could be anything.
If so, Why in case of WsHttpBinding it returns me the 2 FaultReasonText ?
To use FaultException, you need to activate SOAP 1.2 on your web service.
BasicHttpBinding uses SOAP 1.1, WSHttpBinding uses SOAP 1.2. That's why it works with WSHttpBinding and not with BasicHttpBinding.
Instead of using BasicHttpBinding, you should better use customBindings, with textMessageEncoding and httpTransport :
<customBinding>
<binding name="simpleBinding">
<textMessageEncoding messageVersion="Soap12" writeEncoding="utf-8" />
<httpTransport />
</binding>
</customBinding>
If you convert a default basicHttpBinding with this tool : you will obtain :
<!-- generated via Yaron Naveh's http://webservices20.blogspot.com/ -->
<customBinding>
<binding name="NewBinding0">
<textMessageEncoding MessageVersion="Soap11" />
<httpTransport />
</binding>
</customBinding>
<!-- generated via Yaron Naveh's http://webservices20.blogspot.com/ -->
Source binding :
<bindings>
<basicHttpBinding>
<binding name="NewBinding0" />
</basicHttpBinding>
</bindings>
Try to activate SOAP 12 to your service, and it will work
I've done some work using MSMQ with WCF and the NetMsmqBinding to generate messages and dequeue them as they arrive. I've also standardized my solution by using an object graph as the message body. This object contains meta data and an internal payload.
I'd like to construct an admin tool that can monitor queues and peek at the contents of messages. So far I've been unsuccessful figuring out how to deserialize the Message.Body back into the object graph using the System.Messaging libraries.
Any ideas?
Do you have any scope changing the WCF service bindings?
If you use MsmqIntegrationBinding rather than netMsmqBinding you have a range of formatter options you can specify in your binding. For example
<service name="MyQueueListenner">
<!-- Active X endpoint -->
<endpoint address="msmq.formatname:DIRECT=OS:.\private$\myQueue"
binding="msmqIntegrationBinding"
bindingConfiguration="ActiveXBinding"
contract="MyContract" />
<!-- .Net endpoint-->
<endpoint address="msmq.formatname:DIRECT=OS:.\private$\myOtherQueue"
binding="msmqIntegrationBinding"
bindingConfiguration="DotNetBinding"
contract="MyContract" />
</service>
...
<msmqIntegrationBinding>
<binding serializationFormat="ActiveX" name="ActiveXBinding" durable="false" exactlyOnce="false">
<security mode="None" />
</binding>
<binding serializationFormat="Xml" name="DotNetBinding" durable="false" exactlyOnce="false">
<security mode="None" />
</binding>
</msmqIntegrationBinding>
This allows you the full range of formatters providing the greatest range of interoperability with your System.Messaging based sniffer.
The full list of values is here:
http://msdn.microsoft.com/en-us/library/system.servicemodel.msmqintegration.msmqmessageserializationformat.aspx
i know this is old, but to serialize and back any object you can do the following:
//Sample
enter code here
public person class
{
public int Id {get;set;}
public string Name {get;set;}
public static person Desserialize(byte[] data)
{
person result = new person ();
using (MemoryStream m = new MemoryStream(data))
{
using (BinaryReader reader = new BinaryReader(m))
{
result.id = reader.ReadInt32();
result.Name = reader.ReadString();
}
}
return result;
}
public byte[] Serialize()
{
using (MemoryStream m = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(m))
{
writer.Write(id);
writer.Write(Name);
}
return m.ToArray();
}
}
// You can do
Byte[] w_byte = Person.serialize();
Person _Person = Person.Desiserile(w_byte);
}
Editing this to refocus on the actual issue. I've preserved the origional question at the bottom of the message but changing the title and content to reflect what was really happening.
I need to override the maxReceivedMessageSize for a WCF service added to an MVC3 project via the ServiceRoute mechanism. Specifing the binding in the web.config doesn't work. How does one do this.
Initial question is below this line but is misleading based on lots of false positives I was seeing.
Hi I have used some examples to add a file streaming upload service to my MVC3 project. If I use the default bindings (i.e., not defined in web.config) the service works as long as I don't exceed the 64k default size. When I try and define my own binding to increase the size I get a content-type mismatch in my trace and a HTTP415 Unsupported Media Type in the response. I'm trying to call this via fiddler via HTTP and am not using a WCF client.
Here is the error in the trace:
Content Type image/jpeg was sent to a service expecting multipart/related;type="application/xop+xml". The client and service bindings may be mismatched.
Here is the web.config service model section
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="NewBehavior0" />
</endpointBehaviors>
</behaviors>
<services>
<service name="AvyProViewer.FileService">
<endpoint address="UploadFile" binding="basicHttpBinding" bindingConfiguration=""
contract="AvyProViewer.FileService" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<bindings>
<basicHttpBinding>
<binding name="NewBinding0" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Mtom" transferMode="StreamedRequest">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
Here is the service:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class FileService
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "UploadFile")]
public string UploadFile(Stream fileStream)
{
string path = HostingEnvironment.MapPath("~");
string fileName = Guid.NewGuid().ToString() + ".jpg";
FileStream fileToupload = new FileStream(path + "\\FileUpload\\" + fileName, FileMode.Create);
byte[] bytearray = new byte[10000];
int bytesRead, totalBytesRead = 0;
do
{
bytesRead = fileStream.Read(bytearray, 0, bytearray.Length);
totalBytesRead += bytesRead;
} while (bytesRead > 0);
fileToupload.Write(bytearray, 0, bytearray.Length);
fileToupload.Close();
fileToupload.Dispose();
return fileName;
}
}
And here is where I expose it in my MVC3 routes:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new ServiceRoute("FileService", new WebServiceHostFactory(), typeof(FileService)));
. . .
}
I think the issue is with the mtom declaration for messageEncoding in your binding. Try changing messageEncoding to Text.
Answer ended up being a combination of three different stack overflow posts. None by themselves solved the question but each provided crucial clues as to what was happing.
It seems that if you add a ServiceRoute the web.config binding information is ignored. This SO post clued me in to what seems to be undocumented behavior of this function: Unable to set maxReceivedMessageSize through web.config
I then used this post to determine how to programatically override the maxreceivedmesssagesize for the binding: Specifying a WCF binding when using ServiceRoute.
Unfortunately the code form #2 didn't work out of the box (not sure if the binding behavior for ServiceRoute has changed or what makes the difference). Turns out that if you specify a ServiceRoute its automatically created as a CustomBinding which can't be cast to the WebHTTPBinding type used in #2. So this post: How to set the MaxReceivedMessageSize programatically when using a WCF Client? helped me determine how to change the code in #2 to add this capability to a custom binding.
I'm working on my first WCF service, which will support several Ajax calls. I have an endpoint configured this way:
<service behaviorConfiguration="ServiceBehavior" name="AQM">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="Binding1" contract="IAQM" />
</service>
and my behavior configuration:
<endpointBehaviors>
<behavior name="web">
<webHttp />
<enableWebScript />
</behavior>
</endpointBehaviors>
I need to create my own error handling so that I can format some specific information back to the client (see here http://zamd.net/2008/07/08/error-handling-with-webhttpbinding-for-ajaxjson/). My WebServiceHostFactory looks like this:
public class MyServiceFactory : WebServiceHostFactory
{
public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
{
var sh = new ServiceHost(typeof(AQM), baseAddresses);
sh.Description.Endpoints[0].Behaviors.Add(new WebHttpBehaviorEx());
return sh;
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return base.CreateServiceHost(serviceType, baseAddresses);
}
}
public class WebHttpBehaviorEx : WebHttpBehavior
{
protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
// Clear default error handlers
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear();
// Add our own error handler
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(new ErrorHandlerEx());
}
However, after I created my own error handler, it seems it overrides the "enableWebScript" setting I had in my config above, which I think makes sense because now I'm creating my very own behavior dynamically which doesn't have any of the config settings above.
I read that this setting should be used with WCF/Ajax for security purposes (see here http://www.asp.net/ajaxlibrary/Using%20JSON%20Syntax%20with%20Ajax.ashx). So my question is, how can I set the the "enableWebScript" setting on my dynamically created behavior? Or is it not possible?
Update (6/1/2011): I'm also looking to dynamically change the behavior to use Windows credentials for authentication. In the config file it's done like this:
<bindings>
<webHttpBinding>
<binding name="Binding1">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</webHttpBinding>
</bindings>
This is another setting I need to make programmatically since it seems to ignore the config setting.
For me it worked after adding the following constructor in WebHttpBehaviorEx
public WebHttpBehaviorEx()
{
DefaultBodyStyle = WebMessageBodyStyle.Wrapped;
DefaultOutgoingRequestFormat = WebMessageFormat.Json;
DefaultOutgoingResponseFormat = WebMessageFormat.Json;
}
There is a class WebScriptEnablingBehavior that you should be able to create in instance of programmatically and add it to the Behaviors collection of your endpoint. I've never tried it, and don't know how exactly that would work having multiple behaviors defined on a single endpoint, but I think that's basically what you're doing in your declarative configuration. Unfortunately WebScriptEnablingBehavior (which inherits from WebHttpBehavior) is sealed, so you can't just inherit from it.
Update: (from here)
The WebScriptEnablingBehavior is a "profile" of the WebHttpBehavior functionality designed specifically for interop with ASP.NET AJAX clients. It adds in some AJAX-isms like the ability to automatically generate ASP.NET AJAX client proxies.
I'm not sure you actually need to use <enableWebScript/>, like Carlos said, it sounds like it's only needed when you're using ASP.NET AJAX.
I have a net tcp WCF service as follows
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class AVService : IAVService
{
static int _numberofInst = 0;
public AVService()
{
++_numberofInst;
Console.WriteLine("Number of instances "+_numberofInst);
}
~AVService()
{
--_numberofInst;
Console.WriteLine("Number of instances " + _numberofInst);
}
public void Foo(){}
}
When I create an object on the client side as follows
AVService client = new AVService();
client.Foo();
The constructor is called, but when I close the client application without calling close mehotd, the destructor does not been called? why? does this mean the service object still works on the server?
Yes - if you don't explicitly dispose of your client, the server will "hang around" for a while (since you specified PerSession mode).
It will eventually time out (specified by the InactivityTimeout setting on the binding configuration), and will be destroyed. But that could take some time (several minutes to several hours, depending on your settings).
<bindings>
<netTcpBinding>
<binding name="NetTcp_Reliable" receiveTimeout="00:20:00">
<reliableSession enabled="true" ordered="false"
inactivityTimeout="00:15:00" />
</binding>
</netTcpBinding>
</bindings>
Therefore, it is the best practice to always dispose of your client before closing the app.