Thursday, July 5, 2012

Silverlight and WCF NET.TCP Binding

A lot of people on the internet are having issues with Silverlight 5, WCF (Callback Contract) and nettcpbinding. They end up with the following error message

Could not connect to *****. The connection attempt lasted for a time span of 00:00:00.0990056. TCP error code 10013: An attempt was made to access a socket in a way forbidden by its access permissions.. This could be due to attempting to access a service in a cross-domain way while the service is not configured for cross-domain access. You may need to contact the owner of the service to expose a sockets cross-domain policy over HTTP and host the service in the allowed sockets port range 4502-4534.

I was not able to find even a single working example available on the internet for the same. This blog post might help those looking for a solution to the problem and a working example.

First of all silverlight does not support all the bindings available in WCF. If you want to use a WCF service in your silverlight application which requires a session to be created or if you want to use a WCF service with a callback contract in your silverlight application then you are required to use either NET.TCP binding or PoolingDuplexHttp binding.

If you are planning to host your WCF Service on a Windows Server, you must make sure that it supports TCP. To use NET.TCP binding you need to have IIS7 (available on windows server 2008).

Note: IIS6 and below do not support TCP related bindings.

Also silverlight application can communicate with a WCF service over TCP by only using a port in the range of 4502 - 4534. All the ports in this range are not accessible by default and that is why you get the error message mentioned above.

You need to do the following to get it working
  1. Make sure you have enabled Windows Communication Foundation Non-HTTP Activation.
  2.  To enable WCF Non-HTTP Activation go to Control Panel -- Programs -- Turn Windows features on and off. Expand Microsoft .NET Framework 3.5.1, check the WCF Non-HTTP Activation and click on OK.
  3. Using the IIS Manager then enable NET.TCP binding on your website. To enable NET.TCP binding right click on your website (through IIS Manager) and click on Edit Bindings... then Add a new Binding of type: net.tcp and with binding information: 4502:* and click OK. Again right click on your website and then go to Manage Web Site -- Advanced Settings... Then in the list of enabled protocols change http to http,net.tcp and click on OK.
  4. Now create an exception for the port (that you have planned to use, in my example it is 4502) in the Windows Firewall so that communication over that port is not blocked (creating an exception in the Windows Firewall should work in most of the cases).
  5. Then you have to create a clientaccesspolicy.xml file and place it inside the root folder (C:\inetpub\wwwroot or C:\inetpub\vhosts\default\htdocs).
  6. You are good to go. Just use the WCF service in your Silverlight 5 project as you will do in case of ASP.NET or WPF.
 Also silverlight does not support security over NET.TCP binding so you must disable it in the web.config of your WCF service.

<netTcpBinding>
    <binding name="silverlight" portSharingEnabled="true">
        <security mode="None"/>
    </binding>
</netTcpBinding>

 

The clientaccesspolicy.xml will look like the following

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="*"/>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"/>
<socket-resource port="4502" protocol="tcp"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy> 

Here is the working application(WPF Desktop Client, Silverlight 5 Web Client using WCF - NET.TCP binding)

Sunday, April 10, 2011

Problem: How to access master page controls from content page in ASP.NET

Impact: You cannot change the text of textbor or label in your master page. There are situations when you want to do that according to the page viewed by the user.

Solution: The solution to this problem is very simple. All you have to do is to create a public property to get and set the text of a textbox in the master page(.cs file). Then you can access this public property from any content page.

Example:

<%-- Copy and paste this line in you contentPage.aspx and change the value of virtualPath attribute according to you master page's name --%>
<%@ MasterType  virtualPath = "~/MasterPage.master" %>

//Create this public property in the masterpage.cs file
public String Textbox1
{
        get { return txtTextbox1.Text; }
        set { txtTextbox1.Text = value; }
}

//In the content page's code behind use these lines of code
Master.Textbox1 = "Arshdeep Virdi";
string myName = Master.Textbox1;

