June 11, 2008

Safer Email Address-2

In our previous article Safer Email Addresses we discussed how encoded email addresses are good against the email capture programs. Here we will see how to achieve this in ASP.NET.
Create a class called BasePage and inherit the System.Web.UI.Page and then inherit all your webpages from this BasePage.
Put following code in your BasePage.

protected override void Render(HtmlTextWriter writer)
{
StringWriter stringWriter
= new StringWriter();
HtmlTextWriter interceptedHtmlWriter
= new HtmlTextWriter(stringWriter, " ");
base.Render(interceptedHtmlWriter);
string interceptedHtml = stringWriter.ToString();
interceptedHtml
= ReplaceEmailAddresses(interceptedHtml);
writer.Write(interceptedHtml);
}
private string ReplaceEmailAddresses(string content) {
Regex emailMatcher
= new Regex("([0-9a-zA-Z]+[-._+&])*[0-9a-zA-Z]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}");
MatchCollection matchesFound
= emailMatcher.Matches(content);
foreach (Match m in matchesFound) {
content
= Regex.Replace(content, m.Value, EncodeEmail(m.Value));
}
return content;
}

private string EncodeEmail(string p)
{
string encoded = string.Empty;
foreach (char c in p) {
encoded
+= "&#" + Convert.ToInt32(c).ToString()+";";
}
return encoded;
}

Hope this helps....

Submit this story to DotNetKicks

June 03, 2008

UserControl communication explained !

