I ported the Chrome extension to Firefox. Nothing new there. Just use :)
Here is a screenshot:
Coder / Biker
And inside the method, there is absolutely nothing special I am doing when parsing fails. I am returning true when parsing failed and false otherwise. But when it fails, it throws this exception for no reason.
After much of Googling, I found that when client is no longer connected to the service this exception may occur on the server. And the solution was to check Response.IsClientConnected property and act accordingly if its false. When I checked it, to my surprise it was false even when the method itself gets called! That is only when the parsing failed. So my conclusion was that the WCF infrastructure takes care of those requests which are not legit at the very beginning of its pipeline and releases the client to free its connection pool. But I still wonder why it passes the context to the method, if it is not willing to listen for the response.
So to fix this I added this method to my base service class:
protected bool IsClientConnected { get { return HttpContext.Current.Response.IsClientConnected; } }In every method which takes in a Stream, I call this method and make sure client is still listening and return the response. So what do I return when client is not connected? Just null. This gets rid of getting the nasty 'remote host' exception and you can save you logs from overflowing with that.Happy coding!PS: The downside of using this method is that you have to use HttpContext which forces you to use AspNetCompatibilityRequirementsMode.Required, in your service which will prevent you from self-hosting it. But then again I don think clients would be disconnected in this fashion unless in that case. So I guess it's fair enough :)
/// <summary>
/// Generates a 2048 bit RSA key pair.
/// </summary>
/// <returns>The key container</returns>
public static CryptoKey GenerateRsaKeyPair()
{
using(var rsa = new RSA())
{
rsa.GenerateKeys(2048, 0x10021, null, null);
return new CryptoKey(rsa);
}
}
/// <summary>
/// Generates a CSR file content according to the details given.
/// </summary>
/// <param name="csr">CSR details</param>
/// /// <param name="key">RSA key</param>
/// <returns>The CSR file content</returns>
public static string GenerateCsr(CsrProperties csr, CryptoKey key)
{
using (var subject = new X509Name
{
Country = csr.CountryName,
Organization = csr.OrganizationName,
OrganizationUnit = csr.OrganizationalUnitName,
SerialNumber = csr.SerialNumber,
Common = csr.CommonName
})
{
using (var req = new X509Request(0, subject, key))
{
return req.PEM;
}
}
}
/// <summary>
/// Generates checksum using SHA256 algorithm.
/// </summary>
/// <param name="payLoad">Data to be used for hashing</param>
/// <returns>The hash</returns>
public static byte[] GenerateChecksum(byte[] payLoad)
{
using (var algo = new SHA256Managed())
{
return algo.ComputeHash(payLoad);
}
}
/// <summary>
/// Encrypts the data using RSA key.
/// </summary>
/// <param name="payLoad">Data to be encrypted</param>
/// <param name="key">RSA key</param>
/// <returns>The encrypted data</returns>
public static byte[] Encrypt(byte[] payLoad, CryptoKey key)
{
using (var rsa = key.GetRSA())
{
return rsa.PrivateEncrypt(payLoad, RSA.Padding.PKCS1);
}
}