Currently showing entries with the tag: Visual Basic
|
page 1 of 1
|
Reflection on ASP.NET Auto-Compiled Classes
October 12, 2007 • 8:16AM • permalink
I came across a unique situation yesterday that took awhile to figure out, but I thought it was a really cool concept!
The basic idea is that I have an ASP.NET website that references a DLL. The DLL contains an interface that other classes can implement, with the general idea of allowing external classes (external to the DLL) to act as "plug-ins". The logical location to place these classes is in the App_Code folder, since it will auto-compile the classes and make them available globally, but that's when I ran into a problem...
The DLL also contains a static class to populate a static collection of the classes, so that they can be referenced by name. Since the classes act as "plug-ins", they should be able to be modified at any time, as well as allow for new classes to be dropped into the App_Code folder. The only way to deal with a situation like this is with Reflection.
So, I included a reference to System.Reflection and tried loading the type information for one using Type.GetType(). That failed miserably as the return value was null. I thought for a minute and then wrapped the class placed in App_Code in a unique namespace. I went back to my call to Type.GetType() and tried referencing the class using this namespace. Again, a NullReferenceException.
How did I get around this issue? The solution is actually VERY VERY simple! You just need to get a reference to the Assembly that the App_Code folder gets compiled into by using a call to Assembly.Load("App_Code"). After that, you can use the returned assembly reference in order to get the class type. So, if I have a class named AdamWidget in my App_Code folder that implements the IWidget interface from my DLL. The code in the foreign DLL to load a Type instance for that class could be:
Assembly asm = Assembly.Load("App_Code");
Type module_type = asm.GetType("AdamWidget");
if (module_type.GetInterface("IWidget") != null)
{
DoSomething();
}
That's all there is to it! Now our web application can import (through the DLL) any class that implements IWidget in our App_Code folder!
Please also note that I discovered later that you can also reference the same dynamic assembly with a call to Assembly.Load("__code").
The basic idea is that I have an ASP.NET website that references a DLL. The DLL contains an interface that other classes can implement, with the general idea of allowing external classes (external to the DLL) to act as "plug-ins". The logical location to place these classes is in the App_Code folder, since it will auto-compile the classes and make them available globally, but that's when I ran into a problem...
The DLL also contains a static class to populate a static collection of the classes, so that they can be referenced by name. Since the classes act as "plug-ins", they should be able to be modified at any time, as well as allow for new classes to be dropped into the App_Code folder. The only way to deal with a situation like this is with Reflection.
So, I included a reference to System.Reflection and tried loading the type information for one using Type.GetType(). That failed miserably as the return value was null. I thought for a minute and then wrapped the class placed in App_Code in a unique namespace. I went back to my call to Type.GetType() and tried referencing the class using this namespace. Again, a NullReferenceException.
How did I get around this issue? The solution is actually VERY VERY simple! You just need to get a reference to the Assembly that the App_Code folder gets compiled into by using a call to Assembly.Load("App_Code"). After that, you can use the returned assembly reference in order to get the class type. So, if I have a class named AdamWidget in my App_Code folder that implements the IWidget interface from my DLL. The code in the foreign DLL to load a Type instance for that class could be:
Assembly asm = Assembly.Load("App_Code");
Type module_type = asm.GetType("AdamWidget");
if (module_type.GetInterface("IWidget") != null)
{
DoSomething();
}
That's all there is to it! Now our web application can import (through the DLL) any class that implements IWidget in our App_Code folder!
Please also note that I discovered later that you can also reference the same dynamic assembly with a call to Assembly.Load("__code").
0 comments
Javascript and ASP.NET Hacks
September 12, 2007 • 7:25AM • permalink
Both ASP.NET and Javascript can be extremely useful, in entirely different ways. ASP.NET is a great server-side environment and Javascript can be used to enhance the client-side experience. In my experience, junior developers often have a difficult time getting the two to play nicely together, so I thought I would share a few common tricks. (Please note tricks apply whether you code using Visual Basic or C#. Also, many of these tricks or similar implementations of them are trivial to implement in many other server-side languages, such as PHP, Python or JSP.)
1) Data Injection (ASP.NET => Javascript)
First, in the code-behind area of the page, we setup a simple string variable from an external source:
private string username;
public string Username
{
get { return username; }
set { username = value; }
}
public void Page_Load(object sender, EventArgs e)
{
username = Request["username"];
}
Then, in the front-end part of the page, we can use this variable for a Javascript injection:
<head>
<script type="text/javascript">
alert('<% =Username %>');
</script>
</head>
The result, is that when the page loads, the value that is in username is injected into the Javascript. So if the value Adam is passed into the page, the Javascript is transformed at runtime to:
<head>
<script type="text/javascript">
alert('Adam');
</script>
</head>
So that when the page loads, the alert box appears with the requested username:

