FaultException is not working correct when using BasicHttpBinding - wcf

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

Related

Deserializing an object graph from MSMQ that was enqueued using WCF and NetMsmqBinding

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);
}

How to use ServiceRoutes while defining maxReceivedMessageSize for non-custom bindings in WCF

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.

WCF - how to set "enableWebScript" dynamically?

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.

unable to load wcf restful help page after changing transferMode to "Streamed"

In my project, a wcf restful service, which allow users to upload photos to the web service.
After changing config settings to allow large file upload. (add binding configuration, i.e. "TransferMode", "BufferSize", etc.)
All Operation contracts are all working as expected.
However, the service help page for the endpoint stopped working.
The help page comes back, once I remove the binding config setting on my endpoint
How can I fixed this?? where did i missed
thank you all
<bindings>
<webHttpBinding>
<!-- buffer: 64KB; max size: 64MB -->
<binding name="StreamedBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" transferMode="Streamed"
maxBufferPoolSize="67108864" maxBufferSize="65536" maxReceivedMessageSize="67108864">
</binding>
</webHttpBinding>
</bindings>
<service name="WCFRestFul.ApiRestful">
<endpoint address="" binding="webHttpBinding"
bindingConfiguration="StreamedBinding" bindingName="StreamedBinding"
contract="WCFRestFul.IApiRestful" behaviorConfiguration="web" />
</service>
Update:
I think it is not just because of the transfer mode, but maybe some other setting as well.
The service help page comes back once I remove the "bindingConfiguration" in the code above.
I have 2 endpoints. The other endpoint don't have the "bindingConfiguration", and the service help page works fine on that.
I definitely missed some thing here, maybe some thing simple.
any help will be greatly appreciated
I took carlosfigueira advice, painfully removed my config setting one at a time.
I changed my config settings from
OLD Code
<bindings>
<webHttpBinding>
<!-- buffer: 64KB; max size: 64MB -->
<binding name="StreamedBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" transferMode="Streamed"
maxBufferPoolSize="67108864" maxBufferSize="65536" maxReceivedMessageSize="67108864">
</binding>
</webHttpBinding>
</bindings>
To Final working version (transferMode="Streamed" is removed)
<bindings>
<webHttpBinding>
<binding name="StreamedBinding" maxReceivedMessageSize="67108864" />
</webHttpBinding>
</bindings>
finally the service help page is back.
However I can't understand why it is back same as why it was turned off.
anyway, this is the working solution for my case.
hope someone would find it helpful.
What do you mean by saying that it stops working? In the example below the help page is still returned by the service (and I tried using both IE and Chrome, and they were able to see the page).
public class StackOverflow_5937029
{
[ServiceContract]
public interface ITest
{
[WebGet]
int Add(int x, int y);
}
public class Service : ITest
{
public int Add(int x, int y)
{
return x + y;
}
}
static void SendRequest(string address)
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(address);
req.Method = "GET";
HttpWebResponse resp;
try
{
resp = (HttpWebResponse)req.GetResponse();
}
catch (WebException e)
{
resp = (HttpWebResponse)e.Response;
}
Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
foreach (string headerName in resp.Headers.AllKeys)
{
Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]);
}
Console.WriteLine();
Stream respStream = resp.GetResponseStream();
Console.WriteLine(new StreamReader(respStream).ReadToEnd());
Console.WriteLine();
Console.WriteLine(" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ");
Console.WriteLine();
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
WebHttpBehavior behavior = new WebHttpBehavior
{
HelpEnabled = true
};
WebHttpBinding binding = new WebHttpBinding
{
TransferMode = TransferMode.Streamed
};
host.AddServiceEndpoint(typeof(ITest), binding, "").Behaviors.Add(behavior);
host.Open();
Console.WriteLine("Host opened");
SendRequest(baseAddress + "/Add?x=4&y=8");
SendRequest(baseAddress + "/help");
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}

Programmatic configuration of [Silverlight] WCF Client

We're developing a Silverlight Client onto a server-based API exposed via WCF.
I'm trying to move my WCF client code (which works fine) from a configuration-based model to a programmatic model. This will enable me to have a single "root" URL which I can apply at start-up and not require installations to have to maintain humongous configuration files.
I'm stuggling converting my configurations to Silverlight-capable code, though.
Where I have the configuration below for one of my services:
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_ISilverlightHelper">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
<extendedProtectionPolicy policyEnforcement="Never" />
</httpTransport>
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost:50072/API/WCF/Silverlight/SilverlightHelper.svc"
binding="customBinding" bindingConfiguration="CustomBinding_ISilverlightHelper"
contract="API.WCF.Silverlight.ISilverlightHelper" name="CustomBinding_ISilverlightHelper" />
</client>
</system.serviceModel>
</configuration>
I can't figure out how to create the equivelant client-config code. At the moment I have:
CustomBinding customBinding = new CustomBinding();
// I see I need to do something with customBinding but the properties don't seem
// logical
// I have used BasicHttpBinding, but it just returns with "Not Found" (the service does resolve to a valid URL)
BasicHttpBinding basicHttpBinding = new BasicHttpBinding() { MaxBufferSize = int.MaxValue, MaxReceivedMessageSize = int.MaxValue };
EndpointAddress endpointAddress = new EndpointAddress("http://localhost:50072/API/WCF/Silverlight/SilverlightHelper.svc");
ISilverlightHelper silverlightHelper= new ChannelFactory<ISilverlightHelper>(basicHttpBinding, endpointAddress).CreateChannel();
AsyncCallback asyncCallback = delegate(IAsyncResult result)
{
ISilverlightHelper asyncSilverlightHelper = (ISilverlightHelper)result.AsyncState;
string[] files=asyncSilverlightHelper.EndGetPlugInXapNames(result).ToArray();
};
silverlightHelper.BeginGetPlugInXapNames(asyncCallback, silverlightHelper);
Any clues would be appreciated. I've spent all morning Googling/Binging/Overflowing but haven't come across this scenario. Or I might be just so far wrong ...
Sorted it.
I created the BinaryMessageEncodingBindingElement and HttpTransportBindingElements, added them to the CustomBinding and it all works.
Here's my annotated code:
// create the binding elements
BinaryMessageEncodingBindingElement binaryMessageEncoding = new BinaryMessageEncodingBindingElement();
HttpTransportBindingElement httpTransport = new HttpTransportBindingElement() { MaxBufferSize = int.MaxValue, MaxReceivedMessageSize = int.MaxValue };
// add the binding elements into a Custom Binding
CustomBinding customBinding = new CustomBinding(binaryMessageEncoding,httpTransport);
// create the Endpoint URL (I'll use a configured URL later - all web services will then move as one)
EndpointAddress endpointAddress = new EndpointAddress("http://localhost:50072/API/WCF/Silverlight/SilverlightHelper.svc");
// create an interface for the WCF service
ISilverlightHelper silverlightHelper= new ChannelFactory<ISilverlightHelper>(customBinding, endpointAddress).CreateChannel();
// set-up the asynchronous callback
AsyncCallback asyncCallback = delegate(IAsyncResult result)
{
ISilverlightHelper asyncSilverlightHelper = (ISilverlightHelper)result.AsyncState;
string[] files=asyncSilverlightHelper.EndGetPlugInXapNames(result).ToArray();
};
// execute the call
silverlightHelper.BeginGetPlugInXapNames(asyncCallback, silverlightHelper);