Monday, December 21, 2009

WARNING: Request.ApplicationPath and Forms Authentication

In previous post I have made some remarks about using Request.ApplicationPath concatenation with app. running in the root.

Another risc with this approach is related to "cookieless Form based autentication". In this case URLs contain auth. token as part of the URI path. However Request.ApplicationPath does not contain this token segment.

Thus using this "fixed: version of concat:

HyperLink2.NavigateUrl = Request.ApplicationPath.Length > 1 ? Request.ApplicationPath + "/foobar.txt" : "/foobar.txt";
is also incorrect, and will produce link without the auth. token.

Thursday, December 10, 2009

loadXml MAY involve network activities

Argument that MSXML.loadXML cannot be async, because it is loading string and does not involve networking activity (which only can be async) is a bit wrong:

loadXML with string

<!DOCTYPE page [
<!ENTITY ent1 "internal">
<!ENTITY ent2 SYSTEM "test2.xml">

will cause request to URL test2.xml (resolved against URI of the current page).
So Yes there is network activity with loading strings !.

Anyway even this scenario seems to behave synchronously (loadXml is blocking) even with async=true ;-)

"More on XML entities", and "Damned Defaults" are comming soon.... keep in touch

Monday, December 7, 2009

Anti-Sample Of The Day - Request.ApplicationPath +"/mypath"

Imagine the following 3 alternatives of setting link URI:

<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/foobar.txt" Text="asp:HyperLink ~foobar.txt"/><br/>
<asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl="" Text="HyperLink2.NavigateUrl = Request.ApplicationPath + '/foobar.txt';"/><br/>
<a href="<%=Request.ApplicationPath+"/foobar.txt"%>">Request.ApplicationPath+"/foobar.txt"</a>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
HyperLink2.NavigateUrl = Request.ApplicationPath + "/foobar.txt";

Run under /sample application (seems fine):

Run under / (breaks links 2,3):

Source: MSDN, search for ApplicationPath samples. Or one is located directly under ApplicationPath docs:
with small excuse in Remarks section
Use this property to construct a URL relative to the application root from a page or Web user control that is not in the root directory.
BTW: In "equivalent Servlet API" getContextPath()" they have made decision elminating this sort of concat mistake:
The path starts with a "/" character but does not end with a "/" character. For servlets in the default (root) context, this method returns "".

Prove Me Wrong, please - First line of HTTP request

There is no reliable way to retrieve EXACT form of URI specified in the first line of HTTP request.
This applies to Servlet API (need for Cross-Container solution working at Tomcat, WebSphere 6.0.2,6.1,7.x , and others), as well as to ASP.NET Runtime (2+) on IIS 5.1 (and maybe others not tested) with standard modules in action.

GET /UriHandler.aspx/[%5d HTTP/1.1

Exected result:

Mission: tell me THE MAGIC API to achieve this.

Also wanted: description and comparative tables describing IIS and ASP.NET URL normalization with IIS 5,6,7, with/without URLScan and other URL related HTTP.sys and other settings. I mean complete IIS URL handling stack for all IIS versions ;-)

Friday, December 4, 2009

Anti-sample Of The Day - Cast, Null reference, If Too Late

