Friday, October 21, 2011
LinqToSql Count
Placing a Web Method in a Page
Thursday, October 20, 2011
Loading a custom control at runtime
plhContainer.Controls.Add(
new Literal
{
Text = string.Format("{0}.{1}",
method.ReflectedType.FullName, method.Name)
});
When it comes to a custom control you also want the markup code of you custom control to be loaded too. So you need to tell the Page o load it for you:
var nameBox = (NameBox) Page.LoadControl("NameBox.ascx");
Basically, you could do this at any time, but it is recommanded to do this at Page_Load the reason is that this is the best place for the control to restore its state and receive postback events. Also the binding will take place after this method. Look at my previous post for the sequence of the events and method calls when page gets loaded.
It is also recomannded to set a unique ID to that control if you need to find that later using FindControl, or some one else want to find where you have put it :-)
So, my load method will look like this:
private void LoadMyControls()
{
var nameBox = (NameBox) Page.LoadControl("NameBox.ascx");
// Give the user control a unique name by setting its ID property.
// You can use this information to retrieve a reference to the control
// when you need it with the Page.FindControl() method.
nameBox.ID = "nameBox";
nameBox.FirstName = "Asghar";
nameBox.LastName = "Panahy";
nameBox.ChangeRequest += ChangeName;
plhContainer.Controls.Add(nameBox);
}
When I call LoadMyControls() in Page_Load method, I see the following sequence in my output:
STARTING: MCTS._70_515.Resources._Default.Page_Init
STARTING: MCTS._70_515.Resources._Default.OnInit
STARTING: MCTS._70_515.Resources._Default.Page_Load
STARTING: MCTS._70_515.Resources.NameBox.Page_Init
STARTING: MCTS._70_515.Resources.NameBox.OnInit
STARTING: MCTS._70_515.Resources._Default.OnLoad
STARTING: MCTS._70_515.Resources.NameBox.Page_Load
STARTING: MCTS._70_515.Resources.NameBox.OnDataBinding
STARTING: MCTS._70_515.Resources.NameBox.get_LastName
STARTING: MCTS._70_515.Resources.NameBox.OnLoad
STARTING: MCTS._70_515.Resources._Default.OnPreRender
STARTING: MCTS._70_515.Resources.NameBox.OnPreRender
STARTING: MCTS._70_515.Resources.NameBox.OnUnload
STARTING: MCTS._70_515.Resources._Default.OnUnload
Notice that the custom control gets its data binded just after the page has passed Loading which is a good thing.
ASP Page en Control Lifecycle
STARTING: MCTS._70_515.Resources.NameBox.Page_Init
STARTING: MCTS._70_515.Resources.NameBox.OnInit
STARTING: MCTS._70_515.Resources.NameBox.Page_Load
STARTING: MCTS._70_515.Resources.NameBox.OnDataBinding
STARTING: MCTS._70_515.Resources.NameBox.get_LastName
STARTING: MCTS._70_515.Resources.NameBox.OnLoad
STARTING: MCTS._70_515.Resources.NameBox.OnPreRender
STARTING: MCTS._70_515.Resources.NameBox.OnUnload
It is important to note that Page_Load is long before OnLoad method, similar to Page_Init versus OnInit.
Next I click on the change button to post back to handle the event and I see the following:
STARTING: MCTS._70_515.Resources.NameBox.Page_Init
STARTING: MCTS._70_515.Resources.NameBox.OnInit
STARTING: MCTS._70_515.Resources.NameBox.Page_Load
STARTING: MCTS._70_515.Resources.NameBox.OnDataBinding
STARTING: MCTS._70_515.Resources.NameBox.get_LastName
STARTING: MCTS._70_515.Resources.NameBox.OnLoad
STARTING: MCTS._70_515.Resources.NameBox.ChangeRequestClicked
STARTING: MCTS._70_515.Resources.NameBox.OnPreRender
STARTING: MCTS._70_515.Resources.NameBox.OnUnload
Next, I add some similar loggging to the page that contains the control and see what happens when I load the page:
STARTING: MCTS._70_515.Resources.NameBox.Page_Init
STARTING: MCTS._70_515.Resources.NameBox.OnInit
STARTING: MCTS._70_515.Resources._Default.Page_Init
STARTING: MCTS._70_515.Resources._Default.OnInit
STARTING: MCTS._70_515.Resources._Default.Page_Load
STARTING: MCTS._70_515.Resources._Default.OnLoad
STARTING: MCTS._70_515.Resources.NameBox.Page_Load
STARTING: MCTS._70_515.Resources.NameBox.OnDataBinding
STARTING: MCTS._70_515.Resources.NameBox.get_LastName
STARTING: MCTS._70_515.Resources.NameBox.OnLoad
STARTING: MCTS._70_515.Resources._Default.OnPreRender
STARTING: MCTS._70_515.Resources.NameBox.OnPreRender
STARTING: MCTS._70_515.Resources.NameBox.OnUnload
STARTING: MCTS._70_515.Resources._Default.OnUnload
So, The OnLoad method gets called after binding whereas the Page_Load is about before the binding. Obviously, if you need to initialize your data, you better put your code in OnInit rather that OnLoad or Page_Load.
Another important thig here is the PreRender methods. These methods get called after load has been completed and the data is assumed to be in place.
Now let's see what happens when I click a button on the control which causes a postback:
STARTING: MCTS._70_515.Resources.NameBox.Page_Init
STARTING: MCTS._70_515.Resources.NameBox.OnInit
STARTING: MCTS._70_515.Resources._Default.Page_Init
STARTING: MCTS._70_515.Resources._Default.OnInit
STARTING: MCTS._70_515.Resources._Default.Page_Load
STARTING: MCTS._70_515.Resources._Default.OnLoad
STARTING: MCTS._70_515.Resources.NameBox.Page_Load
STARTING: MCTS._70_515.Resources.NameBox.OnDataBinding
STARTING: MCTS._70_515.Resources.NameBox.get_LastName
STARTING: MCTS._70_515.Resources.NameBox.OnLoad
STARTING: MCTS._70_515.Resources.NameBox.ChangeRequestClicked
STARTING: MCTS._70_515.Resources._Default.ChangeName
STARTING: MCTS._70_515.Resources._Default.OnPreRender
STARTING: MCTS._70_515.Resources.NameBox.OnPreRender
STARTING: MCTS._70_515.Resources.NameBox.OnUnload
STARTING: MCTS._70_515.Resources._Default.OnUnload
Both event handlers in the control and in the page are called after all controls and the page has been loaded and the data is binded too, just before the rendering take place.
Wednesday, October 19, 2011
Notify Database changes to ASP.NET pages
- writing to a file (simply create or delete an empty file) in a specific location where a CacheDependency can listen to and callBack a method on change.
- implement an HttpHandler that gets the notification with a parameter of what is changed, and let the database send an http request to the IIS server on a trigger.
Tuesday, October 18, 2011
Implementing custom FileCacheProvider
Friday, October 14, 2011
MVC Tips
<%: Html.TextBoxFor(model => model.UnitPrice, new {Value = String.Format("{0:F2}", Model.UnitPrice)})%>
Localizing ASP.NET Tips
There are two kind of localizations:
- Local resources are specific to a page.
- Global resources are shared throughout the site
If your site contains many folders, you might have an App_LocalResources subfolder in each folder of your site.
<asp:Button ID="ButtonFind" runat="server" Text="Find" CssClass="submitButton" meta:resourcekey="ButtonFindResource1" />
<asp:Localize ID="LabelTitle" runat="server" Text="Customer Lookup" meta:resourcekey="LabelTitleResource1"></asp:Localize>
The Text property of the Button control is to aid the developer at design time.
ASP.NET will use the key to find and match on any property that might be set inside the resource file as meta:resourcekey.<PropertyName> or ButtonFindResoure1.Text:
<data name="ButtonFindResource1.Text" xml:space="preserve">
<value>Find</value>
</data>
<data name="ButtonFindResource1.Tooltip" xml:space="preserve">
<value>Click this to start the search action</value>
</data>
Accessing a Local resource in C# could be done as follows:
Textbox1.Text = GetLocalResourceObject("Textbox1.Text").ToString();
Accessing a shared global resource in C# could be done in one of the two followings:
Textbox1.Text = Resources.ResourceFileName.Textbox1Text;
Textbox1.Text = GetGlobalResourceObject("ResourceFileName", "Textbox1Text") as string;
The methods GetGlobalResourceObject and GetLocalResourceObject can come handy when the resources does not exist at compile time and might be provided as a separate dll at runtime.
Monday, October 10, 2011
Show an object instance as an xnl on your page
}
public void LogCode(string message)
{
placeResult.Controls.Add(new Literal() { Text = "<pre><code>" + message + "</code></pre>" });
}
Show Items structure in Sitecore
Thursday, October 6, 2011
jQuery.Ajax versus Server-side event handler
This sample demonstrates two ways of getting address from the server: using server-side event handler versus calling jQuery.Ajax
The following is the markup that provides two fields with javascript call on the change event. It also provides a button that is wired to a server side methode:
<div>
<h3> Address Test</h3>
tabbing from the textboxes will verify if calling the webservice is required.
<table width="100%"><tr><td><table><tr>
<td> Huisnummer *</td>
<td><div class="FieldContainer">
<asp:TextBox runat="server" ID="textboxHousenumber" ClientIDMode="Static"
CssClass="TextField TextField02" onchange="VerifyAddress();"
ValidationGroup="KlantAddress" />
</div>
</td></tr><tr>
<td> Postcode *</td>
<td><div class="FieldContainer">
<asp:TextBox runat="server" ID="textboxPostcode" ClientIDMode="Static"
CssClass="TextField TextField02"
MaxLength="7" onchange="VerifyAddress();"
ValidationGroup="KlantAddress"
/>
</div>
</td></tr>
</table>
Server side call:<br />
<asp:Button ID="Button1" runat="server" OnClick="ShowAddress" Text="Get Adres" ToolTip="CustomerDataController" />
<asp:Label runat="server" ID="lblAddress" />
Assume we have a we DBLLayer that provides an address or throws an exception.
The event handler would be something like this:
/// <summary>Server side event handler</summary>
public void ShowAddress(object sender, EventArgs e)
{
try
{
var adres = DBLayer.GetAddress(textboxPostcode.Text, textboxHousenumber.Text);
ShowAdres(adres);
}
catch (Exception ex)
{
LogError("Error :- " + ex.Message);
}
}
And the Javascript will look like this:
function VerifyAddress() {
// This method is calling the ShowAddress only if both parameters are filled in.
$("#<%=lblAddress.ClientID %>" ).text("" );
var postcode = $("#<%=textboxPostcode.ClientID %>" ).val();
var huisnummer = $("#<%=textboxHousenumber.ClientID %>" ).val();
if (postcode && huisnummer && parseInt(huisnummer) > 0) {
$("#<%=lblAddress.ClientID %>" ).text("calling the server" );
var data = "{ postcode:'" + postcode + <span' , huisnummer: " + huisnummer + " }" ;
jQuery.ajax({
type: <span' ,
contentType: <span'application/json;' ,
data: data,
dataType: <span' ,
url: <span' ,
success: OnGetAddressComplete,
error: OnErrorReceived
});
}
}
function OnErrorReceived(xhr, ajaxOptions, thrownError) {
var message = jQuery.parseJSON(xhr.responseText);
$("#<%=lblAddress.ClientID %>" ).text(
"ERROR (" + xhr.status + ") - " + message.Message);
}
function OnGetAddressComplete(result) {
// display the result
var adres = result.d;
$("#<%=lblAddress.ClientID %>" ).text(
adres.Straat + <span'' +
adres.Huisnummer + <span',' +
adres.Postcode + <span'' + adres.Plaats);
}
And finally the webservice will be like:
[System.Web.Services.WebMethod ()]
public static Adres GetAddress(string postcode, string huisnummer)
{
if (!IsPostcode(postcode))
throw new Exception ("Invalid Postcode." );
int hNr = 0;
if (!Int32 .TryParse(huisnummer, out hNr))
throw new Exception ("Invalid house number." );
var result = DBLayer .GetAddress(postcode, huisnummer);
if (result == null )
throw new Exception (" Unknown address." );
return result;
}
public static bool IsPostcode(string zipcode)
{
var ZipcodeRegex = @"^[1-9][0-9]{3}[a-zA-Z]{2}[\\s]*$" ;
Regex r = new Regex (ZipcodeRegex, RegexOptions .IgnoreCase);
Match m = r.Match(zipcode);
return m.Success;
}