Sometime we need that all our user controls should communicate to each other when they are on a page. The functionality can be achieved by putting a delegate instance on the user control and on the other user control create a target as following (suppose you have a UserControl AddEditUser.ascx and the page on which you put this user control has user listing and you want that whenever a user is added the Grid must be refreshed. So let's do it using aforesaid approach. Below is the code in the UserControl for the AddEditUser.ascx)

delegate void UserAction(object sender,EventArgs e);
public event UserAction OnUserSaved;
protected btnUserSave_Click(object sender,EventArgs e){

  if(OnUserSaved != null)
      OnUserSaved(sender,e);
}

And in the aspx page you write following code


AddEditUser1.OnUserSaved =
    new UserAction(UserAdded_PageTrigger);

// OR this short hand..

// AddEditUser1.OnUserSaved = UserAdded_PageTrigger;

protected UserAdded_PageTrigger(object sender, EventArgs e)

{

// Time to refresh the Users' List.
}

But let's think broader. I want this UserControl can talk about this recently added user to other UserControls on the page (like a small dashboard showing total users we have or kind of). There is a popular content management solution that call this UserControl a Module. And this functionality is addressed there ( is called Intra module communication) using the Interfaces. A interface is one that a developer has to implement (all methods) so it needs a guideline for a new developer to how to implmenet the interfaces so that his/her module can participate in the module communication.

I tried this using BaseClasses ( BaseClass is not something special but still famous among developers with this name. It is a class that inherits System.Web.UI.Page and this class is then inherited by all the pages in the application so that if, later on there is something to be applied on all the pages of the system this class can help us.). Let's look at the classes first.
 
// BasePage.cs ( base class for all pages)
public class BasePage : System.Web.UI.Page{
  private List<BaseUserControl> _participants;
  public void Register(BaseUserControl me)

  {
   if (_participants == null)_participants = new List<BaseUserControl>();
   _participants.Add(me);
  }
  internal void BroadCastToRegistrants(

    BaseUserControl triggeringControl,
    ControlBroadCastEventArgs e
  )

  {
   if (_participants !=null)
   foreach (BaseUserControl _control in _participants)
   {
    if (_control != triggeringControl) _control.SomethingHappened(triggeringControl, e);
   }

  }
}

 


// BaseUserControl.cs ( base class for all user controls)
public class BaseUserControl : System.Web.UI.UserControl

{
 public delegate void BroadCastEvent(

  BaseUserControl fromControl, ControlBroadCastEventArgs e);

 public event BroadCastEvent OnBroadCastDetected;
 protected override void OnLoad(EventArgs e){
  base.OnLoad(e);

  RegisterToPage();
  }
  protected virtual void RegisterToPage(){
     ((BasePage)this.Page).Register(this);

  }
  public void SomethingHappened(
    BaseUserControl triggeringControl,
   ControlBroadCastEventArgs e)

  {
   if (OnBroadCastDetected != null)
     OnBroadCastDetected(triggeringControl, e);
  }
  public virtual void BroadCast(ControlBroadCastEventArgs e){
   ((BasePage)this.Page).BroadCastToRegistrants(this,e);
  }
}

 
public class ControlBroadCastEventArgs : EventArgs

{
  private string _message = string.Empty;
  private string _sender = string.Empty;
  private object _object =null;

  public string Message { get {return _message;}set{ _message = value;}}

  public string Sender{get{return _sender;}set{_sender = value;}}
  public object Value{get {return _object;}set{_object = value;}}
  public ControlBroadCastEventArgs(){}
}

A very simple approach
 to use but some questions might arise. like

Q : Why ControlBroadCastEventArgs ?

A :  This is the broadcast message. You can extend this message like you can add a DateTime type property that holds the timestamp when the broadcast occured.

Q : Why virtual methods ?

A : Nothing special but in case you want your user control must inherit the above BaseUserControl but should not participate in broadcasting or receiving broadcasts then just override this the Register method and write nothing inside. Or same way like if you want that your control only should listen to the outer broadcasts but should not broadcast anything then override the broadcast and put nothing inside.


Now let's take a look what will be inside your user control that you will inherit from the above BaseUserControl

To listen to a broadcast

protected void Page_Load(object sender, EventArgs e) {
  this.OnBroadCastDetected +=new BroadCastEvent(ThisControl_OnBroadCastDetected);
}

public void ThisControl_OnBroadCastDetected (

    BaseUserControl fromControl, ControlBroadCastEventArgs e)

{
  if (e.Sender == "Broadcaster"){// process the broadcasted message (e);}
}
// to broadcast use following method
protected void BroadcastButton_Click(object sender, EventArgs e)
{
 ControlBroadCastEventArgs ev = new ControlBroadCastEventArgs();
 ev.Message = "New date selected";
 ev.Sender = "CalendarControl";

 ev.Value = Calendar1.SelectedDate;
BroadCast(ev);

}

Using the above approach any control can broadcast anytime (means from any event) and other controls can listen to it. Any number of controls can be participants to listen to above broadcast.

Submit this story to DotNetKicks

May 22, 2008

The Constant Fact : Const Vs Static ReadOnly field

One fact about constant, that we all know, is it's value can never be changed.
Here goes another one.... The constant field is statically replaced by the compiler at the compile time wherever it is found.

Means,


double
circleArea = System.Math.PI * 2 * r;
compiled to
double circleArea = 6.28318 * r;

Said that, suppose you have following expression in your one assembly "Lib"

public const int DataGridPageSize = 50;

And you are referring this assembly in your application "App". Now if you compile the solution the DataGridPageSize will be replaced by 50 in your application. But, if you change the DataGridPageSize value to 100 and compile only the assembly "Lib" and forgot to compile the application "App" then your application still has the old value 50 and not the 100 unless you recompile the "App" application.

But if you have used readonly static field you are safe in above scenario as it is not statically replaced at compile time as the constants are.

Submit this story to DotNetKicks

May 17, 2008

How To Embed Resource And Use It With WebResource Handler

Before you go deeper into this please look into my previous post Why WebResources for good reasons for using WebResources.

Three simple steps for this
.
Embed a resource in the assembly : Select your resource (javascript or image or any other) and goto properties and select "Embedded Resource" as Build Action.



Mention in your AssemblyInfo.cs file :
Mention above this resource in the AssemblyInfo file with the following syntax.
[assembly: WebResource("TestWeb.JavaScripts.common.js", "text/javascript",PerformSubstitution=true)]
Here the first parameter is the path as fully qualified name from the root namespace, like TestWeb is the root namespace and JavaScripts is the directory and then common.js is the filename. Second parameter is the MIME type for the resource being called. Third parameter tells .net that this resource contains some expression that need to be parsed and replaced with real values. We will discuss this third parameter at the end of the topic.

Call the GetWebResourceUrl() : To get the URL that can be used to call the embedded resource. The Url will be in the format
/PathFromRoot/WebResource.axd?d=P6z37LRwQoHAo_Le8MfO3Q2&t=63338169731478
Where d specify the assembly key and t specify the last time the assembly is written (compiled).

syntax of GetWebResourceUrl method is
GetWebResourceUrl(Type type, string resourceName);

I have used the following syntax to register the WebResource given javascript :
string scriptUrl = ClientScript.GetWebResourceUrl(typeof(_Default), "TestWeb.JavaScripts.common.js");
ClientScript.RegisterClientScriptInclude("Common", scriptUrl);

So we are done with how to use WebResource handler.

Now let's examine the third parameter of the WebResource attribute we have used above.
Imagine that we want to use another resource (an image) within the JavaScript file we are calling using the WebResource handler. Suppose the javascript is setting "src" of an image and that image is again a WebResource. So we will write something like following in our javascript file

document.getElementById('logo') = <%= WebResource('logo.gif')%>;


Now if you have mentioned PerformSubstitution=true for the javascript resource then all expressions like above one in your javascript will be replaced by the WebResource handler given url when your javascript will be served like

document.getElementById('logo') = "/PathFromRoot/WebResource.axd?d=P6z37LRwQoHAo_Le8MfO3Q2&t=63338169731478"

Submit this story to DotNetKicks

May 13, 2008

Why WebResources

Before we digg into "HOW TO"s about this topic let's think of "WHY WebResources?" .

Have you ever developed a control that uses some JavaScript? or image?. If not then let's exmine a case where you need to have a TextBox (web custom control) that only accepts digits means you are looking for developing one numeric text box. The quickest thing you will do is you write a class that inherits System.Web.UI.WebControl.TextBox and in that control's life cycle event you will add an HTML attribute to your control like this.Attributes.Add("onkeypress","javascript : return NumericValidationFunction()") (think that you are developing this control not only for a single web application you are working with but to provide to others if anyone needs or to sell).

Now the JavaScript function mentioned above will be written and stored in a string variable and then registered as a javascript in the PreRender method as

protected override void OnPreRender(EventArgs e) {
string numericValidationJs = "<script type='text/javascript'>function NumericValidationFunction() { your custom logic ...}</script>";
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "NumericValidationJs", numericValidationJs ,true);
}
One disadvantage (not to just supporting this topic but it really is) is that it will be rendered as part of your HTML, embedded in the page HTML itself. It increases your page size (HTML that is being rendered to the browser) and also is HeadAche for search engine spiders. Also if you have set of controls within a single library you, for maintainance purpose, need to have a single place to write this JavaScript instead of writing within each control.

Now, based on above reasons you decided to write a ".js" file. The question is to ship this file along with your control library. And if you might have used any image file, for indication that the user has not entered a number, you might also have thought of shipping that image file along with the ".js" file with this assembly.

ASP.NET 2.0 provides a very good way to achieve this and it's recognised as "WebResource handler". Where you can have your resources (like javascript and image and other resources) embedded within your assembly and then use a URL that calls a file with ".axd" extension which is being served by an HTTPHander that respond you with the resource within the assembly. So you need to ship just one ".dll" file that contains your resources within as embedded resource.

Good enough discussion on "WHY" now let's take a look into HOW TO EMBED RESOURCE AND USE IT WITH WEBRESOURCE HANDLER.

Submit this story to DotNetKicks