There is nothing quite like the thrill of thoroughly testing an application, deploying it, and within the hour getting the call that it doesn’t work. In this particular case, the client was receiving an error will attempting to save a large data object via RIA Services on an IIS 6 server. Who knew that clients actually want to save a more information than your typical dummy data examples?
If you have deployed RIA Services to IIS 6 before, then you have probably already come across the need to define the 3 endpoints for each service in your web.config file. Because we are going to need to make a couple changes to this configuration, let’s review what additions that need to be added to the IIS 6 web.config for RIA Services.
Configuring IIS 6 to work with RIA Services
RIA Services works by dynamically creating your WCF Services for you. Each service is created with 3 endpoints, a custom binding, and a behavior. Unfortunately, in IIS 6 you need to define these configurations manually in the web.config. The first 2 things you need to add to your config is in the <service.serviceModel> section:
<behaviors> <serviceBehaviors> <behavior name="RIAServiceBehavior"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <bindings> <customBinding> <binding name="BinaryHttpBinding"> <binaryMessageEncoding /> <httpTransport /> </binding> </customBinding> </bindings>
Next, you need to add a service entry for each of your RIA services in the <service.serviceModel><services> section. This includes the two services that RIA creates in the Business applications (AuthenticationService, UserRegistrationService):
<service name="MyProject.Web.AuthenticationService" behaviorConfiguration="RIAServiceBehavior"> <endpoint address="" binding="wsHttpBinding" contract="MyProject.Web.AuthenticationService" /> <endpoint address="/soap" binding="basicHttpBinding" contract="MyProject.Web.AuthenticationService" /> <endpoint address="/binary" binding="customBinding" bindingConfiguration="BinaryHttpBinding" contract="MyProject.Web.AuthenticationService" /> </service> <service name="MyProject.Web.UserRegistrationService" behaviorConfiguration="RIAServiceBehavior"> <endpoint address="" binding="wsHttpBinding" contract="MyProject.Web.UserRegistrationService" /> <endpoint address="/soap" binding="basicHttpBinding" contract="MyProject.Web.UserRegistrationService" /> <endpoint address="/binary" binding="customBinding" bindingConfiguration="BinaryHttpBinding" contract="MyProject.Web.UserRegistrationService" /> </service>
You’ll notice that each service needs 3 endpoints. For any additional RIA service that you add to your project, you need to add a service entry with the same 3 endpoints.
Enabling Large Data Transfers
Now the problem with this setup is that the default data transfer is 8k. Since objects are being serialized, it doesn’t take much to reach that 8k limit and generate an error. To resolve this issue, we can adjust our custom binding to allow higher transfers. Here is an example using the maximum values for the entries:
<customBinding> <binding name="BinaryHttpBinding"> <binaryMessageEncoding maxReadPoolSize="2147483647" maxWritePoolSize="2147483647" maxSessionSize="2147483647"> <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> </binaryMessageEncoding> <httpTransport manualAddressing="false" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647" allowCookies="false" authenticationScheme="Anonymous" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" keepAliveEnabled="true" maxBufferSize="2147483647" proxyAuthenticationScheme="Anonymous" realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false" useDefaultWebProxy="true" /> </binding> </customBinding>
This will open up the data transfers and allow you to push larger amounts of data across the wire.
It’s important to note that one of the reasons for the 8k default value is to prevent DoS (Denial of Service) attacks. By opening up to the maximum amount, users can increase the amount of data sent to and requested from the server. So, in a production environment, I would give some consideration to the size of the data transfers.