January 2009 - Posts
Hi, I decided to summarize some insights about ASP.NET Themes and Skins . These are a little bits and bytes on this area. so here they are:
1. In addition to adding a "Theme" property to the Page directive such as:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="Themes_and_Skins_Default" Theme="BlueTheme" %>
There is also another property we can use: "StyleSheetTheme" such as:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="Themes_and_Skins_Default" StylesheetTheme="BlueTheme" %>
So what is the difference? Very simple! The difference is when we override the Theme settings in the server control itself. Say I have a TextBox control on the page with a property of BackColor set to "chocolate" color. this Button has a control skin that specifies other color (lets say white).
Here is the control on the ASPX file:
<asp:TextBox ID="TextBox1" BackColor="chocolate"
ForeColor="white" runat="server"></asp:TextBox>
And Here is the control skin in the skin file:
<asp:TextBox runat=server BackColor="White" />
What happens then? does the properties from the skin file win or the properties on the control wins? Well this is exactly the case we want the know the difference between "Theme" and "StyleSheetTheme". If the page contains "Theme" definition then the Theme wins ( the skin file) and if we use "StyleSheetTheme" the control itself wins. (just like css cascading - hence the name "StyleSheetTheme").
2. Say we have an application level Theme (One that is in the web.config and influence all the pages). We can disable this Theme from being applied to some pages by using the Page directive "EnableTheming" and set it to false. like this:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs"
Inherits="Themes_and_Skins_Default2" EnableTheming="false" %>
This can be done in the control level also. We can even say to this page to use a different Theme.
3. Themes and master pages:When we use Master pages in our application the Master directive also has a EnableTheming property.As it turns out the master page takes precedence over the content page. This means that even if you specified in the web.config some Theme you with that all pages will get and the master page specifies EnableTheming="false" any content page that will try to turn it on" will fail.
This is however not the case for a control level.
Hope this helps :)
Pini Dayan
One of the thing many developers hate doing is to try and make some border rounded, usually to get this mission done, one needs to get messy with images and table.
Here is a sample of a rounded login control I built :
As you can see in the top of this control the border is rounded.This is done using table and images created especially for the top left and top right.
As it turns out, in CSS 3 (Which is not a standard yet) we can accomplish this mission very easily with the new border-radius property.
In IE this CSS 3 property is not supported, so i had to download "Mozilla Firefox" in order to show this sample.(It want easy to decide to download this "other" browser)
Here is a simple div with no rounded corners:
and here is the HTML and CSS for it:
<html>
<head>
<style>
div
{
padding:30px;
margin:30px;
background-color:yellow;
color:Red;
width:60px;
height:60px;
}
</style>
</head>
<body>
<div>
Some text
</div>
</body>
</html>
Now here is the same div with the new property from CSS 3:
and all I did was adding:
-moz-border-radius: 15px; to the div selector in the CSS. Amzing right?
Hi , I discovered some time ago an amazing feature of ASP.NET 2.0. This feature is called the "CSS friendly control adapters". What this feature basically mean is that we can take a given control , a server control of any kind such as the Button, BulletedList any other server control we have in ASP.NET and simply control the HTML this control renders.
This feature making the control HTML rendering much easier than having to inherit the control itself or writing a custom control from scratch. Lets see how this is done in a simple sample:
Say we have a page containing a bulleted list ( in simple html this is an un ordered list with the UL tag in use)
<div>
<asp:BulletedList runat=server ID="blBooks">
<asp:ListItem Text="book1" Value="book1"></asp:ListItem>
<asp:ListItem Text="book2" Value="book2"></asp:ListItem>
<asp:ListItem Text="book3" Value="book3"></asp:ListItem>
</asp:BulletedList>
If we run this page and check its HTML we will see indeed that this control renders to a simple combination of the UL and LI html tags:
<ul id="blBooks">
<li>book1</li><li>book2</li><li>book3</li>
</ul>
Now what if we want a different HTML outout for different browsers of even for mobile devices, what then?
Well apparently there is a simple solution called "Control adapters". You can tell the runtime that instead of calling the Render function of the control to call the Render functions of some different class. This class is the control adapter. So how do we get it to work?
1. Add a class to your app_code folder or to the any class library referenced from your web project. This class must inherit WebControlAdapter class. (found in the System.Web.UI.WebControls.Adapters namspace).
2. Override its rendering functionality, here is a sample for the BulletedList control:
public classBulletedListControlAdapter :
WebControlAdapter
{
protected override voidRenderBeginTag(HtmlTextWriter writer)
{
writer.WriteLine();
writer.WriteBeginTag("table");
writer.Write(HtmlTextWriter.TagRightChar);
writer.Indent++;
}
protected override voidRenderEndTag(HtmlTextWriter writer)
{
writer.WriteEndTag("table");
writer.Indent--;
writer.WriteLine();
}
protected override voidRenderContents(HtmlTextWriter writer)
{
writer.Indent++;
BulletedListbl = Control asBulletedList;
if(bl != null)
{
foreach (ListItem i inbl.Items)
{
writer.WriteLine();
writer.WriteBeginTag("tr");
writer.Write(HtmlTextWriter.TagRightChar);
writer.WriteLine();
writer.Indent++;
writer.WriteBeginTag("td");
writer.Write(HtmlTextWriter.TagRightChar);
writer.WriteLine();
writer.Indent++;
writer.Write("*");
writer.Write(HtmlTextWriter.SpaceChar);
writer.Write(i.Text);
writer.WriteLine();
writer.Indent--;
writer.WriteEndTag("td");
writer.WriteLine();
writer.Indent--;
writer.WriteEndTag("tr");
writer.WriteLine();
}
}
writer.Indent--;
}
}
3. Now we need to tell somehow to the runtime to use this adapter. We can do this by simply add a special folder called app_browsers. In this sample i will simply change the default browser instead of telling which adapter to use for each browser , but know this is possible.
Here is my BrowserFile.browser file:
<!-- File: MyAdapters.browser -->
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter
controlType="System.Web.UI.WebControls.BulletedList"
adapterType="MsdnMagazine.BulletedListControlAdapter"
/>
</controlAdapters>
</browser>
</browsers>
Thats it.Now run the same page again, and see the html:
<table>
<tr>
<td>
* book1
</td>
</tr>
<tr>
<td>
* book2
</td>
</tr>
<tr>
<td>
* book3
</td>
</tr>
</table>
Enjoy,
Pini Dayan
Today , I started to debug some page that uses ASP.NET Ajax. I decided that instead of writing my OO (Object Oriented) using simple JavaScript as I often do , i will use the built in functionality from ASP.NET Ajax ( The client half of it). So I debugged some page and they using the script document ( you can see it in the solution explorer when debugging) i checked the "Type" type that I need to use to write my classes, enums and doing some JavaScript reflection.
Here is the mentioned widow:as you can see it shows the JavaScript that are being used for the current page.
So looking at the code of one of those script (The "MicrosoftAjax.debug.js" file that comes with the "System.Web.Extentions" assembly) one can see that the definition of the "Type" type is declared as follow:
if (!window) this.window = this;
window.Type = Function;
So basically "Type" is nothing more than an alias to the Function object which is a built in object in JavaScript ( and contains several methods of it's own like apply , call etc).The only reason Microsoft did this alias is so that it will be more .NET framework like syntax.
Like every JavaScript object (String,Int, Object Date,Array etc) , The Type type has a property named "prototype" that the defines the properties and methods this type has. The Function object is no exception. What this means is that we can extend the functionality of the Type type (The Function Type) easily. This is what Microsoft guy did exactly.Looking several lines of code under i can see the extesion that was done to the Type(Function type):
Type.prototype.getBaseMethod = function Type$getBaseMethod(instance, name) {...
Type.prototype.getBaseType = function Type$getBaseType() {....
Type.prototype.getName = function Type$getName() {......
Type.prototype.initializeBase = function Type$initializeBase(instance, baseArguments) {.....
and much much more.
Now pay attention.What this means is that every function in JavaScript(which is an object , a custom object if you like - a constructor function) will get the newly added methods we just saw.This is very powerful feature which we get by only adding the ScriptManager to our page.
If we take a look at the internal implementation of the "registerClass" function added to the "Type" type, we will notice a few interesting points:
Type.prototype.registerClass =
function Type$registerClass(typeName, baseType, interfaceTypes) {
/// <summary locid="M:J#Type.registerClass" />
/// <param name="typeName" type="String"></param>
/// <param name="baseType" type="Type" optional="true" mayBeNull="true"></param>
/// <param name="interfaceTypes" parameterArray="true" type="Type"></param>
/// <returns type="Type"></returns>
var e = Function._validateParams(arguments, [
{name: "typeName", type: String},
{name: "baseType", type: Type, mayBeNull: true, optional: true},
{name: "interfaceTypes", type: Type, parameterArray: true}
]);
if (e) throw e;
if (!Type.__fullyQualifiedIdentifierRegExp.test(typeName)) throw Error.argument('typeName', Sys.Res.notATypeName);
var parsedName;
try {
parsedName = eval(typeName);
}
catch(e) {
throw Error.argument('typeName', Sys.Res.argumentTypeName);
}
if (parsedName !== this) throw Error.argument('typeName', Sys.Res.badTypeName);
if (Sys.__registeredTypes[typeName]) throw Error.invalidOperati(String.format(Sys.Res.typeRegisteredTwice, typeName));
if ((arguments.length > 1) && (typeof(baseType) === 'undefined'))
throw Error.argumentUndefined('baseType');if (baseType && !baseType.__class) throw Error.argument('baseType',
Sys.Res.baseNotAClass
this.prototype.constructor = this;
this.__typeName = typeName;
this.__class = true;
if (baseType) {
this.__baseType = baseType;
this.__basePrototypePending = true;
}
Sys.__upperCaseTypes[typeName.toUpperCase()] = this;
if (interfaceTypes) {
this.__interfaces = [];
this.resolveInheritance();
for (var i = 2, l = arguments.length; i < l; i++) {
var interfaceType = arguments[i];
if (!interfaceType.__interface)
throw Error.argument('interfaceTypes[' + (i - 2) + ']', Sys.Res.notAnInterface);
for (var methodName in interfaceType.prototype) {
var method = interfaceType.prototype[methodName];
if (!this.prototype[methodName]) {
this.prototype[methodName] = method;
}
}
this.__interfaces.push(interfaceType);
}
}
Sys.__registeredTypes[typeName] = true;
return this;
}
-
There is a lot of code here so I will concentrate on the main thing to notice.
-
The first param is "typeName". The function uses it in the this.__typeName = typeName; statment.This is an internal field in the this. The this will be the object on which we called this function , Like the Person object i will show soon.
-
An internal filed named __class is set to true.This is for later reflecting and checking if this type is being used as a class. (Just like in C#, it's like a metadata).
-
Sys.__registeredTypes[typeName] = true; It sets a global object with the type name we sent as a argument. Also for reflection purposes.
Here is a simple sample showing what i was writing about:
<script>
function Dog(name, lastName) {
this.name = name;
this.lastName = lastName;
this.respondTo = function(name) {
if (this.name == name) {
alert("Woof");
}
};
}
Dog.registerClass("Dog");
var spot = new Dog("Spot", "Spoti");
alert(spot.respondTo("Spot"));
</script>
Hi, usually programmers tend to ignore the power of regular expressions when they write their programs. Well, to be honest I tend to ignore this power as well. So instead of learning once and for all the syntax for these expression we usually copy them from the Internet and use them whenever we need to.
So i decided to start writing a infrastructure that contains several functions to validate a given string with some regular expression pattern, but instead of just writing a class with some static functions, i wrote the class and functions to be an extension methods to the String type. (Extension methods are a new feature in C# 3 and You can read about them here http://msdn.microsoft.com/en-us/library/bb383977.aspx)
So here is my solution, and will also attach the files to be downloaded if you with to extend them even more.
The first class is a simple one, it contains only the constants variable for holding the expressions for some of the things i would like to validate:
public class RegularExpressionConstants
{
//Regular expression for checking if a given string is alpha bet. (e.g aaa , aa9, 931a, not 123).
public const string IS_ALPHABET = "[a-zA-Z]";
//Regular expression for checking if a given string is alpha numeric. (e.g aaa , aa9, 931a, and 123).
public const string IS_ALPHA_NUMERIC = "[a-zA-Z0-9]";
//Regular expression for checking if a given string is a valid email.
public const string IS_EMAIL = @"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*";
//Regular expression for checking if a given string is a valid url.
public const string IS_URL = @"http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?";
//Regular expression for checking if a given string is a valid url.
public const string IS_CELLULAR_NUMBER =
@"^[0][5][0]-\d{7}|[0][5][2]-\d{7}|[0][5][4]-\d{7}|[0][5][7]-\d{7}$";
}
The second class is the String extender which actually extent the string type and make use of the System.Text.RegularExpressions namespace:
public static class RegularExpressionsCheckerExtender
{
public static bool IsAlphaBet(this string sStringToCheck)
{
Regex oIsAlphaBet = new Regex(RegularExpressionConstants.IS_ALPHABET);
return oIsAlphaBet.IsMatch(sStringToCheck);
}
public static bool IsAlphaNumeric(this string sStringToCheck)
{
Regex oIsAlphaBet = new Regex(RegularExpressionConstants.IS_ALPHA_NUMERIC);
return oIsAlphaBet.IsMatch(sStringToCheck);
}
public static bool IsEmail(this string sStringToCheck)
{
Regex oIsAlphaBet = new Regex(RegularExpressionConstants.IS_EMAIL);
return oIsAlphaBet.IsMatch(sStringToCheck);
}
public static bool IsURL(this string sStringToCheck)
{
Regex oIsAlphaBet = new Regex(RegularExpressionConstants.IS_URL);
return oIsAlphaBet.IsMatch(sStringToCheck);
}
public static bool IsIsraeliCellNumber(this string sStringToCheck)
{
Regex oIsAlphaBet = new Regex(RegularExpressionConstants.IS_CELLULAR_NUMBER);
return oIsAlphaBet.IsMatch(sStringToCheck);
}
private static bool CheckIfMatch(string sStringToCheck, string sRegExExpression)
{
Regex oRegEx = new Regex(sRegExExpression);
return oRegEx.IsMatch(sStringToCheck);
}
}
Here is a simple console application code that test the string extended functions:
class Program
{
static void Main(string[] args)
{
//Once we added the "using RegularExpressionsStringExtender;"
//the string type is being extended
string sEmail = "pinid@somedomain.com";
Console.WriteLine(sEmail.IsEmail());
string sCellPhone = "11111111";
Console.WriteLine(sCellPhone.IsIsraeliCellNumber());
string sURL = "http://www.ynet.co.il";
Console.WriteLine(sURL.IsURL ());
//...
}
}Here is a link to download the entire solution
http://blogs.microsoft.co.il/files/folders/pini_dayan/entry210172.aspx
Enjoy
Hi All, It this closing post on the subject of Encrypting web.config data, I would like to show how to encrypt the sensitive data at runtime. Why? you ask, because for example we wish to deploy our code and see what the web.config contains before it is encrypted. or we would like to change the connection string or any appSettings data in a readable way.
So, here is a simple code that does exactly that:
protected void Page_Load(object sender, EventArgs e)
{
EncryptConfig();
}
private void EncryptConfig()
{
// Open the Web.config file.
Configuration config =
WebConfigurationManager.OpenWebConfiguration("~");
// Get the connectionStrings section.
ConnectionStringsSection section =
config.GetSection("connectionStrings")
as ConnectionStringsSection;
// Toggle encryption.
if (section.SectionInformation.IsProtected)
{
section.SectionInformation.UnprotectSection();
}
else
{
if (!section.SectionInformation.IsLocked)
{
section.SectionInformation.
ProtectSection("RsaProtectedConfigurationProviderqqq"); section.SectionInformation.ForceSave = true;
//Save changes to the Web.config file.
config.Save(ConfigurationSaveMode.Full);
}
}
}
Couple of things to notice here:
1. This code is better of being in a some base page so that when the user enters some page in your app, you guaranty that the base page code is called.
2. You can write the same code for Encrypting the app setting section as well.
3. Notice the name of the container key i am using, "RsaProtectedConfigurationProviderqqq".
This is the name of the RSA provider i added to my machine.config file after creating a container key.