2) Input Injection (Javascript => ASP.NET)
There are many ways to get data from a HTML form to the ASP.NET code, including the basic query string and basic form post. Sometimes though, a server control doesn't contain the dynamic nature needed to properly collect user input. In the following example, we're going to collect data from multiple checkboxes and pass them back as a comma-delimited string.
Before I begin, you may ask why I wouldn't just use a CheckboxList or a series of single Checkboxes. You could (especially after reading the third trick that I will present below), but that would make it a little more difficult to do a few dynamic tricks with the checkboxes, like a Select All or Select None functionality.
First, the back-end code:
private string received_values;
public string ReceivedValues
{
get { return received_values; }
set { received_values = value; }
}
public void Page_Load(object sender, EventArgs e)
{
received_values = Request.Form["sent_value"];
}
All we're doing is making the results of a HTTP form post, with the input name "sent_value", publically accessible.
Then, on the front-end, we're going to create our checkboxes based on the contents of a static array. This is only to make a simple example, and our "IDValues" could represent anything from friends on a buddylist, stocks in a portfolio, books in a library, software titles in a shopping cart - anything you could retrieve from a database, XML feed, etc.
Here's the entire code listing. The explanation is below it.
<form id="the_form" method="post">
<% int[] IDValues = new int[] { 5, 10, 25, 50 }; %>
<% for (int x = 0, cnt = IDValues.Length; x < cnt; ++x) { %>
<input type="checkbox" id="someid_<% =IDValues[x] %>" /> <% =IDValues[x] %>
<% } %>
<input type="hidden" id="sent_value" name="sent_value" value="" />
<input type="button" onclick="doSubmit(); return false;" value="Submit" />
</form>
<% if (!string.IsNullOrEmpty(ReceivedValues)) { %>
<strong>Received Values:</strong> <% =ReceivedValues %>
<% } %>
<script type="text/javascript">
function doSubmit()
{
var frm = document.getElementById('the_form');
var post_string = "";
for (var x = 0, cnt = frm.elements.length; x < cnt; ++x)
{
if (frm.elements[x].checked)
post_string += frm.elements[x].id.substring(7) + ",";
}
if (post_string.length > 0)
post_string = post_string.substring(0, post_string.length - 1);
document.getElementById('sent_value').value = post_string;
frm.submit();
}
</script>
It's actually very simple! We create four checkboxes, easily identified by the prefix 'someid_' in their id property. When the button is clicked, we obtain a reference to the form object and loop through all of its elements. If the item is checked (obviously indicating a checkbox in our example), then we remove the 'someid_' prefix and append the id to a running string, with a comma-delimeter.
After traversing the whole form, we cleanup the string by removing the extraneous comma and store the value in a hidden input tag we've created already. This is the key to posting the resulting values to the back-end.
Upon submission, the ReceivedValues string will be populated and will be output, like so:

3) Javascript on ASP.NET Controls (Javascript <=> ASP.NET)
Finally, there are a few additional tricks you can mix in to ease the integration of Javascript and ASP.NET. A very simple example would be a form that requires both client-side validation and server-side validation.
I'll assume the reader can already output an error message using either Javascript or ASP.NET. In this example, we'll assume that we have an existing system to validate a page and upon error, set the InnerHtml property of a div object with the ID 'ErrorMessage'. (Note that divs are implemented as HttpGenericControl objects on the back-end)
If we decided to add in Javascript validation as well (possibly to implement a 'strong password' indicator like Live.com), we don't want to have to create a new location for Javascript error messages.
Using a simple trick, we don't have to:
<form runat="server">
<div id="ErrorMessage" runat="server"></div>
<script type="text/javascript">
document.getElementById("<% =ErrorMessage.ClientID %>").innerHTML = "Cool, eh?";
</script>
</form>
That's all there is to it! While this example is oversimplified, it is easy to see how it can be implemented and extended. This applies to all the examples given above. With the plethora of ASP server controls and Javascript methods available, not to mention AJAX implementations, it's very easy to see how you can make your sites much more dynamic by using the above tricks.
1) Data Injection (ASP.NET => Javascript)
First, in the code-behind area of the page, we setup a simple string variable from an external source:
private string username;
public string Username
{
get { return username; }
set { username = value; }
}
public void Page_Load(object sender, EventArgs e)
{
username = Request["username"];
}
Then, in the front-end part of the page, we can use this variable for a Javascript injection:
<head>
<script type="text/javascript">
alert('<% =Username %>');
</script>
</head>
The result, is that when the page loads, the value that is in username is injected into the Javascript. So if the value Adam is passed into the page, the Javascript is transformed at runtime to:
<head>
<script type="text/javascript">
alert('Adam');
</script>
</head>
So that when the page loads, the alert box appears with the requested username:

