Supporting both Mtom and Text as MessageEncoding in WCF - asp.net

I have a WCF service, which has a method with the following signature:
object GetCommand(Guid apiKey, SocialService service, string name, object argument);
The reason it's working with objects as both the return type and last argument, is because it should be possible to pass any type as argument and return any type.
Anyway, I'm passing an object, which contains the following property:
public byte[] Photo { get; set; }
To enable large messages, I'd like to start using Mtom, while I was previously using plain-text as MessageEncoding type.
Problem is, I want it to be backwards compatible, so current already-configures clients should keep using plain-text encoding, while new clients should be able to use Mtom via the web.config.
My question is: is it possible to keep using plain-text as MessageEncoding by default (existing clients) and offer Mtom encoding as well side-by-side?
I've tried some things with the configuration, like defining multiple endpoints with different binding-configurations, but I can't get it to work:
Server
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpTextBinding_SocialProxy" />
<binding name="BasicHttpMtomBinding_SocialProxy" maxReceivedMessageSize="5242880" messageEncoding="Mtom">
<readerQuotas maxStringContentLength="655360" maxArrayLength="1310720" maxNameTableCharCount="1310720" maxBytesPerRead="327680" />
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="SocialProxyService">
<endpoint name="BasicEndpoint_SocialProxy" address="" contract="InfoCaster.SocialProxy.ISocialProxy" binding="basicHttpBinding" bindingConfiguration="BasicHttpTextBinding_SocialProxy" />
<endpoint name="MtomEndpoint_SocialProxy" address="" contract="InfoCaster.SocialProxy.ISocialProxy" binding="basicHttpBinding" bindingConfiguration="BasicHttpMtomBinding_SocialProxy" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<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" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Client
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_SocialProxy" messageEncoding="Mtom" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://socialproxy.local/socialproxy.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_SocialProxy"
contract="Webservice.SocialProxy" name="BasicHttpBinding_SocialProxy" />
</client>
</system.serviceModel>
Problem is:
If I don't set Mtom messageEncoding # the client, everything works via plain-text. But when I set it to use Mtom, I'll get an exception:
The remote server returned an error: (415) Cannot process the message because the content type 'multipart/related; type="application/xop+xml";start="<http://tempuri.org/0>";boundary="uuid:65a6b418-8eb3-4c76-b4c0-ea3486a56892+id=2";start-info="text/xml"' was not the expected type 'text/xml; charset=utf-8'..
Anyone able to help me out? :-)

If you want to add a new endpoint (for newer clients), that endpoint needs to be in a different address. Since you didn't get any error, I imagine you have an incorrect name in the name attribute of the <service> element. Remember that the name attribute should contain the fully-qualified name of the service class. If your service class is at the namespace InfoCaster.SocialProxy, your service configuration should be defined like below:
<services>
<service name="InfoCaster.SocialProxy.SocialProxyService">
<endpoint name="BasicEndpoint_SocialProxy" address="" contract="InfoCaster.SocialProxy.ISocialProxy" binding="basicHttpBinding" bindingConfiguration="BasicHttpTextBinding_SocialProxy" />
<endpoint name="MtomEndpoint_SocialProxy" address="newClients" contract="InfoCaster.SocialProxy.ISocialProxy" binding="basicHttpBinding" bindingConfiguration="BasicHttpMtomBinding_SocialProxy" />
</service>
</services>
And the clients would have something like
<client>
<endpoint address="http://socialproxy.local/socialproxy.svc/newClients"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_SocialProxy"
contract="Webservice.SocialProxy" name="BasicHttpBinding_SocialProxy" />
</client>
Now, if you want a single endpoint which can support both text and MTOM in a way that clients sending text receive a text response, and clients which send MTOM receive a MTOM response back, you can still do it. You'll need a custom encoder, and I wrote one in the post at http://blogs.msdn.com/b/carlosfigueira/archive/2011/02/16/using-mtom-in-a-wcf-custom-encoder.aspx.

Related

Value cannot be null. Parameter name: context

