
Friday, September 15, 2006
Tuesday, September 12, 2006
Ready Set Grow case study from Microsoft
I was searching for some MSFT article for the F5 IIS session bump issue and sporadically searched for schwan and landed in the RSG case study. Not sure this is only version MSFT has.
Right bar lists, Microsoft BizTalk Server 2006 & Microsoft Visual Studio 2005 in products and technologies. Hmm how come VS2005 & Biz2006 was used, when we started project in Jan '04
:-)
Right bar lists, Microsoft BizTalk Server 2006 & Microsoft Visual Studio 2005 in products and technologies. Hmm how come VS2005 & Biz2006 was used, when we started project in Jan '04
:-)
Labels:
RSG
Thursday, September 07, 2006
ASP.net session bump/hijack issue - F5 & IIS cluster
I haven't seen this issue personally, but it is confirmed from multiple sources this happens. In short: user rarely bumps into another user's session, in verbose: user logs into web app and uses it for a while and all of a sudden gets data that is not in his session.
Current prod infrastructure is IIS cluster behind F5. Session affinity is set to 20 mins and IIS session time-out is set 20 mins. Session location is in-proc.
I have seen request getting postedback to different webserver and hence viewstate validation fail with exception CryptographicException: Bad Data. Authentication of viewstate failed. ...
i don't know how F5 works but i guess F5 lost identifier of the user and hence thinks it as new user and routes request to different web server. This is a normal issue and we can either turnoff viewstate encryption or explicitly specify viewstate encryption key in all servers in cluster.
But i have to totally rule out F5 from the session bump/hijack issue, 'coz F5 has no idea what asp.net session is, that is something internal to aspnet_wp.exe (IIS5) or w3wp.exe (IIS6).
Under the hood, aspnet maintains the session id using ASP.NET_SessionId cookie and IIS can guarantee its uniqueness across its requests. Here is an MSFT KB about reusing session id for apps in same DNS domain and this article explains behind the scene how asp.net serves request.
I'm guessing this could be the cause,
userA hits webserver1 in cluster in the initial request and F5 should take us to the same server for subsequent requests.
If F5 sends the userA's request to webserver2 in middle of the session, and by happenstance (theoretically this may be possible) userA's ASP.NET_SessionId is already assigned by webserver2 to some other user (say userB), then aspnet engine will think userA as userB and assign userB's sessionstate to this request.
Pls leave a note if you think this may be possible or how you think this could be happening.
I expect IIS team to provide option to make the sessionid unique in a cluster environment. For now what we planned is to generate a unique sessionid and store it in cookie as well as session, check if they match for every request, if not kill the session, this is going to kill both user's session, but i don't know if there is any way out.
I didn't want to include tis logic in existing app 'coz 1 i'll have to include this logic in every app i write and 2 i'm too lazy. I wrote following HTTPModule and hooked it to web app, ideally something like this should be configured in machine.config so that we don't need to do this every web.config, netiher i don't have authority nor i want to pursue this.
Right now code is written to send a mail when something like this happens (just dropping a line to see if something takes this bait) and it will redirect to itself, so page is written poperly to handle empty session which i expect to be a norm.
using System;
using System.Web;
using System.Web.SessionState;
namespace KCC
{
public class SessionCheck : IHttpModule
{
public SessionCheck() {}
public void Dispose() {}
public void Init(HttpApplication httpApp)
{
httpApp.PreRequestHandlerExecute += new EventHandler(this.PreRequestHandlerExecute);
if (httpApp.Modules["Session"] != null)
{
SessionStateModule session = (SessionStateModule) httpApp.Modules["Session"];
session.Start += new EventHandler(this.OnSessionStart);
}
}
public void OnSessionStart(object sender, EventArgs e)
{
HttpCookie sessionChk = new HttpCookie("KCC.SessionCheck");
sessionChk["iSAS.SessionID"] = Guid.NewGuid().ToString();
sessionChk["iSAS.MacName"] = System.Environment.MachineName;
sessionChk["iSAS.SesStrtTmstmp"] = System.DateTime.Now.ToString();
HttpContext.Current.Response.AppendCookie(sessionChk);
HttpContext.Current.Session["iSAS.SessionID"] = sessionChk["iSAS.SessionID"];
}
private void PreRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication httpApp = (HttpApplication) sender;
HttpSessionState session = httpApp.Context.Session;
if (session != null) //skip pages which don't use session
{
if(session["iSAS.SessionID"] != null) //skip if session value is empty
{
if (!httpApp.Context.Session.IsNewSession) //skip if new session
{
string szCookieHeader = System.Web.HttpContext.Current.Request.Headers["Cookie"];
if ((null != szCookieHeader) && (szCookieHeader.IndexOf("ASP.NET_SessionId") >= 0)) //skip if new session 2
{
if (httpApp.Request.Cookies["KCC.SessionCheck"] != null) //skip ifCookie not found
{
if (httpApp.Request.Cookies["KCC.SessionCheck"]["iSAS.SessionID"] != null) //skip if cookie data not found
{
if (session["iSAS.SessionID"].ToString().Trim() != httpApp.Request.Cookies["KCC.SessionCheck"]["iSAS.SessionID"].ToString().Trim())
{
System.Text.StringBuilder info = new System.Text.StringBuilder();
if (httpApp.Request.Cookies["KCC.SessionCheck"]["iSAS.SesStrtTmstmp"] != null)
info.Append("Session start time: " + httpApp.Request.Cookies["KCC.SessionCheck"]["iSAS.SesStrtTmstmp"].ToString());
info.Append("<br/>");
if (httpApp.Request.Cookies["KCC.SessionCheck"]["iSAS.MacName"] != null)
info.Append("Session start web server name: " + httpApp.Request.Cookies["KCC.SessionCheck"]["iSAS.MacName"].ToString());
info.Append("<br/>");
info.Append("Current time " + System.DateTime.Now.ToString());
info.Append("<br/>");
info.Append("Current web server " + System.Environment.MachineName);
info.Append("<br/>");
info.Append("Logged on NTID" + httpApp.Context.Request.ServerVariables.Get("LOGON_USER").ToString());
info.Append("<br/>");
if (session["NTID"] != null) info.Append("Current NTID in session" + session["NTID"].ToString());
info.Append("<br/>");
info.Append("URL " + httpApp.Request.Url.ToString());
info.Append("<br/>");
System.Web.Mail.MailMessage msg = new System.Web.Mail.MailMessage();
msg.To = "me@mail.com";
msg.Subject = "-- SESSION HIJACK ISSUE --";
msg.From = "me@mail.com";
msg.Body = info.ToString();
msg.BodyFormat = System.Web.Mail.MailFormat.Html;
try
{
System.Web.Mail.SmtpMail.SmtpServer = "mailhost.com";
System.Web.Mail.SmtpMail.Send(msg);
}
catch //do nothing
{}
httpApp.Context.Response.Cookies["KCC.SessionCheck"].Expires = DateTime.Now.AddYears(-1);
session.Abandon();
httpApp.Context.Response.Write(httpApp.Context.Request.Url.AbsoluteUri.ToString());
httpApp.Context.Response.Redirect(httpApp.Context.Request.Url.AbsoluteUri.ToString(),true);
httpApp.CompleteRequest();
}
}
}
}
}
}
}
}
}
}
For further reading, Foiling Session Hijacking Attempts and HTTP application executes events sequence.
Current prod infrastructure is IIS cluster behind F5. Session affinity is set to 20 mins and IIS session time-out is set 20 mins. Session location is in-proc.
I have seen request getting postedback to different webserver and hence viewstate validation fail with exception CryptographicException: Bad Data. Authentication of viewstate failed. ...
i don't know how F5 works but i guess F5 lost identifier of the user and hence thinks it as new user and routes request to different web server. This is a normal issue and we can either turnoff viewstate encryption or explicitly specify viewstate encryption key in all servers in cluster.
But i have to totally rule out F5 from the session bump/hijack issue, 'coz F5 has no idea what asp.net session is, that is something internal to aspnet_wp.exe (IIS5) or w3wp.exe (IIS6).
Under the hood, aspnet maintains the session id using ASP.NET_SessionId cookie and IIS can guarantee its uniqueness across its requests. Here is an MSFT KB about reusing session id for apps in same DNS domain and this article explains behind the scene how asp.net serves request.
I'm guessing this could be the cause,
userA hits webserver1 in cluster in the initial request and F5 should take us to the same server for subsequent requests.
If F5 sends the userA's request to webserver2 in middle of the session, and by happenstance (theoretically this may be possible) userA's ASP.NET_SessionId is already assigned by webserver2 to some other user (say userB), then aspnet engine will think userA as userB and assign userB's sessionstate to this request.
Pls leave a note if you think this may be possible or how you think this could be happening.
I expect IIS team to provide option to make the sessionid unique in a cluster environment. For now what we planned is to generate a unique sessionid and store it in cookie as well as session, check if they match for every request, if not kill the session, this is going to kill both user's session, but i don't know if there is any way out.
I didn't want to include tis logic in existing app 'coz 1 i'll have to include this logic in every app i write and 2 i'm too lazy. I wrote following HTTPModule and hooked it to web app, ideally something like this should be configured in machine.config so that we don't need to do this every web.config, netiher i don't have authority nor i want to pursue this.
Right now code is written to send a mail when something like this happens (just dropping a line to see if something takes this bait) and it will redirect to itself, so page is written poperly to handle empty session which i expect to be a norm.
using System;
using System.Web;
using System.Web.SessionState;
namespace KCC
{
public class SessionCheck : IHttpModule
{
public SessionCheck() {}
public void Dispose() {}
public void Init(HttpApplication httpApp)
{
httpApp.PreRequestHandlerExecute += new EventHandler(this.PreRequestHandlerExecute);
if (httpApp.Modules["Session"] != null)
{
SessionStateModule session = (SessionStateModule) httpApp.Modules["Session"];
session.Start += new EventHandler(this.OnSessionStart);
}
}
public void OnSessionStart(object sender, EventArgs e)
{
HttpCookie sessionChk = new HttpCookie("KCC.SessionCheck");
sessionChk["iSAS.SessionID"] = Guid.NewGuid().ToString();
sessionChk["iSAS.MacName"] = System.Environment.MachineName;
sessionChk["iSAS.SesStrtTmstmp"] = System.DateTime.Now.ToString();
HttpContext.Current.Response.AppendCookie(sessionChk);
HttpContext.Current.Session["iSAS.SessionID"] = sessionChk["iSAS.SessionID"];
}
private void PreRequestHandlerExecute(object sender, EventArgs e)
{
HttpApplication httpApp = (HttpApplication) sender;
HttpSessionState session = httpApp.Context.Session;
if (session != null) //skip pages which don't use session
{
if(session["iSAS.SessionID"] != null) //skip if session value is empty
{
if (!httpApp.Context.Session.IsNewSession) //skip if new session
{
string szCookieHeader = System.Web.HttpContext.Current.Request.Headers["Cookie"];
if ((null != szCookieHeader) && (szCookieHeader.IndexOf("ASP.NET_SessionId") >= 0)) //skip if new session 2
{
if (httpApp.Request.Cookies["KCC.SessionCheck"] != null) //skip ifCookie not found
{
if (httpApp.Request.Cookies["KCC.SessionCheck"]["iSAS.SessionID"] != null) //skip if cookie data not found
{
if (session["iSAS.SessionID"].ToString().Trim() != httpApp.Request.Cookies["KCC.SessionCheck"]["iSAS.SessionID"].ToString().Trim())
{
System.Text.StringBuilder info = new System.Text.StringBuilder();
if (httpApp.Request.Cookies["KCC.SessionCheck"]["iSAS.SesStrtTmstmp"] != null)
info.Append("Session start time: " + httpApp.Request.Cookies["KCC.SessionCheck"]["iSAS.SesStrtTmstmp"].ToString());
info.Append("<br/>");
if (httpApp.Request.Cookies["KCC.SessionCheck"]["iSAS.MacName"] != null)
info.Append("Session start web server name: " + httpApp.Request.Cookies["KCC.SessionCheck"]["iSAS.MacName"].ToString());
info.Append("<br/>");
info.Append("Current time " + System.DateTime.Now.ToString());
info.Append("<br/>");
info.Append("Current web server " + System.Environment.MachineName);
info.Append("<br/>");
info.Append("Logged on NTID" + httpApp.Context.Request.ServerVariables.Get("LOGON_USER").ToString());
info.Append("<br/>");
if (session["NTID"] != null) info.Append("Current NTID in session" + session["NTID"].ToString());
info.Append("<br/>");
info.Append("URL " + httpApp.Request.Url.ToString());
info.Append("<br/>");
System.Web.Mail.MailMessage msg = new System.Web.Mail.MailMessage();
msg.To = "me@mail.com";
msg.Subject = "-- SESSION HIJACK ISSUE --";
msg.From = "me@mail.com";
msg.Body = info.ToString();
msg.BodyFormat = System.Web.Mail.MailFormat.Html;
try
{
System.Web.Mail.SmtpMail.SmtpServer = "mailhost.com";
System.Web.Mail.SmtpMail.Send(msg);
}
catch //do nothing
{}
httpApp.Context.Response.Cookies["KCC.SessionCheck"].Expires = DateTime.Now.AddYears(-1);
session.Abandon();
httpApp.Context.Response.Write(httpApp.Context.Request.Url.AbsoluteUri.ToString());
httpApp.Context.Response.Redirect(httpApp.Context.Request.Url.AbsoluteUri.ToString(),true);
httpApp.CompleteRequest();
}
}
}
}
}
}
}
}
}
}
For further reading, Foiling Session Hijacking Attempts and HTTP application executes events sequence.
Labels:
ASP.net
Chennai satellite town
Irrespective of what Ramadoss/JJ/KK thinks about the chennai satellite town, this is going to come up. Reason cited for objection "destroying fertile lands", CRAP! what if NY residents opposed to so called encroachment of urban buildings some 100 yrs back; ok tamil heroine's will have to look for different city to dance around, nothing much.
Current facilities is super sufficent for chennai city (if we can roll back 10 yrs). What leaders don't have is a vision (Dr. APJ strsses this in almost all his speeches), even the most hated Hitler had a vision to make Germany a modern nation, if not they will not have Autobahn now. Hmm, why should J needs to worry if she has to identify something everyday to spit out "arrikai".
Nothing is going to improve if TN politics is going to roll around J & K.
Vande Mataram!
:-s
Current facilities is super sufficent for chennai city (if we can roll back 10 yrs). What leaders don't have is a vision (Dr. APJ strsses this in almost all his speeches), even the most hated Hitler had a vision to make Germany a modern nation, if not they will not have Autobahn now. Hmm, why should J needs to worry if she has to identify something everyday to spit out "arrikai".
Nothing is going to improve if TN politics is going to roll around J & K.
Vande Mataram!
:-s
Labels:
Scraps
Wednesday, September 06, 2006
asp:CustomValidator changing ErrorMessage displayed
requirement: custom validate the amount value; is required only if ddlContributionType value is 2 or 3.
code:
<!-- aspx -- >
<asp:dropdownlist id="ddlContributionType" runat="server">
<asp:textbox id="txtAmount" runat="server">
<asp:customvalidator id="CustomValidateAmount" runat="server" controltovalidate="txtAmount" errormessage="Invalid" clientvalidationfunction="CustomValidateAmount_ClientValidate" onservervalidate="CustomValidateAmount_ServerValidate" />
function CustomValidateAmount_ClientValidate(oSource,oArguments)
{
var ddlContributionType;
if (oSource.getAttribute("ContributionType") != null)
{
ddlContributionType = document.getElementById(oSource.getAttribute("ContributionType"));
}
if (ddlContributionType != null)
{
if ( (ddlContributionType.value != "2") && (ddlContributionType.value != "3") )
{
oArguments.IsValid = true;
return;
}
}
else
{
oArguments.IsValid = true;
return;
}
var amount = oArguments.Value;
oArguments.IsValid = false;
if ( isNaN(amount) == true)
{
oSource.innerHTML = "Invalid amount";
return;
}
var re = new RegExp("^\\d+(\\.\\d{1,2})?$");
m = amount.match(re);
if (m == null)
{
oSource.innerHTML = "Invalid amount format";
return;
}
if ( amount < innerhtml = "Minimum donation of $1 required"> 9999.99 )
{
oSource.innerHTML = "Maximum donation is $9999.99";
return;
}
oArguments.IsValid = true;
}
' .aspx.vb Page_Load
CustomValidateAmount.Attributes("ContributionType") = ddlContributionType.ClientID.ToString()
I explicity not included the check if required for condition 2 or 3, as i re-use an existing validator (RequiredFieldValidatorWithAEnablingCondition) that i developed long back, will mail the code if requested
<KCC:RequiredFieldValidatorWithAEnablingCondition runat="server" ID="RequiredFieldValidatorWithAEnablingConditionAmount" ControlToValidate="txtAmount"
ControlToCompare="ddlContributionType" TriggerValue="2;3" ErrorMessage="Required." />
code:
<!-- aspx -- >
<asp:dropdownlist id="ddlContributionType" runat="server">
<asp:textbox id="txtAmount" runat="server">
<asp:customvalidator id="CustomValidateAmount" runat="server" controltovalidate="txtAmount" errormessage="Invalid" clientvalidationfunction="CustomValidateAmount_ClientValidate" onservervalidate="CustomValidateAmount_ServerValidate" />
function CustomValidateAmount_ClientValidate(oSource,oArguments)
{
var ddlContributionType;
if (oSource.getAttribute("ContributionType") != null)
{
ddlContributionType = document.getElementById(oSource.getAttribute("ContributionType"));
}
if (ddlContributionType != null)
{
if ( (ddlContributionType.value != "2") && (ddlContributionType.value != "3") )
{
oArguments.IsValid = true;
return;
}
}
else
{
oArguments.IsValid = true;
return;
}
var amount = oArguments.Value;
oArguments.IsValid = false;
if ( isNaN(amount) == true)
{
oSource.innerHTML = "Invalid amount";
return;
}
var re = new RegExp("^\\d+(\\.\\d{1,2})?$");
m = amount.match(re);
if (m == null)
{
oSource.innerHTML = "Invalid amount format";
return;
}
if ( amount < innerhtml = "Minimum donation of $1 required"> 9999.99 )
{
oSource.innerHTML = "Maximum donation is $9999.99";
return;
}
oArguments.IsValid = true;
}
' .aspx.vb Page_Load
CustomValidateAmount.Attributes("ContributionType") = ddlContributionType.ClientID.ToString()
I explicity not included the check if required for condition 2 or 3, as i re-use an existing validator (RequiredFieldValidatorWithAEnablingCondition) that i developed long back, will mail the code if requested
<KCC:RequiredFieldValidatorWithAEnablingCondition runat="server" ID="RequiredFieldValidatorWithAEnablingConditionAmount" ControlToValidate="txtAmount"
ControlToCompare="ddlContributionType" TriggerValue="2;3" ErrorMessage="Required." />
Labels:
ASP.net
Monday, September 04, 2006
Is life hitch hiking ?
Today saw Discovery documentry on panspermia, wonder what finally turned out in "kerala red rain". School taught the evolution theory, temple preached "intelligent design", after all who cares about these, idea is to stuff the answer paper and get results in mark sheet.
I think i really didn't take any side here, where do U stand ?
I think i really didn't take any side here, where do U stand ?
Labels:
Scraps
Saturday, September 02, 2006
LDAP authentication in website
Got a requet from a client to provide LDAP authentication in exisiting ASP website, in plain terms authenticate users using thier domain id and password. Initial thought of intergrated win auth was ruled out 'coz of Kiosk based computers used. Should make sure we SSL the page.
'ASP code
Const ADS_SECURE_AUTHENTICATION = &H1
On Error Resume Next
Err.Clear
Set dso = GetObject("LDAP:")
Set domain = dso.OpenDSObject("LDAP://server.com", strUserName, strUserPassword, ADS_SECURE_AUTHENTICATION)
If Err.number <> 0 then
Response.Write("Invalid login. Err.number=" & Err.number)
Else
Response.Write("Valid login. Err.number=" & Err.number)
End If
Set dso = Nothing
Set domain = Nothing
Also same functionality in ASP.net 1.0 http://support.microsoft.com/?id=326340.
'ASP code
Const ADS_SECURE_AUTHENTICATION = &H1
On Error Resume Next
Err.Clear
Set dso = GetObject("LDAP:")
Set domain = dso.OpenDSObject("LDAP://server.com", strUserName, strUserPassword, ADS_SECURE_AUTHENTICATION)
If Err.number <> 0 then
Response.Write("Invalid login. Err.number=" & Err.number)
Else
Response.Write("Valid login. Err.number=" & Err.number)
End If
Set dso = Nothing
Set domain = Nothing
Also same functionality in ASP.net 1.0 http://support.microsoft.com/?id=326340.
Labels:
ASP.net
dinamalar epaper
Its becoming almost an habit to read dinamalar in original paper format. Today i thought of scrapping the content for offline viewing, it was rediculously simple, here goes the code.
using System;
using System.Drawing;
using System.Text;
using System.Net;
using System.IO;
namespace GetDinamalar
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
DoWork();
}
static void DoWork()
{
// /Web/PagePrint/YYYY/MM/DD/DD_MM_YYYY_001.pdf
try
{
int pgCtr=1;
Console.WriteLine("Booting up ....");
string folderpath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location.ToString()),DateTime.Now.ToString("MM.dd.yyyy") );
Directory.CreateDirectory(folderpath) ;
WebProxy proxy = null;
Microsoft.Win32.RegistryKey reg1 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
if (reg1.GetValue("ProxyEnable", "1").ToString() == "1")
{
proxy = new WebProxy("http://" + reg1.GetValue("ProxyServer", "proxy.isas.com:80").ToString(),true,null,CredentialCache.DefaultCredentials);
}
reg1.Close();
while(true)
{
Console.WriteLine("Sending request to web for page " + pgCtr.ToString());
string address = "http://epaper.dinamalar.com/Web/PagePrint/" + DateTime.Now.ToString("yyyy/MM/dd/dd_MM_yyyy_") + pgCtr.ToString().PadLeft(3,'0') + ".pdf";
WebRequest httpRequest = WebRequest.Create(address);
if(proxy != null) httpRequest.Proxy = proxy;
Stream ReceiveStream = null;
try
{
ReceiveStream = httpRequest.GetResponse().GetResponseStream();
}
catch
{
return;
}
string filePath = Path.Combine(folderpath ,DateTime.Now.ToString("yyyy_MM_dd_") + pgCtr.ToString().PadLeft(3,'0') + ".pdf");
FileStream fs = new FileStream(filePath, FileMode.Create,FileAccess.Write);
BinaryWriter binWrt = new BinaryWriter(fs);
binWrt.BaseStream.Seek(0, SeekOrigin.End);
int data=0;
byte [] buffer = new byte [1024];
while ((data=ReceiveStream.Read(buffer,0,1024))>0)
{
binWrt.Write(buffer,0,data);
}
binWrt.Flush() ;
binWrt.Close() ;
pgCtr++;
}
}
catch (Exception exception)
{
Console.WriteLine("Error:" + exception.ToString());
Console.Read();
}
finally
{
Console.WriteLine("Exiting process ...");
}
}
}
}
using System;
using System.Drawing;
using System.Text;
using System.Net;
using System.IO;
namespace GetDinamalar
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
DoWork();
}
static void DoWork()
{
// /Web/PagePrint/YYYY/MM/DD/DD_MM_YYYY_001.pdf
try
{
int pgCtr=1;
Console.WriteLine("Booting up ....");
string folderpath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location.ToString()),DateTime.Now.ToString("MM.dd.yyyy") );
Directory.CreateDirectory(folderpath) ;
WebProxy proxy = null;
Microsoft.Win32.RegistryKey reg1 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
if (reg1.GetValue("ProxyEnable", "1").ToString() == "1")
{
proxy = new WebProxy("http://" + reg1.GetValue("ProxyServer", "proxy.isas.com:80").ToString(),true,null,CredentialCache.DefaultCredentials);
}
reg1.Close();
while(true)
{
Console.WriteLine("Sending request to web for page " + pgCtr.ToString());
string address = "http://epaper.dinamalar.com/Web/PagePrint/" + DateTime.Now.ToString("yyyy/MM/dd/dd_MM_yyyy_") + pgCtr.ToString().PadLeft(3,'0') + ".pdf";
WebRequest httpRequest = WebRequest.Create(address);
if(proxy != null) httpRequest.Proxy = proxy;
Stream ReceiveStream = null;
try
{
ReceiveStream = httpRequest.GetResponse().GetResponseStream();
}
catch
{
return;
}
string filePath = Path.Combine(folderpath ,DateTime.Now.ToString("yyyy_MM_dd_") + pgCtr.ToString().PadLeft(3,'0') + ".pdf");
FileStream fs = new FileStream(filePath, FileMode.Create,FileAccess.Write);
BinaryWriter binWrt = new BinaryWriter(fs);
binWrt.BaseStream.Seek(0, SeekOrigin.End);
int data=0;
byte [] buffer = new byte [1024];
while ((data=ReceiveStream.Read(buffer,0,1024))>0)
{
binWrt.Write(buffer,0,data);
}
binWrt.Flush() ;
binWrt.Close() ;
pgCtr++;
}
}
catch (Exception exception)
{
Console.WriteLine("Error:" + exception.ToString());
Console.Read();
}
finally
{
Console.WriteLine("Exiting process ...");
}
}
}
}
Labels:
.NET
Back from Hibernation :-)
It is almost 3 months i blogged, got myself tied up for happier personal reasons. To re-start with c# (.net 1.x) code to scrap daily dilbert comic and set it as desktop wallpaper.
Due to frequent demand for this, download the application here. Copy GetDilbert.exe to a folder and create a shortcut in windows startup.
using System;
using System.Drawing;
using System.Text;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
namespace GetDilbert
{
class Class1
{
private const int SPI_SETDESKWALLPAPER = 0X14;
private const int SPIF_UPDATEINIFILE = 0X1;
private const int SPIF_SENDWININICHANGE = 0X2;
[DllImport("USER32.DLL", EntryPoint = "SystemParametersInfo", SetLastError = true)]
private static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
[STAThread]
static void Main(string[] args)
{
DoWork();
}
static void DoWork()
{
try
{
Console.WriteLine("Booting up ....");
string address = "http://www.dilbert.com/comics/dilbert/archive/";
WebProxy proxy = null;
WebRequest httpRequest = WebRequest.Create(address);
Microsoft.Win32.RegistryKey reg1 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
if (reg1.GetValue("ProxyEnable", "1").ToString() == "1")
{
proxy = new WebProxy("http://" + reg1.GetValue("ProxyServer", "proxy.isas.com:80").ToString(),true,null,CredentialCache.DefaultCredentials);
}
reg1.Close();
string streamText = null;
Console.WriteLine("Sending request to web ...");
if(proxy != null) httpRequest.Proxy = proxy;
using (StreamReader rdr = new StreamReader(httpRequest.GetResponse().GetResponseStream(), System.Text.Encoding.ASCII))
{
streamText = rdr.ReadToEnd();
}
Console.WriteLine("Scrapping web response ...");
Match match = Regex.Match(streamText,@"/comics/dilbert/archive/images/(\w+).(gifjpg)",RegexOptions.IgnoreCase);
if (match != Match.Empty)
{
string imageLocation = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location.ToString()),"Dilbert_" + DateTime.Now.ToString("MM.dd.yyyy") + ".bmp");
Console.WriteLine("Downloading todays comic ...");
httpRequest = WebRequest.Create("http://www.dilbert.com" + match.Value);
if(proxy != null) httpRequest.Proxy = proxy;
using (Bitmap bmp = new Bitmap(httpRequest.GetResponse().GetResponseStream()))
{
bmp.Save(imageLocation, System.Drawing.Imaging.ImageFormat.Bmp);
}
Console.WriteLine("Setting as desktop wallpaper...");
Microsoft.Win32.RegistryKey reg = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
reg.SetValue("TileWallpaper", "0");
reg.SetValue("WallpaperStyle", "0");
reg.Close();
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, imageLocation, SPIF_UPDATEINIFILE SPIF_SENDWININICHANGE);
Console.WriteLine("Shutting down app.");
}
}
catch (Exception exception)
{
Console.WriteLine("Error:" + exception.ToString());
Console.Read();
}
}
}
}
Due to frequent demand for this, download the application here. Copy GetDilbert.exe to a folder and create a shortcut in windows startup.
using System;
using System.Drawing;
using System.Text;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
namespace GetDilbert
{
class Class1
{
private const int SPI_SETDESKWALLPAPER = 0X14;
private const int SPIF_UPDATEINIFILE = 0X1;
private const int SPIF_SENDWININICHANGE = 0X2;
[DllImport("USER32.DLL", EntryPoint = "SystemParametersInfo", SetLastError = true)]
private static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
[STAThread]
static void Main(string[] args)
{
DoWork();
}
static void DoWork()
{
try
{
Console.WriteLine("Booting up ....");
string address = "http://www.dilbert.com/comics/dilbert/archive/";
WebProxy proxy = null;
WebRequest httpRequest = WebRequest.Create(address);
Microsoft.Win32.RegistryKey reg1 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
if (reg1.GetValue("ProxyEnable", "1").ToString() == "1")
{
proxy = new WebProxy("http://" + reg1.GetValue("ProxyServer", "proxy.isas.com:80").ToString(),true,null,CredentialCache.DefaultCredentials);
}
reg1.Close();
string streamText = null;
Console.WriteLine("Sending request to web ...");
if(proxy != null) httpRequest.Proxy = proxy;
using (StreamReader rdr = new StreamReader(httpRequest.GetResponse().GetResponseStream(), System.Text.Encoding.ASCII))
{
streamText = rdr.ReadToEnd();
}
Console.WriteLine("Scrapping web response ...");
Match match = Regex.Match(streamText,@"/comics/dilbert/archive/images/(\w+).(gifjpg)",RegexOptions.IgnoreCase);
if (match != Match.Empty)
{
string imageLocation = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location.ToString()),"Dilbert_" + DateTime.Now.ToString("MM.dd.yyyy") + ".bmp");
Console.WriteLine("Downloading todays comic ...");
httpRequest = WebRequest.Create("http://www.dilbert.com" + match.Value);
if(proxy != null) httpRequest.Proxy = proxy;
using (Bitmap bmp = new Bitmap(httpRequest.GetResponse().GetResponseStream()))
{
bmp.Save(imageLocation, System.Drawing.Imaging.ImageFormat.Bmp);
}
Console.WriteLine("Setting as desktop wallpaper...");
Microsoft.Win32.RegistryKey reg = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
reg.SetValue("TileWallpaper", "0");
reg.SetValue("WallpaperStyle", "0");
reg.Close();
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, imageLocation, SPIF_UPDATEINIFILE SPIF_SENDWININICHANGE);
Console.WriteLine("Shutting down app.");
}
}
catch (Exception exception)
{
Console.WriteLine("Error:" + exception.ToString());
Console.Read();
}
}
}
}
Labels:
.NET
Monday, May 01, 2006
Microsoft.Web.AJAX