Unbelievable what we can find on the net :-(

public void Init(HttpApplication context){
context.BeginRequest += delegate(Object sender, EventArgs ea) {
HttpApplication ha = sender as HttpApplication;
String absoluteUrl = ha.Context.Request.Url.ToString( ).ToLower( );
if (ha != null) {

Sample is called "Real World HttpModule Examples", subtitle of the web site is "... Home for AJAX, Silverlight, and .NET Technology, Architecture, and Elegance" Date of publishing 2007.
More bad news, author is MVP [ASP.NET] ;-(

Wednesday, December 2, 2009

loadXML,load(uri),load(dom) sync or async ?

This post is to clarify some of my statements presented in webreflection blog comments (do not want to waste your space Andrea).

"Official Documentation" (more cookbook than API specification)

Question: is it guaranteed by "specification" that dom.loadXML is blocking regardless on dom.async property ? Do I have to write dom.async=false to perform intentional synchronous load of xml string ?

(not)Final Note

Since I have failed to "clearly" decrypt the documentation wording to come up with presentable argument I provide tests: Experiments show that current implementation of MSXML (all tested versions) show:
  • async=false - load(uri) - IS BLOCKING
  • async=true - load(uri) - IS NONBLOCKING
  • async=true - load(dom) - IS BLOCKING (logical ?, documented ?)
  • async=true - loadXML(string) - IS BLOCKING (logical ?, documented ?)

Usage of onreadystatechange is available in both async, and sync modes.
Would you write different code for load(uri) and load(dom/stream) ?
I do not.

For intentionaly synchronous code I will write async=false before any load (loadXml/load(dom)/load(uri))
and will continue processing after load exits (even if "runtime behavior" shows async=false as unnecesary for loadXml/load(dom)).

For intentionaly asynchronous code I will write async=true before any load (loadXml/load(dom)/load(uri))
(even if it's default) and will use readystatechange, and will not rely on load blocking (even if "runtime behavior" show that loadXml/load(dom) blocks).

Argument that loading string cannot be asynchronous is naive, anything can be made asynchronous even i++ if component designer decides to be and language + runtime features alow that ;-)

loadXmlIsSAsync.js (testcase)

/** loadXml - blocking, async propery ignored ? load(DOM) - blocking, async propery ignored ? load(uri) - blocking/nonblocking, async propery honored **/ function main() { var progids= [ "Msxml.DOMDocument", "Msxml2.DOMDocument", "Msxml2.DOMDocument.3.0", "Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.6.0", "Msxml2.FreeThreadedDOMDocument.3.0", "Msxml2.FreeThreadedDOMDocument.4.0", "Msxml2.FreeThreadedDOMDocument.5.0", "Msxml2.FreeThreadedDOMDocument.6.0" ]; var depth=200,width=200; var line=nTimes("<test>",depth)+nTimes("</test>",depth); var strXml= "<root xmlns:xsi=''>" +nTimes(line,width) +"</root>"; for(var i=0;i<progids.length;i++) { //loadXML(str) var dom1s=loadXml(progids[i],false,strXml); var dom1a=loadXml(progids[i],true,strXml); // load(dom) var dom2s=load(progids[i],false,dom1s); var dom2a=load(progids[i],true,dom1s); //load(url) var dom3s=load(progids[i],false,"loadXmlIsAsync.xml"); //200x200 size var dom3a=load(progids[i],true,"loadXmlIsAsync.xml"); print([]); } } function loadXml(progid,async,strXml) { var _dbg=["\r\n"+progid+".loadXml(strXml) "+async]; var xml=new ActiveXObject(progid); xml.onreadystatechange=function() { _dbg.push("rsch:"+xml.readyState); //window.confirm(); } xml.async=async; var success=xml.loadXML(strXml); _dbg.push("success:"+success); _dbg.push("xml.async:"+xml.async); _dbg.push("xml.readyState:"+xml.readyState); _dbg.push("xml.length:"+xml.xml.length); _dbg.push("xml.parseError:"+xml.parseError+","+xml.parseError.reason); print(_dbg); return xml; } function load(progid,async,xmlSource) { var _dbg=["\r\n"+progid+".load("+(typeof xmlSource=="string"?"url":"dom")+") "+async]; var xml=new ActiveXObject(progid); xml.onreadystatechange=function() { _dbg.push("rsch:"+xml.readyState); //window.confirm(); } xml.async=async; var success=xml.load(xmlSource); _dbg.push("success:"+success); _dbg.push("xml.async:"+xml.async); _dbg.push("xml.readyState:"+xml.readyState); _dbg.push("xml.length:"+xml.xml.length); _dbg.push("xml.parseError:"+xml.parseError+","+xml.parseError.reason); print(_dbg); return xml; } function nTimes(str,n) { var buff=new Array(n); for(var i=0;i<n;i++){buff[i]=str;}; return buff.join(""); } var print; if(typeof window != 'undefined') { print=function(_dbg) { document.getElementsByTagName("body")[0].innerHTML+=("<HR>"+_dbg.join("<BR>")); } window.onload=function() { main(); } } else { print=function(_dbg) { WScript.Echo(_dbg.join("\r\n")); } main(); }

Tuesday, December 1, 2009

Lamport's Bakery algorithm in JavaScript

This paper presents implementation of the original Lamport's Bakery algorithm [1] in JavaScript language. Our goal was to implement clear and simple rewrite of the original pseudo-code [1] to JavaScript, with maximum stress to similarity. With this in mind, the algorithm can be verified using the original proof of correctness [1]. We also provide test case showing that "synchronization" may be necessary in certain browsers and our bakery implementation can be used as possible solution. We believe that implemented solution is much more elegant, readable and correct than the existing Wallace variation [2] widelly spread in the web.