I have a WCF webservice which I am struggling to get to successfully run using netTcpBinding.
The error I am receiving is
Value cannot be null.
Parameter name: context
Amongst the first search results that I received regarding this error message was the following post that suggests that this error occurs because WCF doesn't support enumerations (which my service does contain).
However having spent some time in creating another test WCF service I have been able to successfully serve responses that contained enumerations through my webservice which seems to contradict what that post is saying.
Here is how my service definition looks.
<service name="Implementations.CourseService" behaviorConfiguration="metadataBehavior">
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<endpoint address="/CourseService.svc" binding="wsHttpBinding" contract="Contracts.ICourseService" />
<endpoint address="" binding="netTcpBinding" contract="Contracts.ICourseService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:808/CourseService.svc" />
</baseAddresses>
</host>
</service>
<serviceBehaviors>
<behavior name="metadataBehavior" >
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<netTcpBinding >
<binding name="tcpBinding" />
</netTcpBinding>
and this is the end result of invoking this service.
Any help would be immensely appreciated. I will also regularly check this post so if anyone needs any further information that I may not have provided please do ask, as I'm not really sure what's pertinent and what's not.

Webservice over SSL endpoint not found with 404

I've got a webservice up and running and through the browser I can reach it and see it's up and running. Also without https I can make calls to the webservice.
To make calls at the moment I'm using a small console application to test and see the results.
Server side my web.config is as following:
The service section
<services>
<service name="Website.mynamespace.Service1">
<endpoint address="/service.svc" behaviorConfiguration="" binding="wsHttpBinding" contract="SomeDLLFile.Anothernamespace.Services.Proxy.Interface1" ></endpoint>
<endpoint address="/service.svc" behaviorConfiguration="" binding="wsHttpBinding" contract="SomeDLLFile.Anothernamespace.Services.Proxy.Interface1" bindingConfiguration="myBinding" />
<endpoint address="mex" binding="wsHttpBinding" contract="IMetadataExchange"/>
</service>
<service name="Website.mynamespace.Service2">
<endpoint address="/service.svc" behaviorConfiguration="" binding="wsHttpBinding" contract="SomeDLLFile.Anothernamespace.Services.Proxy.Interface2" ></endpoint>
<endpoint address="/service.svc" behaviorConfiguration="" binding="wsHttpBinding" contract="SomeDLLFile.Anothernamespace.Services.Proxy.Interface2" bindingConfiguration="myBinding" />
<endpoint address="mex" binding="wsHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
The used binding
<wsHttpBinding>
<binding name="myBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
On the client side (my console application) i've added an service reference to my webservice. This way I'm able to make calls over HTTP. However when using HTTPS i'm getting an error saying the following
"There was no endpoint listening at https://test.mywebsite.nl/service.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details."
The app.config from my console application looks like this;
<client>
<endpoint address="https://test.mywebsite.nl/service.svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IProxyInterface1"
contract="Service.IProxyInterface1"
name="BasicHttpBinding_IProxyClientInterface" />
<endpoint address="https://test.mywebsite.nl/service.svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IProxyInterface2"
contract="Service.IProxyInterface2"
name="BasicHttpBinding_IProxyInterface2" />
</client>
<behaviors>
<serviceBehaviors>
<!--
Step 2. Inside a <serviceBehaviors> section, add
a name attribute in the <behaviors> element that
matches the behaviorConfiguration attribute in the
<service> element above.
-->
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
When i'm looking at the inner exception I'm looking at an 404-error. I've tried various suggestion from other topics on SO and also articles at MS, but I must be missing something since i'm still represented with the same error. Anybody any idea what I'm doing wrong here?
Got the issue solved thanks to this topic here on SO.
The problem was in the service name, so I combined the endpoints to both contracts in one service definition. I also changed the wsHttpBinding to an basicHttpBinding.
I had something similar and installed a Self Certified SSL certificate in IIS. Try:
http://weblogs.asp.net/scottgu/archive/2007/04/06/tip-trick-enabling-ssl-on-iis7-using-self-signed-certificates.aspx
Obviously you will need to buy a proper certificate when you come to deploy into your production environment.

Problems with WCF Webservice and SSL