In past i was intrigued by new mail notification feature in Outlook Web Access {tracking back OWA history} and kept wondering on technology behind that.
Enter Google Maps, everything changed after people coined term AJAX . Happen to learn concept of remote scripting in last project which used JSRS technique to get data for dropdowns and help text from server for controls. And i decided to look out for alternatives/options for this new wave (hype?) of web programming model. Ajax.NET Professional seems to be easier to use. But support to asp.net controls are limited, and when googling around that ended up in ASP.Net 2.0 Client Callback feature & Atlas April CTP, Expect Atlas to shadow the limited callback feature of asp.net 2.0
Here is a 18 mins video demo on Developing ASP.NET 2.0 Applications using "Atlas" by Scott G. Its kind-of Houdini show, when you see him write a Todolist web page and AJAX enabling the page, all under 18 mins and without writing a SINGLE line of javascript! I can understand why java community hates MS. Have time? See Atlas in action
From an architect point of view, Ajax usage may probably violate tiered approach and presentation tier code may end up spaghetti, isn't the idea of asp.net code behind model is to avoid this. Atlas overcomes this by providing a declarative programming model for Ajax and enabling use of asp.net server controls
I gotta give credits to MS for developing something like Atlas, even though its an alternative to Smart Client architecture that MS wants to use for rich web apps. But, I'd expect to use this in limited and for appropriate cases and i don't want follow Ajax bandwagon of creating single-page interface application in web, IMHO web apps are not supposed to work that way, rather leverage on Ajax features in cases where it demands like Google Suggest. To end with an interesting fact i happen to learn how Google prevents against excessive queries, mainLoop sets itself up to be called repeatedly using the javascript setTimeout function, instead of keydown events, handling fast typers on slow connections and also timeout interval between calls seems to be dynamic, adjusted according to how quickly the server responds.
Subscribe to:
Posts (Atom)