I've built a WCF Publish Subscribe Topic Service and can successfully publish/subscribe with a console appplication (meaning I know it at least works in a console), and can successfully add both service references to both in my Silverlight Application.
The Problem:
Every time I try to subscribe or publish (in other words, anytime, I pass through my user name and password) while using Silverlight, the ServiceSecurityContext.Current.PrimaryIdentity is NULL, but it works fine in the console. Also, when accessing the service, it doesn't hit my custom user name and password validator when accessing it from Silverlight, but it does from a console.
What are my requirements?
I need to consume my publish subscribe service via Silverlight. The WCF Service needs to user UserName authentication. The WCF Service needs to be as secure as possible while still allowing for use with Silverlight. I have to use .Net, I have to use WCF PubSubTopic, I have to use Silverlight.
I am open to creating multiple subscriber endpoints(for instance, maybe a custom one for SL to use, and another for my api users), but I need to user the same publisher as the rest of my api users (oh yeah, btw, the WCF service is built as an api for my users to access if they want... I'm only allowing them access to the subscriber, and blocking the publisher)
I'm looking for example, advice, and/or troubleshooting help with my current problem. Here's some of my code
VB.NET code of Silverlight trying to publish something
Private Const PUBLISHER_ENDPOINT_ADDRESS As String = "http://myserver/portal/api/v1/Publisher.svc"
Friend Shared Sub PublishSomething()
Dim binding As PollingDuplexHttpBinding = New PollingDuplexHttpBinding()
Dim endpoint_address As EndpointAddress = New EndpointAddress(PUBLISHER_ENDPOINT_ADDRESS)
Dim client As New PublisherClient(binding, endpoint_address)
client.ClientCredentials.UserName.UserName = String.Format("{0}\{1}", Common.CompanyName, Common.UserName)
client.ClientCredentials.UserName.Password = "mypassword"
Dim uUpdate As New PortalPublisherService.UserUpdatedNotification
uUpdate.CompanyID = CompanyId
uUpdate.CompanyName = CompanyName
uUpdate.isAdvisor = True
uUpdate.isMaster = True
uUpdate.MetaNotes = "Testing from silverlight."
uUpdate.updateById = UserId
uUpdate.updateByName = UserName
uUpdate.userEmail = "bill#domain.com"
uUpdate.userId = UserId
client.UserUpdateAsync(uUpdate)
End Sub
Here's the web.config from the service
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
<protocolMapping>
<add scheme="http" binding="wsDualHttpBinding"/>
</protocolMapping>
<extensions>
<bindingExtensions>
<add name="pollingDuplexHttpBinding"
type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement,
System.ServiceModel.PollingDuplex, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</bindingExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<!--primary behavior-->
<behavior name="Portal.Api.Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceCredentials>
<serviceCertificate findValue="PortalApiCert" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
<clientCertificate>
<authentication certificateValidationMode="PeerOrChainTrust" revocationMode="NoCheck"/>
</clientCertificate>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Portal.Web.UserPassAuth, Portal.Web"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<pollingDuplexHttpBinding>
<binding name="pollingBindingConfig"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00"
sendTimeout="00:01:00"
transferMode="Buffered"
hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="5242880"
maxBufferSize="655360"
maxReceivedMessageSize="655360">
<readerQuotas maxDepth="32"
maxStringContentLength="81920"
maxArrayLength="163840"
maxBytesPerRead="16384"
maxNameTableCharCount="163840" />
<security mode="TransportCredentialOnly" />
</binding>
</pollingDuplexHttpBinding>
</bindings>
<services>
<!--publisher endpoint configuration settings-->
<service behaviorConfiguration="Portal.Api.Behavior" name="Portal.Web.Publisher">
<endpoint address="" binding="pollingDuplexHttpBinding" contract="Portal.Publisher.IPublisher" bindingConfiguration="pollingBindingConfig"/>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="meta"/>
<host>
<baseAddresses>
<add baseAddress="http://server/portal/api/v1/IPublisher"/>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
I want to emphasize that I've tried, figuratively, a million different configurations, but can't remember every combination I've tried. I know I'm doing some stuff in the config I shouldn't be, but I was just trying to get it to work period. Also, here are the links I've looked at already
this one
and this one
there's more, but ... well... it's been a long day...
Thanks in advance for any help
Additional NOTE:
This is the binding I'm successfully using with NON-Silverlight implementations
<wsDualHttpBinding>
<binding name="Portal.Api.Binding" maxReceivedMessageSize="2147483647" sendTimeout="00:10:00">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
<security mode="Message">
<message clientCredentialType="UserName" negotiateServiceCredential="false"/>
</security>
</binding>
</wsDualHttpBinding>
Since no one has answered this, I will answer this with my findings. What I'm looking for here is not possible with RIA services and Silverlight over HTTPS. WCF RIA services just don't offer this functionality at this time. If you know this statement not to be true.. please answer my question above with a solution.
Related
Scenario
I am supporting/enhancing a Windows Form App that communicates via a WCF service hosted in IIS using a ServiceHostFactory class.
For the problem I am trying to solve, I am dealing with these 2 methods in the ServiceContract. The ServiceContract is marked as PerCall.
[OperationContract(IsOneWay = true)]
void RunJob(int jobId);
[OperationContract]
byte[] GetUserJobs(int userID);
The user will submit a job, via the RunJob method in a fire and forget fashion. This job will make a WCF call to another service, get some data back, do a lot of stuff with it and store it in the database. This particular job takes roughly 62 minutes to complete.
While the job is in a Running state, the client calls the GetUserJobs method asynchronously every 10 seconds to check job status and update the GUI accordingly. The client is communicating with the WCF service via netTcpBinding.
Problem
Right around the 1 hour mark, the GUI becomes completely unresponsive. Asynchronous calls are still being made, but the completed event is never being called. It seems to me something is deadlocked or blocking, and I can't figure exactly why this is happening. The GUI can start becoming unresponsive before the RunJob (OneWay) is actually finished on the server, but the job itself always finishes and data gets saved to the database.
So even though the GUI is unusable, the Server is still working, except it won't respond to any WCF calls.
If I edit the web.config on the server to recycle IIS, the GUI becomes responsive again.
I am by no means a WCF expert, and I am really struggling with coming up with a solution to this problem. I am pretty sure it is happening because of the asynchronous calls, but I can't pinpoint the exact cause yet. The Asynchronous calls are getting closed, according to the code below.
According to my trace logs, I see the following errors right around when the GUI becomes unresponsive:
<ExceptionType>System.ServiceModel.CommunicationException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>There was an error writing to the pipe: The pipe is being closed. (232, 0xe8).</Message>
Then for Activity http://tempuri.org/IConnectionRegister/ValidateUriRoute I will see:
<DataItem> <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Warning"> <TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.CommunicationObjectFaulted.aspx</TraceIdentifier> <Description>Faulted System.ServiceModel.Channels.ClientFramingDuplexSessionChannel</Description> <AppDomain>/LM/W3SVC/2/ROOT/Service_mt-4-130395564562210673</AppDomain> <Source>System.ServiceModel.Channels.ClientFramingDuplexSessionChannel/56837067</Source> </TraceRecord> </DataItem>
<DataItem> <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Warning"> <TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.CommunicationObjectFaulted.aspx</TraceIdentifier> <Description>Faulted System.ServiceModel.Channels.ServiceChannel</Description> <AppDomain>/LM/W3SVC/2/ROOT/Service_mt-4-130395564562210673</AppDomain> <Source>System.ServiceModel.Channels.ServiceChannel/3537205</Source> </TraceRecord> </DataItem>
Relevant Code/Config (Sanitized a bit)
Client Binding Config
I have tried to set all the timeouts to "infinite" for now, just to rule out that there was some strange timeout behavior. I have tried various timeout settings, but nothing seems to work.
<binding name="MyEndpoint" closeTimeout="infinite"
openTimeout="infinite" receiveTimeout="infinite" sendTimeout="infinite"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10"
maxBufferPoolSize="2147483647" maxBufferSize="2147483647"
maxConnections="100" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<reliableSession ordered="true" inactivityTimeout="infinite"
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
Server Binding Config
<netTcpBinding>
<binding name="MyBinding" portSharingEnabled="true" transferMode="Buffered" closeTimeout="infinite" openTimeout="infinite" receiveTimeout="infinite" sendTimeout="infinite" maxBufferPoolSize="524288" maxBufferSize="2147483647" maxConnections="10" listenBacklog="200" maxReceivedMessageSize="2147483647">
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
<reliableSession ordered="true"
inactivityTimeout="infinite"
enabled="false" />
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
<netTcpBinding>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<ServiceErrorHandler />
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
The GUI does something similar to the following to asynchronously call the WCF service:
public void RefreshJobs()
{
//When the GUI becomes unresponsive, a lot of these log statements start piling up in the log file, until service is restarted
Logger.GetInstance().Info("Begin RefreshJobs");
ServiceClient svc = new ServiceClient("MyEndpoint", url);
try
{
svc.GetUserJobsCompleted += new EventHandler<GetUserJobsCompletedEventArgs>(svc_GetJobsCompleted);
}
catch (Exception e)
{
throw e;
}
svc.GetUserJobsAsync(SomeSingleton().CurrentUser.UserID, false, svc);
Logger.GetInstance().Info("End RefreshJobs");
}
private void svc_GetJobsCompleted(object sender, GetUserJobsCompletedEventArgs e)
{
Logger.GetInstance().Info("Start GetJobsCompleted");
if (e.Result != null)
{
//Do Stuff to Update GUI
}
//Close the connection
if (e.UserState is ServiceClient)
{
((ServiceClient)e.UserState).Close();
}
Logger.GetInstance().Info("End GetJobsCompleted");
}
The problem ended up being the CPU being overloaded, which caused the Smsvchost.exe to stop responding.
A fix from Microsoft is available
It seems like I've been banging my head with custom faults in my Silverlight WCF service forever so I will happily DO MY BEST TO BUY A BEER for anyone who can help me solve this!!!
After much pain I finally have my WCF service throwing custom errors (ParameterValidationFault) and using Fiddler I know that the service's response contains my serialized fault object, but the HTTP response code is 500, not 200, so the client starts throwing exceptions rather than reading the response.
I know my SilverlightFaultBehavior class is supposed to take care of changing the response status code, but the breakpoints I set there are never being hit, so I'm hoping this is a simple web.config issue (web.config at end of post).
If this is relevant my web.config shows "the element 'behavior' has invalid child element 'silverlightFaults'...", in the section
<endpointBehaviors>
<behavior name="SilverlightFaultBehavior">
<silverlightFaults/>
</behavior>
</endpointBehaviors>
but I thought this wasn't a problem as I can view the service's metadata without error. However now I'm thinking this is the missing link that's preventing my status code from being changed on the way out. I have read that this error indicates a problem with the type attribute within my behaviorExtension element not exactly matching what .NET thinks it should be, but I have checked this a million times and the namespace and assembly name are definitely correct. I haven't messed with the version, culture, or public key stuff.
Is there a simple way for .NET to tell me exactly what this type string should be (spaces, commas, and all)? I have viewed the dll's properties in explorer but I'm still no closer.
Any other suggestions on where this might be coming from would be hugely appreciated.
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="silverlightFaults" type="my.namespace.SilverlightFaultBehavior, AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="SilverlightFaultBehavior">
<silverlightFaults/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="my.namespace.IService.customBinding0">
<binaryMessageEncoding />
<httpTransport />
</binding>
</customBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="my.namespace.IService">
<endpoint address="" binding="customBinding" bindingConfiguration="my.namespace.IService.customBinding0" contract="my.namespace.IService" behaviorConfiguration="SilverlightFaultBehavior" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
</configuration>
My SilverlightFaultBehavior class starts like this and is a copy-paste of this MSDN post with a namespace change
namespace my.namespace
{
public class SilverlightFaultBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
OK so this problem has not been resolved but worked-around. I finally saw in this very useful post that I can have anonymous endpointBehaviors. The behaviour is now applied and custom faults are correctly (in a non-standard kind of way) returned as HTTP 200s. Making the behavior anonymous means it is applied to all endpoints, but as my service currently only needs a single endpoint this works for me.
It truly sucks that I had all this grief after reading the friggin manual and implementing it word for word. In the end my config parse error "the element 'behavior' has invalid child element 'silverlightFaults'..." was irrelevant, but a very smelly red-herring along the way as it very well could have been the cause (and still may be).
In case anyone is wondering, I just drank the beer.
My Silverlight/WCF application uses PrincipalPermission in each service method to ensure the user is Authenticated. This works just fine when I have everything configured to HTTP, but once I configured my service endpoints/bindings to support HTTPS (SSL), I get an exception thrown when I call the Demand() method of my PrincipalPermission object.
EDIT: I should mention I am using IIS 7.5 Express to host and debug this project.
Here is the method that checks to make sure the user is authendicated. It's called from each of my service methods:
protected void SecurityCheck(string roleName, bool authenticated)
{
System.ServiceModel.Web.WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
PrincipalPermission p = new PrincipalPermission(null, roleName, authenticated);
try
{
p.Demand();
}
catch (Exception ex)
{
/* wrap the exception so that Silverlight can consume it */
ServiceException fault = new ServiceException()
{
/* Code = 1 will mean "unauthenticated!" */
Code = 1, Message = ex.Message
};
throw new FaultException<ServiceException>(fault); }
}
}
The execption thown is "Request for principal failed."
Here are the important bits of my web.config file:
<behavior name="BinarySSL">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="6553600"/>
<serviceTimeouts transactionTimeout="00:10:00"/>
</behavior>
<binding name="MyApp.Web.Services.ProjectService.customBinding0"
receiveTimeout="00:10:00" sendTimeout="00:10:00">
<binaryMessageEncoding />
<httpsTransport authenticationScheme="Basic"/>
</binding>
<service name="MyApp.Web.Services.ProjectService" behaviorConfiguration="BinarySSL">
<endpoint address="" binding="customBinding" bindingConfiguration="MyApp.Web.Services.ProjectService.customBinding0"
contract="MyApp.Web.Services.ProjectService" />
</service>
Here is the ClientConfig:
<binding name="CustomBinding_ProjectService">
<binaryMessageEncoding />
<httpsTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
<endpoint address="https://localhost:44300/Services/ProjectService.svc"
binding="customBinding" bindingConfiguration="CustomBinding_ProjectService"
contract="ProjectProxy.ProjectService" name="CustomBinding_ProjectService" />
I'm hoping someone can point in in the right direction here. Again, this configuration works just fine until I configure my services for SSL. Any thoughts?
Thanks,
-Scott
I thought I found the problem, and answered my own question - but I was wrong. Still have the same issue.
I'm working on a project using Silverlight 4 and WCF. All of the web methods, exept one are working fine. In Silverlight I use a custom xaml writer to write a string and I want to save the string in a database. Using the Insert method on the web service, I can insert data as long as the string parameter is not too large. When trying to insert the string created by the xaml writer, I get an error. I used Fiddler to trace the error and I"m getting and HTTP 400 error. I have read in numerous post that I need to change the config settings on the servce hosting in the web app and in the client config in the Silverlight app. I have made all the changes that I could find on the web. I don't know what else to try and I have ran out of resources. When I paste the xaml string into Notepad and save it, the file is only 425 KB. Here are the changes I've made to each config file. Hopefully someone can pointout anyting I'm missing. Thank you for looking over my issue.
web.config file in web app:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<!-- Enable the serializer to serialize greater number of records -->
<behavior name="CustomServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="CustomBinding">
<readerQuotas maxDepth="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
ServiceReferences.ClientConfig:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_DBService" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost.:49436/BuilderWebService/DBService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_DBService"
contract="ServiceReference1.DBService" name="BasicHttpBinding_DBService" />
</client>
</system.serviceModel>
In your web.config in the binding tag you shoiuld add attributes: maxBufferPoolSize, maxReceivedMessageSize, maxBufferSize:
<basicHttpBinding>
<binding name="CustomBinding"
maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647">
<readerQuotas maxDepth="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647"
maxStringContentLength="2147483647" />
</binding>
</basicHttpBinding>
In my example, I've provided the maximal values for the sizes, but you can define the sizes you actually need. Hope it will help you.
I have no trouble retrieving a large amount of data, but sending it back to the service displays this error. I've tried adding the element to both the web.config and servicereferences.clientconfig and it's not recognized in either. At one point I got a message about adding readerQuotas to bindingElementExtensions, but I can't find anything useful on how to do this. I found posts saying I had to modify the devenv.exe.config and such, but doing that hosed VS.
Edit
Here's the binding section of the web.config:
<bindings>
<customBinding>
<binding name="QaRiM.Web.Service1.customBinding0">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service name="QaRiM.Web.Service1">
<endpoint address="" binding="customBinding" bindingConfiguration="QaRiM.Web.Service1.customBinding0"
contract="QaRiM.Web.Service1" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
and the servicereferences.clientconfig:
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_Service1">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost:36533/Service1.svc" binding="customBinding"
bindingConfiguration="CustomBinding_Service1" contract="ServiceReference1.Service1"
name="CustomBinding_Service1" />
</client>
</system.serviceModel>
</configuration>
Both were generated by VS.
You are simply missing the configuration for the maximum string content length.
Add this to your binding attributes (client and server)
<readerQuotas maxStringContentLength="2147483647" />
Sorry, I didn't realize that this child element is located under the encoding being used when using a custom binding, it appears to bebinaryMessageEncoding in your example. If not, try the other encodings with the setting.
<bindings>
<customBinding>
<binding name="QaRiM.Web.Service1.customBinding0">
<binaryMessageEncoding>
<readerQuotas maxStringContentLength="2147483647"/>
</binaryMessageEncoding>
</binding>
</customBinding>
</bindings>
if The maximum string content length quota (8192) has been exceeded while reading XML data.” is ignoring your web.config settings EVEN after you set
you can also solve the problem in your code by creating an instance of XmlDictionaryReaderQuotas and setting the MaxStringContentLength to 2147483647
then just use the instance of XmlDictionaryReaderQuotas seen here as mycreatedreaderquota
XmlDictionaryReaderQuotas mycreatedreaderquota = new XmlDictionaryReaderQuotas();
mycreatedreaderquota.MaxStringContentLength = 2147483647;
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, mycreatedreaderquota);
edit: This saved an incomplete draft, sorry
Synchronizing the service/client definitions is what you've done but it's definitely imperative that they match.
Are you sure you need custom binding? Have you tried using ws(Dual)HttpBinding as a base?
This post may be of interest: silverlight 3 wcf service configuration -- getting maxreceivedmessagesize error, specifically the httpRuntime maxRequestLength="2147483647" setting.
You may need to set maxBufferPoolSize and maxItemsInObjectGraph. The config in the linked SO post pretty much maxed everything out.
I don't know if you use the ChannelFactory client proxy method or the service reference method but you may wish to go the former route. In debug sessions I was finding certain values from the config weren't being applied as I had thought but my short term memory on the subject is rather lost now.
Related to #5 somewhat, you can run into WCF Test Client issues where the test client is using default bindings that you're not prepared for.
Another post that may be of interest: http://www.haveyougotwoods.com/archive/2008/04/14/wcf-message-streaming.aspx
Streaming is likely your best bet on the client side to keep from the blocking nature of buffered transferMode. I don't know the specifics of how big the data will be consistently but your service will behave a little nicer on the client end if you went that route. A good primer on configuring just the client side for streaming can be found here: http://systemmetaphor.blogspot.com/2009/05/using-wcf-to-transfer-large-data-files.html.
Hopefully some combination of the above helps
Have you tried setting the maxStringContentLength within the config for the service? In my situation, setting it on the service allowed for the Silverlight client to use the desired value for maxStringContentLength.
One note is that if you are allowing longer strings, but don't adjust the maxReceivedMessageSize, than this can cause issues as well. The maxReceivedMessageSize does need to be controlled on both the service and the client, as one will not inherit the values from another.