Wednesday, May 18, 2011

An ASP.NET HttpModule to set the current culture to the user’s locale

My web application needs to display user information depend on its default culture.


I created an ASP.NET module:





using System;
using System.Globalization;
using System.Threading;
using System.Web;
namespace Gold.Translate
{
public class UserLocaleModule : IHttpModule
{
public void Init(HttpApplication httpApplication)
{
httpApplication.BeginRequest += (sender, eventArgs) =>
{
var app = sender as HttpApplication;
if (app == null)
{
throw new ApplicationException("Sender is null or not an HttpApplication");
}
var request = app.Context.Request;
if (request.UserLanguages == null request.UserLanguages.Length == 0) return;

var language = request.UserLanguages[0];
if (language == null) return;

try
{
Thread.CurrentThread.CurrentCulture = new CultureInfo(language);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(language);
}
catch
{}
};
}

public void Dispose()
{

}
}
}

Configuration in web.config for classic mode:








<httpModules runAllManagedModulesForAllRequests="true">
<add name="UserLocale" type="Gold.Translate.UserLocaleModule, Gold.Translate" />
</httpModules>


Configuration in web.config for integration mode:








<modules runAllManagedModulesForAllRequests="true">
<add name="UserLocale" type="Gold.Translate.UserLocaleModule, Gold.Translate" />
</modules>



Migration Issues with IIS 7

When you migrated from IIS 6 to IIS 7 you must take care of needed changes. I fiund 2 good Urls tell you about all issues need to take care of it:

http://help.godaddy.com/article/4162

http://world.episerver.com/Documentation/Items/Tech-Notes/EPiServer-CMS-5/EPiServer-CMS-5-R2-SP1/Changes-Between-IIS6-and-IIS7/

Thursday, April 28, 2011

Regular expressions

Sometimes I required to do some tasks using regular expression. In this post I decided to collect my regular expressions:

First regular expression is to find images in the html and replace its src url:







static string ReplaceTag(string HTMLBody, string srcPath, string newPath)
{
Regex reImg = new Regex(@"]*>", RegexOptions.IgnoreCase);
Regex reHeight = new Regex(@"height=(?:(['""])(?(?:(?!\1).)*)\1(?[^\s>]+))", RegexOptions.IgnoreCase RegexOptions.Singleline);
Regex reWidth = new Regex(@"width=(?:(['""])(?(?:(?!\1).)*)\1(?[^\s>]+))", RegexOptions.IgnoreCase RegexOptions.Singleline);
Regex reSrc = new Regex(@"src=(?:(['""])(?(?:(?!\1).)*)\1(?[^\s>]+))", RegexOptions.IgnoreCase RegexOptions.Singleline);
string tmpHTMLBody = HTMLBody;
MatchCollection mc = reImg.Matches(HTMLBody);
foreach (Match mImg in mc)
{
Console.WriteLine(" img tag: {0}", mImg.Groups[0].Value);
string tmpImgTag = string.Empty;
string tmpOldImgSrc = string.Empty;
string tmpNewImgSrc = string.Empty;
tmpImgTag = mImg.Groups[0].Value;

if (reHeight.IsMatch(mImg.Groups[0].Value))
{
Match mHeight = reHeight.Match(mImg.Groups[0].Value);
Console.WriteLine(" height is: {0}", mHeight.Groups["height"].Value);
}
if (reWidth.IsMatch(mImg.Groups[0].Value))
{
Match mWidth = reWidth.Match(mImg.Groups[0].Value);
Console.WriteLine(" width is: {0}", mWidth.Groups["width"].Value);
}
if (reHeight.IsMatch(mImg.Groups[0].Value))
{
Match mSrc = reSrc.Match(mImg.Groups[0].Value);
tmpOldImgSrc = mSrc.Groups["src"].Value;
tmpNewImgSrc = tmpOldImgSrc.ToLower().Replace(srcPath.ToLower(), newPath.ToLower());
tmpHTMLBody = tmpHTMLBody.ToLower().Replace(tmpOldImgSrc.ToLower(), tmpNewImgSrc.ToLower());
Console.WriteLine(" src is: {0}", mSrc.Groups["src"].Value);
}
}
return tmpHTMLBody;
}

