Thursday, August 9
Validation and Agile Principles
trim method, since a prebuilt one is not available.
But while watching Peter blum's DNRTV episode,
he showed that a prebuilt Trim method is available only when the method is used as (set as)a client side validator of the customvalidato control.
txtVal .value = ValidatorTrim(txtVal.value);
To hook up an additional control to the
ControlTovalidate use:
ValidatorHookupControlID("secondcontrolClientID",All credit goes to Peter Blum and DnrTV, blogging only for future reference purposes.
"clientIDOfTheCustomValidator");
Also, ValidatorEnable(clientID) to enable/disable validators on the client side.
What I find funny is that these functions don't find a mention in the Professional series of
asp.net not have I come across these in forums/blogs I browsed up till now. I wonder how one is supposed to find out helpful things like these.
Also here is a list of Agile principles mentioned by Venkat on DrntV episode on agile design
DRY - Don't repeat yourself
YAGNI - You aren't gonna need it
OCP - Open Closed Principle
LSP - Liskov's substitution principle
DIP - Dependency inversion principle ( used in creating enumerators for various classes such as ArrayList, queue...)
Will expand on these as time goes.
Amazing shows, hail dnrtv.
Labels: agile, javascript, validation
Monday, July 16
Using HTTP Handler for dynamic image generation
One of the ways to achieve this is to create the image server side, store it on the disk on server and set the ImageUrl property of the image on the page to that saved image and send it to the browser.
This approach works but leads to addditional maintenance tasks, such as cleaning up old images, managing disk space etc...
One of the short comings of the asp.net image control Vs the image control in WinForms is that it lacks a property called "Bitmap" which allows you to assign a dynamically generated bitmap to the image control.
The only property exposed is the "ImageUrl".
I heard about http handlers and modules in podcats from polymorphic podcasts where Miguel Castro was explaining the use of HttpHandler to process certain file types.
Here is a formal definition from msdn : "An ASP.NET HTTP handler is the process (frequently referred to as the "endpoint") that runs in response to a request made to an ASP.NET Web application. The most common handler is an ASP.NET page handler that processes .aspx files. When users request an .aspx file, the request is processed by the page via the page handler.
HTTP handlers have access to the application context, including the requesting user's identity (if known), application state, and session information. When an HTTP handler is requested, ASP.NET calls the ProcessRequest method on the appropriate handler. The handler's ProcessRequest method creates a response, which is sent back to the requesting browser. As with any page request, the response goes through any HTTP modules that have subscribed to events that occur after the handler has run."
Scott Hanselman says : "Remember, an HttpHandler is the kind of thing you want to use when an HttpRequest is going to return a file or image to the browser. Basically anything other than a standard page. True, you could use a page, remove all the HTML from the ASPX part, and return stuff in Page_Load, but that's not really what pages are for, right? Also, Pages are themselves an HttpHandler (returned by PageHandlerFactory) so why not write your own HttpHandler?"
The processRequest for our bar chart image handler looks like this.
public void ProcessRequest (HttpContext context)
{
mPresenter = new ChartsPresenter(this);
ProcessQueryString(context);
DrawBarChart(context);
}
When the bitmap generation is completed, we output the bitmap in this fashion
context.Response.ContentType = "image/gif";
bitmap.Save(context.Response.OutputStream,
System.Drawing.Imaging.ImageFormat.Gif);
We associate the ImageUrl property of the image to the http handler created to output the bar chart. Here is an abstract base class for creating http handlers that return proper error codes in case of problems. Phil Haack wrote it.
Wednesday, July 11
Databind dropdowns to Enums
Here is how you do it.
20 private enum ReportTypes : int
21 {
22 ByVendor = 1,
23 ByCategory = 2,
24 ByType = 3
25 }
35 protected void Page_Load(object sender, EventArgs e)
36 {
37 if (!IsPostBack)
38 {
44 ddlReportTypes.DataSource = Enum.GetNames(typeof(ReportTypes));
45 ddlReportTypes.DataBind();
46 }
47 }
48 protected void ddlReportTypes_SelectedIndexChanged(object sender, EventArgs e)
49 {
50 ReportTypes rType =
51 (ReportTypes)Enum.Parse(typeof(ReportTypes), ddlReportTypes.SelectedValue);
52 switch (rType)
53 {
54 case ReportTypes.ByVendor:
56 break;
57 case ReportTypes.ByCategory:
60 break;
61 case ReportTypes.ByType:
62 break;
63 }
64 }
Wednesday, July 4
Web.Config Gotcha
10 <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
Removing the xmlns attribute from the configuration tag brings back the intellisense for the Web.Config.
10 <configuration>
I saw this on one of the dnrtv shows, so credit goes to the author Miguel Castro.
Labels: gotcha
Tuesday, July 3
Setting up Windows Authentication for Intranet Websites
Recently I was put on a project that needed to harness the built in windows security for user authentication. Idea was to allow access only tousers of subscribed to certain groups. Once authenticated, based on the group the user is subscribed to, I needed to perform custom actions.
The configuration started with the Web.Config. I added the authentication andauthorization sections to the Web.Config, specifying the authentication type and the groups authorized to access the site.
We deny access to anonymous users. Also, with the "Impersonate clause" we tell ASP.NET
to run using the permission/priveledges of the authenticated user
instead of the default asp_net user.
37 authentication mode="Windows"
38 authorization
39 allow roles="MSDomain\Buyers,MSDomain\Clerks,MSDomain\Receivers"
40 deny users="*"
41 <>authorization
42 identity impersonate="true"
In order to be able to find out whether a user belongs to a particular group and to get a list of groups a user is subscribed to, we needed to
specify a "roleManager" config section and set the default provider to "AspNetWindowsTokenRoleProvider". Until this is done, the any code written
to check whether the user is part of a group/list of groups will not work.
"Role Manager" helps us manage groups(roles) and perform group based authorization
in the applicaion. We need the role manager to help us identify the groups of which the authenticated user is a part of and perform actions like wise.
"The main benefits of using role manager are that it allows you to look up users' roles without writing and maintaining code. Additionally, the
role providers offer a consistent way for you to check the role membership of your users, regardless of the underlying data store. Therefore,
if your role store were to change tomorrow, you would only need to change the configuration settings to make your code work."
roleManager enabled="true" defaultProvider="WindowsTokenRoleProvider" >
The default role providers are as follows:
In my case, all I needed was to redirect user to corresponding portion of the site depending on their role, hence read-only role provider was1. SqlRoleProvider
- role information kept in SQL Server
2. WindowsTokenRoleProvider
- read-only provider that retrieves role information for a
Windows user account based on the account's Windows security
group membership
3. AuthorizationStoreRoleProvider
- used if your application uses Authorization Manager (AzMan)
sufficient.
Msdn article says "The Windows security system acts as role store for this
provider, so no additional configuration is required to set up the role store"
Once the user is authenticated, we need to check if the user is part of a particular group, if yes, then perform the custom action.
Below is the code required to validate whether a user is part of a inranet group.
120 if (User.IsInRole (WindowsGroupSettings.SettingFor.Buyers))
121 {
122 if (this.LoadPricesForBuyer != null)
123 {
124 _buyerName = User.Identity.Name;
125 LoadPricesForBuyer(this, EventArgs.Empty);
126 }
127 }
To get a list of groups a user is part of use the following code:
140 if (!IsPostBack)
141 {
142 gvRoles.DataSource = Roles.GetRolesForUser(User.Identity.Name);
143 gvRoles.DataBind();
149 }
Notice that I have used the WebNavigator, MVP pattern in this project. :)
I am having a torrid time fighting the fonts/html in post that contain code copied using copySourceAsHtml,
especially code containing tags.
Labels: intranet applications, roles, windows authentication
Thursday, June 28
ASP.Net FormView Control.
319 asp:FormView ID="fvExceptionDetails" runat="server"/asp:
320 AllowPaging="true" DataKeyNames="Oid"
321 OnModeChanging="fvExceptionDetails_ModeChanging"
322 OnPageIndexChanging="fvExceptionDetails_PageIndexChanging"
323 OnItemUpdating="fvExceptionDetails_ItemUpdating">
324 ItemTemplate
325 /ItemTemplate
326 EditTemplate
327 /EditTemplate
328 FormView>
261 protected void fvExceptionDetails_PageIndexChanging(object sender,
262 FormViewPageEventArgs e)
263 {
264 fvExceptionDetails.PageIndex = e.NewPageIndex;
265 DataBindExceptionDetails();
266 }
267 ///
268 /// event invoked only when mode changed through UI.
269 ///
270 ///
271 ///
272 protected void fvExceptionDetails_ModeChanging(object sender,
273 FormViewModeEventArgs e)
274 {
275 fvExceptionDetails.ChangeMode(e.NewMode);
276 if (e.NewMode == FormViewMode.Edit)
277 {
278 fvExceptionDetails.AllowPaging = false;
279 }
280 else
281 {
282 fvExceptionDetails.AllowPaging = true;
283 }
284 if (e.NewMode != FormViewMode.Insert)
285 {
286 DataBindExceptionDetails();
287 }
288 SetJSonclickAttribute();
289 }
322 protected void fvExceptionDetails_ItemUpdating(object sender,
323 FormViewUpdateEventArgs e)
324 {
325 //perform update logic here.
326 fvExceptionDetails.ChangeMode(FormViewMode.ReadOnly);
327 fvExceptionDetails.AllowPaging = true;
328;/span> DataBindExceptionDetails();
329 }
I hope this implementation detail helps. One thing to note would be that I was not using an ObjectDataSource/SqlDataSource to populate the Detailsview.
Sunday, June 24
ASP.Net Page Cycle
Here is the sequence of events and a brief description of the critical ones. I haven't had the chance to use of all of them as yet.
Order top to bottom
PreInit (method: Page_PreInit)
InitThemes and master pages are applied between PreInit and Init, hence PreInit is the last place to programtically modify the selected theme/masterpage. When implmenting "Nested Master pages" while maintaining the ability to see pages in design mode in VS 2005, one needs to set the the change the page's current master page ( the base master page) to the nested master page using this event.
This event is called before any state is restored from the
client response. It is used to prepare the Page for processing the request. Dynamic controls can be added in this event.
Child controls are created between this event and the "InitComplete" event if it is a postback. Also, Control/View State is loaded if it is a postback.
Load
Most commonly used event. It is used to initialize control values on a GET request (!IsPostBack). It is called after
the control/view state has been restored in the Init event on a POST request (IsPostBack) before control passes to the specific event that caused the postback.
To be used to move code from the PreRender event,
the place to make last minute changes to controls.
Used to make any post-event modifications to the controls (Last place to make a change before they get rendered). Recently, I created an editable gridview consiting of 2 columns, one a "State" dropdown and the other "Type" dropdown whose content needed to be changed based on the state selected. I had a Telerik RadAjaxPanel around the Grid and wanted to change the content of the "type" dropdown based on the selection in the "State" dropdown. I had specifically used the PreRender event to tie the "State" dropdown to the "Type" dropdown for every row in the Grid.
Render
UnLoad
Tuesday, June 12
Safari Beta 3 for PC released
A substantial amount of education related community use the mac's and we had a lot of requests to make the sites "Safari" compatible.
This is a big player entering the pc browser market and should make things interesting.
Get it at Safari Beta 3 for PC
Saturday, June 9
Asp.net Release mode Request timeout
Upon talking to an Architect in the company it dawned upon me that there ASP.NET has something called "Request Timeout" (seperate than Session timeout) and this varies between the debug and the release mode. For the debug mode, the duration is a year while for release mode the request timeout is 90 seconds. Hence the abrupt request termination.
He pointed me to this:
Code Better: Peter Gekko: Timeout of an asp.net page
In short the code looks like this:
279 protected override void OnInit(EventArgs e)
280 {
281 timeOut = Server.ScriptTimeout;
282 // Give it 5 hour = (3600 * 5) = 18000 seconds
283 Server.ScriptTimeout = 18000;
284 }
This task can be completed using an ASP.NET Async page or by spawning a separate thread/process. I will make a post on that experience. Till then, this is workable.
Friday, June 8
Javascript gotcha
Please overlook the missing "<" at the start of the script tags, since blogger understandingly has issues with script tags.
script src="../jscalender-1.0/calender.js" />
script src="../jscalender-1.0/calender/look.js" />
script src="../jscalender-1.0/calender/feel.js" />
script language="javascript" type="text/javascript">
function showCalender()
{
}
/script>
In spite of the rendered page containing the above script blocks, the showCalender function was not found and I kept getting a runtime javascript error: Object not found.
IE provided no clues about what is happening, finally when I looked at the source in Firefox with the color scheme, it dawned upon me that only the first script tag is being recognized while the rest are being ignored.
When I changed them to:
script src="../jscalender-1.0/calender.js"> /script>
script src="../jscalender-1.0/calender/look.js" > /script>
script src="../jscalender-1.0/calender/feel.js" > /script>
script language="javascript" type="text/javascript">
function showCalender()
{
}
/script>
So the moral is, close the JavaScript tags with /script> even though the /> might work in certain cases, it baffles you in cases like this.
Saturday, June 2
Books and Tree Surgeon
He says on recruiting, he only looks for 2 qualities in "Smart" and "gets things done".
I also like his "Joel Test" for evaluating employers. Quoting him:
1.Do you use source control?
2.Can you make a built in one step?
3.Do you make daily builds?
4.Do you have a bug database?
5.Do you fix bugs vefore writing new code?
6.Do you have an up-to-date schedule?
7.Do you have a spec?
8.Do programmers have a quite working conditions?
9.Do you use the best tools money can buy?
10.Do you have testers?
11.Do new candidates write code during their interview?
12.Do you do hallway usability testing?
Also interesting is his idea about "hallway usability testing", which I actually implemented on a recent project. Its amazing how much input you get from fellow developers, their criticism, ideas to make the ap better. Hallway testing will stay with me forever.
I recently bought Code Complete, Jeff Atwood swears by this book. I want to read this book, its a big one. He considers it as the bible for all software developers.
I went to Barnes and nobles to read a book called Head First Design Patterns, I really liked the book and concepts were explained so beautifully. I just read about the "Strategy Pattern" and loved the way they presented the materials. I liked the line "Just because you know every OO concept doesnt mean you know how to use they".
some of the concepts I can still remember are
Encapsulate everything that changes
Use Composition over inheritance
Code to Interfaces and not implementations.
I came accross an amazing tool called "Tree Surgeon" which creates a development tree for you. just give it a project name and "voila" it creates a development tree for your project. One of the criticism asp.net received from David Heinemeier Hansson was that asp.net gives you a clean slate when you start with a new project. One has to be knowledgeble enough to setup the testing framework, business layer, build project. If you are new to .Net and not fortunate enough to have a good mentor, you would probably end up with a bloated project. Tree Surgeon does all that for you.
I am going to try and use it in some home project, probably a project to do an existing project using the MVP pattern. I will report my findings.
It will also introduce me to NAnt build system. I have only been using VS 2005 for building my projects uptill now.
Friday, June 1
IIS User
Well, it turns out that it runs under ASPNET in XP (which most developers have) but runs under "Network Service" in Win 2003 which most servers have. I was setting an old website for maintainance purposes and the IIS user needed write permission to a certain folder (for ActiveReports PDFs to be written) .
Cassini, the internal web server for VS 2005 seemed to have access to that folder fine. I then setup a virtual dir for this project on my local IIS and gave ASPNET user write access and it worked. It took me a while to realise that under Win 2003, IIS runs under "Network Service".
Anyways, here is an article about it.
How To: Use the Network Service Account to Access Resources in ASP.NET
Wednesday, May 23
Mozilla Blogspot Issue
I am having this weird issue with Mozilla not able to display the html spurted out by CopySourceAsHtml utility and it happens only with the first post with html created by CopysourceAsHtml.
IE displays the posts correctly. Will have to look into this.
Compact Framework : Table Exist Method
I had a condition where I needed to I needed to check if a certain table existed on the pda database and if not then pull it from the server. I needed a table exist method and wanted to avoid the try catch code block which I have seen in use to derive that a table doesn't exist if you get a exception on something like this
'select (count(*) from premiums;'
I knew there would be a cleaner way to know if a table exist in a database or not.
Here is the method :
We query the meta data and get a clean answer, no try/catch needed derive the answer.
430 ///
431 /// Queries the information schema to find whether a table exists or not
432 ///
433 ///
434 ///
435 private bool TableExists(string table)
436 {
437 bool retAnswer = false;
438 try
439 {
440 int exist = (int)ConnectionManager.DBInfoConnection.ExecuteScalar(
441 "SELECT count(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='" + table + "'");
442 if (exist == 1)
443 retAnswer = true;
444 }
445 catch (Exception ex)
446 {
447 GenericLogger.Error("Could not query database for list of tables", ex);
448 }
449 return retAnswer;
450 }
Please ignore the non use of SqlParameters. I had to add this as a maintainence method in an
2-3 years old app and when you have to decide between your urge to make drastic(essential)
changes to a system and the number of hours that have been alotted
to this task, I think pragmatism wins.
Sunday, May 20
Visual Studio Must have tools & blog roll
Scott Hanselman's list of power tools
He has a important take on blogging. He rightfully contends that you will have returning audience only if your blog content is well formatted/indented and easy on the eyes.
I have started using the CopySourceAsHtml VS2005 plugin to do code blog posts. As you can see, I need to clean up old code posts on this blog and use the tool above to have the posts easy on the eyes.
I also like Jeff Atwood's writing, he says make it a habit to blog atleast once a week and make a commitement, since interpersonal and communication skills are so important and needs to honed with time. He writes on human factors in software development.
You can't miss Joel Spolsky author of the blog Joel on Software. His books are hilarious and fun to read.
I listen to Craig Shoemaker as often as I can. His show/blog is essential for every asp.net developer. He has the knack to explain beautifully the why/how/where approach for a solution.
Most podcasts/screencasts assume you know about things, while he explains things from the ground up.
One cannot miss the blog of the ASP.Net guru Scott Guthrie for ASP.Net tricks, tips, hacks, patches and advice.
I like to read blog by Jean Paul Boodhoo for knowledge about Test Driven Development and pattern based development.
I also sometimes refer to Scott Mitchel's blog. Scott, is a ASP.NET guru and consultant. He has an excellent series on "Working with Data in ASP.NET 2.0".
I will be editing this list this week, it is no way near completion.
Thursday, May 17
Sanitization against Sql injection attacks.
Here is what I use to sanitize my text input before inserting into DB. Most of the code is from a msdn article on how to avoid sql injection attacks.
29 ///
30 /// make search text input sql safe.
31 ///
32 ///
33 ///
34 private static string SafeSqlLikeClauseLiteral(string inputSQL)
35 {
36 // Make the following replacements:
37 // ' becomes ''
38 // [ becomes [[]
39 // % becomes [%]
40 // _ becomes [_]
41
42 string s = inputSQL;
43 s = inputSQL.Replace("'", "''");
44 s = s.Replace("[", "[[]");
45 s = s.Replace("%", "[%]");
46 s = s.Replace("_", "[_]");
47 return s;
48 }
49 ///
50 /// make text input sql safe
51 ///
52 ///
53 ///
54 private static string SafeSqlLiteral(string inputSQL)
55 {
56 return inputSQL.Replace("'", "''");
57 }
58 ///
59 /// convert '' to ' when returning to the user, Remember, only to be used
60 /// when returning strings to user.
61 ///
62 ///
63 ///
64 private static string Desanitize(string output)
65 {
66 return output.Replace("''", "'");
67 }
Wednesday, November 29
Group Number in SQL Reporting Services
I was grouping data in a table in a SQL report. I could successfully add row numbers to the details of the group but was unable to add row numbers to group header.
Something like this
1 ClaimID1
1
2
3
2 ClaimID2
1
2
3
4
5
3 ClaimID3
1The following expression helped adding the row number for the groups
=RunningValue(Fields!ClaimID.Value, CountDistinct, Nothing)
Friday, November 3
javascript Trim method
This script will strip starting and ending spaces for you..
72 // JScript File
73 //javascript left & right trim similar to stringObj.Trim() in C#
74 function trimAll(sString)
75 {
76 while (sString.substring(0,1) == ' ')
77 {
78 sString = sString.substring(1, sString.length);
79 }
80 while (sString.substring(sString.length-1, sString.length) == ' ')
81 {
82 sString = sString.substring(0,sString.length-1);
83 }
84 return sString;
85 }
Tuesday, October 3
Detecting Session Timeout in Asp.Net
I stumbled upto this code (it works) which helps detect a session timeout in asp.Net.
One needs to follow the common BasePage pattern and inherit all the pages from this common page.
All the common functions can be put in this page.
///
/// This overriden method helps handle Session timeouts.
/// Credit to author.
///
///
84 /// <summary>
85 /// This overriden method helps handle Session timeouts.
86 /// </summary>
87 /// <param name="e"></param>
88 override protected void OnInit(EventArgs e)
89 {
90 base.OnInit(e);
91
92
93 //It appears from testing that the Request and Response both share the
94 // same cookie collection. If I set a cookie myself in the Reponse, it is
95 // also immediately visible to the Request collection. This just means that
96 // since the ASP.Net_SessionID is set in the Session HTTPModule (which
97 // has already run), thatwe can't use our own code to see if the cookie was
98 // actually sent by the agent with the request using the collection. Check if
99 // the given page supports session or not (this tested as reliable indicator
100 // if EnableSessionState is true), should not care about a page that does
101 // not need session
102 if (Context.Session != null)
103 {
104 //Tested and the IsNewSession is more advanced then simply checking if
105 // a cookie is present, it does take into account a session timeout, because
106 // I tested a timeout and it did show as a new session
107 if (Session.IsNewSession)
108 {
109 // If it says it is a new session, but an existing cookie exists, then it must
110 // have timed out (can't use the cookie collection because even on first
111 // request it already contains the cookie (request and response
112 // seem to share the collection)
113 string szCookieHeader = Request.Headers["Cookie"];
114 if ((null != szCookieHeader) && (szCookieHeader.IndexOf("ASP.NET_SessionId") >= 0))
115 {
116 //string url = "~/Default.aspx?x=" + RedirectMessage("Session Timed out.");
117 //Response.Redirect(url);
118 Session["TimeoutMessage"] = "Your Session timed out";
119 Response.Redirect("~/Default.aspx");
120 }
121 }
122 }
123 }
Subscribe to Posts [Atom]