2) Input Injection (Javascript => ASP.NET)
There are many ways to get data from a HTML form to the ASP.NET code, including the basic query string and basic form post. Sometimes though, a server control doesn't contain the dynamic nature needed to properly collect user input. In the following example, we're going to collect data from multiple checkboxes and pass them back as a comma-delimited string.
Before I begin, you may ask why I wouldn't just use a CheckboxList or a series of single Checkboxes. You could (especially after reading the third trick that I will present below), but that would make it a little more difficult to do a few dynamic tricks with the checkboxes, like a Select All or Select None functionality.
First, the back-end code:
private string received_values;
public string ReceivedValues
{
get { return received_values; }
set { received_values = value; }
}
public void Page_Load(object sender, EventArgs e)
{
received_values = Request.Form["sent_value"];
}
All we're doing is making the results of a HTTP form post, with the input name "sent_value", publically accessible.
Then, on the front-end, we're going to create our checkboxes based on the contents of a static array. This is only to make a simple example, and our "IDValues" could represent anything from friends on a buddylist, stocks in a portfolio, books in a library, software titles in a shopping cart - anything you could retrieve from a database, XML feed, etc.
Here's the entire code listing. The explanation is below it.
<form id="the_form" method="post">
<% int[] IDValues = new int[] { 5, 10, 25, 50 }; %>
<% for (int x = 0, cnt = IDValues.Length; x < cnt; ++x) { %>
<input type="checkbox" id="someid_<% =IDValues[x] %>" /> <% =IDValues[x] %>
<% } %>
<input type="hidden" id="sent_value" name="sent_value" value="" />
<input type="button" onclick="doSubmit(); return false;" value="Submit" />
</form>
<% if (!string.IsNullOrEmpty(ReceivedValues)) { %>
<strong>Received Values:</strong> <% =ReceivedValues %>
<% } %>
<script type="text/javascript">
function doSubmit()
{
var frm = document.getElementById('the_form');
var post_string = "";
for (var x = 0, cnt = frm.elements.length; x < cnt; ++x)
{
if (frm.elements[x].checked)
post_string += frm.elements[x].id.substring(7) + ",";
}
if (post_string.length > 0)
post_string = post_string.substring(0, post_string.length - 1);
document.getElementById('sent_value').value = post_string;
frm.submit();
}
</script>
It's actually very simple! We create four checkboxes, easily identified by the prefix 'someid_' in their id property. When the button is clicked, we obtain a reference to the form object and loop through all of its elements. If the item is checked (obviously indicating a checkbox in our example), then we remove the 'someid_' prefix and append the id to a running string, with a comma-delimeter.
After traversing the whole form, we cleanup the string by removing the extraneous comma and store the value in a hidden input tag we've created already. This is the key to posting the resulting values to the back-end.
Upon submission, the ReceivedValues string will be populated and will be output, like so:

3) Javascript on ASP.NET Controls (Javascript <=> ASP.NET)
Finally, there are a few additional tricks you can mix in to ease the integration of Javascript and ASP.NET. A very simple example would be a form that requires both client-side validation and server-side validation.
I'll assume the reader can already output an error message using either Javascript or ASP.NET. In this example, we'll assume that we have an existing system to validate a page and upon error, set the InnerHtml property of a div object with the ID 'ErrorMessage'. (Note that divs are implemented as HttpGenericControl objects on the back-end)
If we decided to add in Javascript validation as well (possibly to implement a 'strong password' indicator like Live.com), we don't want to have to create a new location for Javascript error messages.
Using a simple trick, we don't have to:
<form runat="server">
<div id="ErrorMessage" runat="server"></div>
<script type="text/javascript">
document.getElementById("<% =ErrorMessage.ClientID %>").innerHTML = "Cool, eh?";
</script>
</form>
That's all there is to it! While this example is oversimplified, it is easy to see how it can be implemented and extended. This applies to all the examples given above. With the plethora of ASP server controls and Javascript methods available, not to mention AJAX implementations, it's very easy to see how you can make your sites much more dynamic by using the above tricks.
|
page 1 of 1
|