This Regular Expression to Clean Word to Html remove word classes and attributes:







static internal string CleanWordHtml(string html)
{
// start by completely removing all unwanted tags
html = Regex.Replace(html, @"<[/]?(fonth1h2h3h4h5h6bspanxmldelins[ovwxp]:\w+)[^>]*?>", "", RegexOptions.IgnoreCase);
// then run another pass over the html (twice), removing unwanted attributes
html = Regex.Replace(html, @"<([^>]*)(?:classlangstylesizeface[ovwxp]:\w+)=(?:'[^']*'""[^""]*""[^\s>]+)([^>]*)>", "<$1$2>", RegexOptions.IgnoreCase);
html = Regex.Replace(html, @"<([^>]*)(?:classlangstylesizeface[ovwxp]:\w+)=(?:'[^']*'""[^""]*""[^\s>]+)([^>]*)>", "<$1$2>", RegexOptions.IgnoreCase);
return html;
}

This Regular Expression to remove tags from Html:







static internal string StripHtml(string html, bool allowHarmlessTags)
{
if (html == null html == string.Empty)
return string.Empty;

if (allowHarmlessTags)
return System.Text.RegularExpressions.Regex.Replace(html, "", string.Empty);

string strippedHtml = System.Text.RegularExpressions.Regex.Replace(html, "<[^>]*>", string.Empty);
strippedHtml = HttpUtility.HtmlDecode(strippedHtml);
return strippedHtml;
}


Check that a string contains Arabic Characters using C#:





static internal bool hasArabic(string text)
{
Regex regex = new Regex(
"\\p{IsArabic}");
return regex.IsMatch(text);
}

Friday, April 8, 2011

How to run 32-bit UDL file on a 64-bit Operating System

Once we create an UDL File and run it on 64 Bit OS, it will list down all the 64 bit OLE DB providers installed on the machine. The reason behind for this is simple.
When you double click on a UDL file on a 64 bit machine, it’ll enumerate only the 64 bit OLE DB Providers and if we have the 32 bit Ole DB providers installed, we will not be able to find that in the enumerated list.
Create a udl file with the name test.udl under the path, C:\.
When we have created a UDL file on a 64 bit machine and try to open it, the following:
"C:\Program Files\Common Files\System\Ole DB\oledb32.dll",OpenDSLFile C:\test.udl Command will be called through C:\windows\system32\rundll32.exe.
Here both Oledb32.dll and rundll32.exe are 64 bit and will not enumerate the 32bit Dlls.
How to run the UDL which lists down the 32bit Dlls?
We can find the 32bit version of Oledb32.dll under the path:
C:\Program Files (x86)\Common Files\System\Ole DB
and 32 bit version of rundll32.exe under the path:
C:\WINDOWS\SysWOW64.
We’ll need to execute the command below from a command line or Start/Run :
C:\Windows\syswow64\rundll32.exe "C:\Program Files (x86)\Common Files\System\Ole DB\oledb32.dll",OpenDSLFile C:\test.udl
Check the paths of rundll32.exe and oledb32.dll while running this command

Saturday, January 22, 2011

Display Html in RDLC file

I want to display HTML in RDLC of reporting service. Report Viewer support html but with limited tags, I want to display HTML generated from rich text editor. After investigation I found the best solution is displaying it as image. Steps to do that:

1. Create class library convert HTML to image.
2. Use this class with report viewer.
3. Display report with asp net.

1. Create class library convert HTML to image
a. In the following url http://webapplication02.blogspot.com/2011/01/convert-html-to-image.html you find the way to create class library to convert html to image.
It is better to create image as bmp for better image quality but this will not work with excel.
You can convert image to another type but check its quality.
b. Need to add [assembly: AllowPartiallyTrustedCallers()] to trust class library for using by report viewer.