I've read lots of threads the last hours but I did not find a solution which is working for me :-(
So as already multiple other users I have problems calling a SVC-Webservice via SSL from my Windows Phone 7 application. On localhost it works fine. I've deployed the Webservice within my Webapplication. The service "MyService.svc" is in the root of the webapplication. On IIS I've only added HTTPS (from Startcom, using default Port 443) for this IP and made SSL required. I could open my web application and I could open the Webservice using any browser at http://mydomain.com/MyService.svc, from both server and local development machine. The page says I could call svcutil.exe https://mydomain.com/MyService.svc?wsdl. When I click on the link the data is display correct.
Now when I try to access it via WP7 app I always get the following error:
"There was no endpoint listening at https://mydomain.com/MyService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details."
And inner details say: "The remote server returned an error: NotFound."
Here is the important part of my web.config. I don't know whether this is all required, as said I've copied it from multiple threads but at least in IE it works fine:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="1073741824" />
<useRequestHeadersForMetadataAddress>
<defaultPorts>
<add scheme="https" port="443" />
</defaultPorts>
</useRequestHeadersForMetadataAddress>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyBehavior" name="MyNamespace.MyService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="HttpsBinding"
contract="MyNamespace.IMyService">
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="HttpsBinding">
<readerQuotas maxStringContentLength="2147483647" />
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<!-- <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> -->
Many thanks!

ProtocolException Received when Calling WCF service

I am having this problem since a week now and am unable to resolve this. I have looked at various posts but found nothing related to the problem.
I have a website and a WCF service inside the same website project. It was all working fine, but suddenly, the WCF service client is not able to receive a valid response from the service.
Error message:
ProtocolException occured
The content type text/html; charset=utf-8 of the response message does
not match the content type of the binding (text/xml; charset=utf-8).
If using a custom encoder, be sure that the IsContentTypeSupported
method is implemented properly. The first 1024 bytes of the response
were: '
Value cannot be null.Parameter name: input
body {font-family:"Verdana";font-weight:norma....
I don't understand what is this parameter input. How can I resolve this issue? The WCF service is accessible via browser using the endpoint mentioned in the web.config
Here is the code:
Code behind:
using (var client = new Agent4HomeWebsite.PhotosWebServiceRef.PhotosWebServiceClient())
{
var temp = client.GetImageObjects();
}
Web.config:
<configuration>
....
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IPhotosWebService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint
address="http://localhost:49274/PhotosWebService.svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IPhotosWebService"
contract="PhotosWebServiceRef.IPhotosWebService"
name="BasicHttpBinding_IPhotosWebService" />
</client>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>

Error on Silverlight WCF access via https

From my silverlight 4.0 application. I can access the WCF File easily but when moved to https, I can't access the WCF Service. The error details are following:
An unknown error occurred. Please contact your system Administrator for more information.
An exception occurred during the operation, making the result invalid. Check InnerException for exception details.
at System.ComponentModel.AsyncCompletedEventArgs.RaiseExceptionIfNecessary()
at FileSearch.SearchServices.GetTypeofFileDetailedCompletedEventArgs.get_Result()
at FileSearch.Home.<SearchButton_Click>b__0(Object s, GetTypeofFileDetailedCompletedEventArgs ea)
at FileSearch.SearchServices.SearchServiceClient.OnGetTypeofFileDetailedCompleted(Object state)
I have seen different posts regarding this issue, but nothing is pointing me in a proper direction.
Here are the details regarding my web.config file for the web application that hosts the silverlight application as well as the WCF Service.
<services>
<service name="FileSearch.Web.Services.SearchService">
<endpoint address="" binding="customBinding" bindingConfiguration="FileSearch.Web.Services.SearchService.customBinding0" contract="FileSearch.Web.Services.SearchService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
and here is the servicerefernce.clientconfig file:
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_SearchService">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="../Services/SearchService.svc"
binding="customBinding" bindingConfiguration="CustomBinding_SearchService"
contract="SearchServices.SearchService" name="CustomBinding_SearchService" />
</client>
</system.serviceModel>
</configuration>
UPDATE:
I've received answers to run the service in the https mode only. I want to run the service in both http and https modes.
any ideas regarding this ?
Specify two endpoints one with secured transport and one without it.
try adding
<security mode="Transport" />
in you service config file. this should be nested inside the binding node.
Check out the security mode configuration section in this article.
For supporting Https scheme, you'd need to change transport to <httpsTransport>. I see you're using <httpTransport>.

Resources