Problem: ASP.NET page not updating the content of page

Impact: Sometimes when you are working with xml(or some other data source) and changes are made to the xml file. These changes are not reflected in the aspx page.

Solution: When I first started working with XML and ASP.NET, I came across this problem. I was working on an project where I was supposed to create a xml file of user comments. When a user posted comment, the comment was written to the xml file but was not shown on the aspx page. I tried refreshing the page, response.Redirect() and server.Transfer() but was not able to get the currently posted comments.

To get rid of this problem simply write Response.Cache.SetNoStore(); in the Page_Load method.

Example:

protected void Page_Load(object sender, EventArgs e)
{
        Response.Cache.SetNoStore();
        Response.Expires = -1000;
}

Saturday, April 9, 2011

Problem: Call an aspx page and have it decrypt and return an image

Impact: If you are working with images which are encrypted and stored in a folder. You cannot show the images directly in your aspx page as they are encrypted, by calling another aspx page you can open the encrypted image, decrypt it and return it back to the requesting page.

Solution:

1. Create an aspx page, name it DecryptImage.aspx and copy the code below.

protected void Page_Load(object sender, EventArgs e)
{
    string filePath = Page.Request.QueryString["filePath"];
    Response.ContentType = "image/jpg";
    FileStream encFile = new FileStream(filePath, FileMode.Open, FileAccess.Read);

    //Code to decrypt image goes here

    Response.BinaryWrite(decFileBytes);
    Response.Flush();
    Response.End();
}

2. Then in the calling page use an asp image control to display the image and set its url in the code behing the page file(the .cs file).

Example: 

<asp:Image ID="Image1" runat="server"></asp:Image>

protected void Page_Load(object sender, EventArgs e)
{
    Image1.ImageUrl = "DecryptImage.aspx?filePath=folderName/fileName.jpg";
}

Problem: Host WCF service with netTcpBinding on IIS6

Impact: Service will not work

Solution: IIS 6 does not support netTcpBinding, in order to use netTcpBinding host you service on IIS 7 or change the binding to wsDualHttpBinding or any other http binding if you want to use IIS 6.

Following are the few bindings that you can use with IIS6:
  • basicHttpBinding
  • wsDualHttpBinding
  • wsHttpBinding

Problem: Minimizing SQL injection attacks

Impact: SQL injections can expose private data and modify information stored in database.

Solution: SQL injection attacks can be the most harmful common server attack. Every skilled developer can make mistakes that lead to SQL injection vulnerabilities. To minimize SQL injections you can do the following things.
  1. Use Stored Procedures.
  2. Use Parameterized SQL Commands.
  3. Sanatize the user input to replace characters in the input with special characters.
Example of sanitization:

string output = input.Replace("*", "star");

Problem uploading large files from a client to WCF service

Impact: ProtocolException is thrown displaying message "The remote server returned an unexpected response: (400) Bad Request".

Solution: If you have just started working with WCF applications and are trying to upload small files then you might get rid of this exception, but if you are trying to upload larges files then you might have to face this exception. The solution to this problem is very simple, all you have to do is to follow the steps mentioned below.
  1. Open you WCF application's Web.config or App.config file.
  2. Find a node called <system.serviceModel>.
  3. Inside the <system.serviceModel> nodes create a node <bindings>.
  4. Then create a node matching the binding you are using. For example <basicHttpBinding></basicHttpBinding> for basicHttpBinding.
  5. In the last copy and paste the following code: <binding name="basicBinding" maxBufferPoolSize="104857600" maxReceivedMessageSize="5242880">

Note: Change the binding name according to the bindingConfiguration attribute of you endpoint and also change the size(in bytes) as per you requirement.

Example:

<system.serviceModel>
    <bindings>
      <wsDualHttpBinding>
        <binding name="DualBinding" maxBufferPoolSize="104857600" maxReceivedMessageSize="5242880">
        </binding>
      </wsDualHttpBinding>
    </bindings>

</system.serviceModel>