2. Use Class with report viewer:
a. Replace your html field in report with Image with properties:
i. Mime type image/bmp
ii. Type of field Database
iii. Field Expression =Code.GetHtmlImage(HtmlField)

b. Add this function to report:


Public Function GetHtmlImage(ByVal body as String) As Byte()
return htmlConv.getWebPageBytes(body, nothing, nothing)
End Function


c. Add Assembly reference to 3 dlls:
i. System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
ii. System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
iii. Your class library
d. Add class library ImageConv class and instance htmlConv
e. To build your solution with report reference to your class library copy your class library to folder:
($Program Files Path)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies

3. Display Report with ASPNET:


ReportViewer1.LocalReport.ExecuteReportInCurrentAppDomain(System.Reflection.Assembly.GetExecutingAssembly().Evidence);
ReportViewer1.LocalReport.AddTrustedCodeModuleInCurrentAppDomain("System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
ReportViewer1.LocalReport.AddTrustedCodeModuleInCurrentAppDomain("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
ReportViewer1.LocalReport.AddTrustedCodeModuleInCurrentAppDomain(Full Assembly name of your class libarary);

Also need to add Full Trust in Web.Config

Convert Html to Image

I searched for free open source csharp to convert html to image. I found solution using:

WebBrowser (namespace System.Windows.Forms) code below is sample of conversion:


static byte[] CaptureWebPageBytesP(string body, int? width, int? height)
{
byte[] data;
// create a hidden web browser, which will navigate to the page
using (WebBrowser web = new WebBrowser())
{
web.ScrollBarsEnabled = false; // we don't want scrollbars on our image
web.ScriptErrorsSuppressed = true; // don't let any errors shine through
web.Navigate("about:blank");
// wait until the page is fully loaded
while (web.ReadyState != System.Windows.Forms.WebBrowserReadyState.Complete)
System.Windows.Forms.Application.DoEvents();
web.Document.Body.InnerHtml = body;

// set the size of our web browser to be the same size as the page
if (width == null)
width = web.Document.Body.ScrollRectangle.Width;
if (height == null)
height = web.Document.Body.ScrollRectangle.Height;
web.Width = width.Value;
web.Height = height.Value;
// a bitmap that we will draw to
using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width.Value, height.Value))
{
// draw the web browser to the bitmap
web.DrawToBitmap(bmp, new Rectangle(web.Location.X, web.Location.Y, web.Width, web.Height));
// draw the web browser to the bitmap
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
EncoderParameter qualityParam = null;
EncoderParameters encoderParams = null;
try
{
ImageCodecInfo imageCodec = null;
//imageCodec = getEncoderInfo("image/jpeg");
imageCodec = getEncoderInfo("image/bmp");

// Encoder parameter for image quality
qualityParam = new EncoderParameter(Encoder.Quality, 100L);

encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = qualityParam;
bmp.Save(stream, imageCodec, encoderParams);
}
catch (Exception)
{
throw new Exception();
}
finally
{
if (encoderParams != null)
encoderParams.Dispose();
if (qualityParam != null)
qualityParam.Dispose();
}
bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
stream.Position = 0;
data = new byte[stream.Length];
stream.Read(data, 0, (int)stream.Length);
}
}
}
return data;
}

But I faced problem when I try to use it without Window Forms (console application, aspnet, or windows service) It gave me error cannot be instantiated because the current thread is not in a single-threaded. To solve this error created STAThread like code below:

public static byte[] CaptureWebPageBytes(string body, int? width, int? height)
{
bool bDone = false;
byte[] data = null;
DateTime startDate = DateTime.Now;
DateTime endDate = DateTime.Now;

//sta thread to allow intiate WebBrowser
var staThread = new Thread(delegate()
{
data = CaptureWebPageBytesP(body, width, height);
bDone = true;
});
staThread.SetApartmentState(ApartmentState.STA);
staThread.Start();
while (!bDone)
{
endDate = DateTime.Now;
TimeSpan tsp = endDate.Subtract(startDate);

Application.DoEvents();
if (tsp.Seconds > 50)
{
break;
}
}
staThread.Abort();
return data;
}