I have implemented an HttpHandler for js files. The work of this HttpHandler is to localize the contents of js files. So the handler picks the contents of js files, localize them and writes to the response object. But the problem is that the handler is resulting in "The remote host closed the connection" when it is used for long files. Following is the code for HttpHandler
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Web.SessionState;
using System.Xml.Linq;
namespace ProjectLocalization
{
/// <summary>
/// HTTP Handler to handle .js file localized resources by replacing Resources tag
/// </summary>
public class JSFileResourceHandler : IHttpHandler, IRequiresSessionState
{
// Regex pattern to extract the resource place holders.
private const string RESOURCEPATTERN = @"<\x25{1}\x24{1}\s*Resources\s*:\s*(?<declaration>\w+\s*,\s*\w+)\s*%>";
//Regex pattern to extract resource location settings.
private const string SETTINGSPATTERN = @"<resourcesettings>(?>.|\n)+?resourceSettings>";
//Caches the default culture set when the handler got instantiated.
private CultureInfo defaultCulture;
public delegate CultureInfo OnApplyCulture();
public static event OnApplyCulture ApplyCulture;
// Initializes a new instance of the class.
public JSFileResourceHandler()
{
defaultCulture = Thread.CurrentThread.CurrentCulture;
}
// Gets a value indicating whether another request can use
// the True if the instance is reusable; otherwise, false.
public bool IsReusable
{
get { return true; }
}
// Enables processing of HTTP Web requests by a custom HttpHandler
// that implements the interface.
// HttpContext: its object that provides references to the intrinsic server objects (for example, Request,
// Response, Session, and Server) used to service HTTP requests.
public void ProcessRequest(HttpContext context)
{
context.Response.Buffer = false;
// Retrieve culture information from session
if (ApplyCulture != null)
{
//Call ApplyCulture(delegate), is ApplyCutlture Return NULL then default culture will be set.
CultureInfo culture = ApplyCulture() ?? defaultCulture;
if (culture != null)
{
// Set culture to current thread
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(culture.Name);
Thread.CurrentThread.CurrentUICulture = culture;
}
}
string physicalFilePath = context.Request.PhysicalPath;
string fileContent = string.Empty;
string convertedFile = string.Empty;
// Determine whether file exists
if (File.Exists(physicalFilePath))
{
// Read content from file
using (StreamReader streamReader = File.OpenText(physicalFilePath))
{
fileContent = streamReader.ReadToEnd();
if (!string.IsNullOrEmpty(fileContent))
{
// Load resource location types
//Dictionary<string, System.Type> locationTypes = GetResourceLocationTypes(fileContent);
Boolean IsLocalized = IsLocalizationImplemented(fileContent);
// Find and replace resource place holders
convertedFile = IsLocalized ? ReplaceResourcePlaceholders(fileContent) : fileContent;//, locationTypes);
}
}
}
context.Response.ContentType = "application/javascript";
context.Response.Output.Write(convertedFile);
context.Response.Flush();
}
private static bool IsLocalizationImplemented(string strFileContent)
{
try
{
bool IsLocalize = false;
Match settingsMatch = Regex.Match(strFileContent, SETTINGSPATTERN, RegexOptions.IgnoreCase);
while (settingsMatch.Success)
{
string Value = settingsMatch.Groups[0].Value.Replace("///", String.Empty).Replace("//", String.Empty);
XElement Settings = XElement.Parse(Value);
//Load Value that it is localized or not.
if (Settings.Element("Resource").Attribute("IsLocalize") != null)
{
String strIsLocalized = Settings.Element("Resource").Attribute("IsLocalize").Value;
settingsMatch = settingsMatch.NextMatch();
if (strIsLocalized.ToUpper() == @"TRUE") IsLocalize = true;
}
}
return IsLocalize;
}
catch
{
return false;
}
}
//Replaces the resource placeholders.
//fileContent:Content of the file
//return:File content with localized strings
private static string ReplaceResourcePlaceholders(string fileContent)
{
string outputString = fileContent;
Match resourceMatch = Regex.Match(fileContent, RESOURCEPATTERN);
while (resourceMatch.Success)
{
// Determine whether a valid match was found
if (resourceMatch.Groups["declaration"] != null)
{
// Extract resource arguments -> always two
// arguments expected: 1. resource location name, 2. resource name
string[] arguments =
resourceMatch.Groups["declaration"].Value.Split(',');
if (arguments.Length < 2)
{
throw new ArgumentException("Resource declaration");
}
string resourceLocationName = arguments[0].Trim();
string resourceName = arguments[1].Trim();
// Load resource string
string localizedValue = "";
try
{
localizedValue = Convert.ToString(HttpContext.GetGlobalResourceObject(resourceLocationName, resourceName));
localizedValue = localizedValue.Replace("\\'", "~");
localizedValue = localizedValue.Replace("'", "~");
localizedValue = localizedValue.Replace("~", "\\'");
}
catch
{
localizedValue = "ERROR WHILE LOCALIZATION!!!";
}
// Replace place holder
outputString = outputString.Replace(resourceMatch.Groups[0].Value, localizedValue);
}
// Find next regex match
resourceMatch = resourceMatch.NextMatch();
}
return outputString;
}
}
}
I think the error is caused by the following lines
context.Response.ContentType = "application/javascript";
context.Response.Output.Write(convertedFile);
context.Response.Flush();
The error comes like The remote host closed the connection. The error code is 0x80072746.
at System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6.FlushCore(Byte[] status, Byte[] header, Int32 keepConnected, Int32 totalBodySize, Int32 numBodyFragments, IntPtr[] bodyFragments, Int32[] bodyFragmentLengths, Int32 doneWithSession, Int32 finalStatus, Boolean& async) at System.Web.Hosting.ISAPIWorkerRequest.FlushCachedResponse(Boolean isFinal) at System.Web.Hosting.ISAPIWorkerRequest.FlushResponse(Boolean finalFlush) at System.Web.HttpResponse.Flush(Boolean finalFlush) at System.Web.HttpResponse.Flush() at System.Web.HttpWriter.Write(String s) at ProjectLocalization.JSFileResourceHandler.ProcessRequest(HttpContext context) at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Can anyone suggest a solution.....
Have you tried getting rid of the call to Flush()? That is the only part that seems suspicious to me.
User contributions licensed under CC BY-SA 3.0