Wednesday, September 30, 2009

Datetime Formatting .NET & SQL

Another problem, another solution.

Date time formatting in .NET and SQL cannot be more easy but people simply do not know about it and you have to knock your heads in a hundred places to find what you are looking for. This article plans to summarize on the same.

ASP.NET

Dim dt As DateTime = DateTime.Now
Dim strDate As String = ""
strDate = dt.ToString("MM/dd/yyyy") ' 07/21/2007
strDate = dt.ToString("dddd, dd MMMM yyyy") 'Saturday, 21 July 2007
strDate = dt.ToString("dddd, dd MMMM yyyy HH:mm") ' Saturday, 21 July 2007 14:58
strDate = dt.ToString("dddd, dd MMMM yyyy hh:mm tt") ' Saturday, 21 July 2007 03:00 PM
strDate = dt.ToString("dddd, dd MMMM yyyy H:mm") ' Saturday, 21 July 2007 5:01
strDate = dt.ToString("dddd, dd MMMM yyyy h:mm tt") ' Saturday, 21 July 2007 3:03 PM
strDate = dt.ToString("dddd, dd MMMM yyyy HH:mm:ss") ' Saturday, 21 July 2007 15:04:10
strDate = dt.ToString("MM/dd/yyyy HH:mm") ' 07/21/2007 15:05
strDate = dt.ToString("MM/dd/yyyy hh:mm tt") ' 07/21/2007 03:06 PM
strDate = dt.ToString("MM/dd/yyyy H:mm") ' 07/21/2007 15:07
strDate = dt.ToString("MM/dd/yyyy h:mm tt") ' 07/21/2007 3:07 PM
strDate = dt.ToString("MM/dd/yyyy HH:mm:ss") ' 07/21/2007 15:09:29
strDate = dt.ToString("MMMM dd") ' July 21
strDate = dt.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK") ' 2007-07-21T15:11:19.1250000+05:30
strDate = dt.ToString("ddd, dd MMM yyyy HH':'mm':'ss 'GMT'") ' Sat, 21 Jul 2007 15:12:16 GMT
strDate = dt.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss") ' 2007-07-21T15:12:57
strDate = dt.ToString("HH:mm") ' 15:14
strDate = dt.ToString("hh:mm tt") ' 03:14 PM
strDate = dt.ToString("H:mm") ' 5:15
strDate = dt.ToString("h:mm tt") ' 3:16 PM
strDate = dt.ToString("HH:mm:ss") ' 15:16:29
strDate = dt.ToString("yyyy'-'MM'-'dd HH':'mm':'ss'Z'") ' 2007-07-21 15:17:20Z
strDate = dt.ToString("dddd, dd MMMM yyyy HH:mm:ss") ' Saturday, 21 July 2007 15:17:58
strDate = dt.ToString("yyyy MMMM") ' 2007 July


SQL

select convert(char, getdate(), 100) --mon dd yyyy hh:mmAM (or PM)
select convert(char, getdate(), 101) --mm/dd/yyyy
select convert(char, getdate(), 102) --yyyy.mm.dd
select convert(char, getdate(), 103) --dd/mm/yyyy
select convert(char, getdate(), 104) --dd.mm.yyyy
select convert(char, getdate(), 105) --dd-mm-yyyy
select convert(char, getdate(), 106) --dd mon yyyy
select convert(char, getdate(), 107) --mon dd, yyyy
select convert(char, getdate(), 108) --hh:mm:ss
select convert(char, getdate(), 109) --mon dd yyyy hh:mm:ss:mmmAM (or PM)
select convert(char, getdate(), 110) --mm-dd-yyyy
select convert(char, getdate(), 111) --yyyy/mm/dd
select convert(char, getdate(), 112) --yyyymmdd
select convert(char, getdate(), 113) --dd mon yyyy hh:mm:ss:mmm
select convert(char, getdate(), 114) --hh:mm:ss:mmm(24h)
select convert(char, getdate(), 120) --yyyy-mm-dd hh:mm:ss(24h)
select convert(char, getdate(), 121) --yyyy-mm-dd hh:mm:ss.mmm
SUBSTRING(RIGHT(CONVERT( VARCHAR, dateassigned, 100),7),1,5) + ' ' + SUBSTRING(RIGHT(CONVERT( VARCHAR, dateassigned, 100),7),6,7) hh:mm AM


Hope this saved you some time.

Tuesday, September 29, 2009

Custom Validation Summary - The Javascript way!

I was once faced with a unique requirement, I had to make all the validation summaries which appear in a website clickable such that once you click on the error list, the control which produed the error should be focused upon.
This was intresting and I thought it would interest other people who face the same dillemma.
Now, all this can of course be done through custom controls however nobody wanted to go through 100's of pages and then change the validation summary to the custom control, so I decided to do it the Javascript way.

To start off, Validations in ASP.NET are done through Javascript, no revelation there, these scripts are stored in a WebResource.axd file which is downloaded into the clients temporary internet files folder. The methodology followed here is that I took the function generated by .NET from the WebResource file, modified it and shadowed the function so that my custom function gets called every time instead of the default one which .NET produces.

To dwelve into the code, below is an extract from a ".JS" file that i had created:

function InitializeValSummary() {

if (typeof (ValidationSummaryOnSubmit) == 'function') { ValidationSummaryOnSubmit = ValidationSummaryOnSubmit_Overload; }

}


function SetElementFocus(strValID) {

var objValidator = strValID;

var blnFlag = false;

if (objValidator.controltovalidate == null && objValidator != null) {



var arrElementsToFocus = document.getElementById(objValidator.id).parentNode.getElementsByTagName('Input');

if (arrElementsToFocus && arrElementsToFocus.length > 0){

for (var intIndex = 0;intIndex<arrElementsToFocus.length;intIndex++){

if (arrElementsToFocus[intIndex].type != 'hidden'){

arrElementsToFocus[intIndex].focus();

blnFlag = true;

break;

}

}

}

if (!blnFlag){

arrElementsToFocus = document.getElementById(objValidator.id).parentNode.getElementsByTagName('TextArea');

if (arrElementsToFocus && arrElementsToFocus.length > 0) arrElementsToFocus[0].focus();

}

return;

}

if (objValidator == null || typeof (objValidator.controltovalidate) != "string") return;


var objControlToFocus = document.getElementById(objValidator.controltovalidate);

if (objControlToFocus == null) return;



var arrCtrlToFocus = document.getElementById(objControlToFocus.id).parentNode.getElementsByTagName('Input');

if (arrCtrlToFocus && arrCtrlToFocus.length > 0) {

for (var intCount = 0; intCount < arrCtrlToFocus.length; intCount++) {

if (arrCtrlToFocus[intCount].type != 'hidden') {

arrCtrlToFocus[intCount].focus();

break;

}

}

}

else {

objControlToFocus.focus();

}

}


function ValidationSummaryOnSubmit_Overload(validationGroup) {

if (typeof (Page_ValidationSummaries) == "undefined")

return;

var summary, sums, s;

for (sums = 0; sums < Page_ValidationSummaries.length; sums++) {

summary = Page_ValidationSummaries[sums];

summary.style.display = "none";

if (!Page_IsValid && IsValidationGroupMatch(summary, validationGroup)) {

var i;

if (summary.showsummary != "False") {

summary.style.display = "";

if (typeof (summary.displaymode) != "string") {

summary.displaymode = "BulletList";

}

switch (summary.displaymode) {

case "List":

headerSep = "<br>";

first = "";

pre = "";

post = "<br>";

end = "";

break;

case "BulletList":

default:

headerSep = "";

first = "<ul>";

pre = "<li>";

post = "</li>";

end = "</ul>";

break;

case "SingleParagraph":

headerSep = " ";

first = "";

pre = "";

post = " ";

end = "<br>";

break;

}

s = "";

if (typeof (summary.headertext) == "string") {

s += summary.headertext + headerSep;

}

s += first;

for (i = 0; i < Page_Validators.length; i++) {

if (!Page_Validators[i].isvalid && typeof (Page_Validators[i].errormessage) == "string") {

s += pre + '<a style="cursor:pointer" onclick=SetElementFocus(' + Page_Validators[i].id + ')>' + Page_Validators[i].errormessage + '</a>' + post;

}

}

s += end;

summary.innerHTML = s;

window.scrollTo(0, 0);

}

if (summary.showmessagebox == "True") {

s = "";

if (typeof (summary.headertext) == "string") {

s += summary.headertext + "\r\n";

}

var lastValIndex = Page_Validators.length - 1;

for (i = 0; i <= lastValIndex; i++) {

if (!Page_Validators[i].isvalid && typeof (Page_Validators[i].errormessage) == "string") {

switch (summary.displaymode) {

case "List":

s += Page_Validators[i].errormessage;

if (i < lastValIndex) {

s += "\r\n";

}

break;

case "BulletList":

default:

s += "- " + Page_Validators[i].errormessage;

if (i < lastValIndex) {

s += "\r\n";

}

break;

case "SingleParagraph":

s += Page_Validators[i].errormessage + " ";

break;

}

}

}

alert(s);

}

}

}

}


function AddFunctionToLoad(){

var objFunc = window.onload;

if (objFunc !=null && typeof(objFunc) == 'function'){

window.onload = function(){

objFunc();

InitializeValSummary();

}

}else{

window.onload = function() { InitializeValSummary(); }

}

}

AddFunctionToLoad();




Lets start from the basics; The first step is to create a copy of the validation function to do that simply locate the webresource.axd file (there will be multiple you'll have to fish out the one which contains the validation scripts), copy the function "ValidationSummaryOnSubmit" which basically is responsible for creating the summary that we see in the UI. After copying change the function name to something else (in my case I usually suffix it with "_Overloaded" to know which function it originally was). In the bold line in the code i have slightly modified the .Net output such that instead of a regular red text, the text is wrapped in a "anchor" tag which calls a function in its "onclick" event.
The "Page_Validators" is an array which will already be available when this function is run and contains the validator objects of the validators which lie in the same validation group as the validation summary.


Now that we have the custom function ready we have to shadow the .Net version such that our custom function gets called instead of the default one.
To achieve the above the following points need to be kept in mind:

  1. A javascript function can be shadowed by simply changing the pointer of that function by making it "equal" to another function (see function InitializeSummary)

  2. The .Net function will be available only after the page fully loads.

  3. To shadow the function we have to then include our initialize method in the window.onload event, which is achieved by the function "AddFunctionToLoad" (see code)

  4. Once shadowed, the original function is lost and all calls will come to our custom function.





Now all that is remaining is to create a function which sets the element focus based upon the validator object that is passed onto the the function (see SetElementFocus).
The latter function was made for handling all circumstances that occurred in my web application which required the script, I'll leave it up to the users to figure the function out, it's pretty straight forward in my opinion.

Hope this saved you a lot of time researching.

ASP.NET Methods for carrying User data







One of the frequently faced problems by people who have started work in asp.net is “how to retain a value across pages), although there are scattered articles which give the solutions, this is an attempt to combine them and present the various solutions available.


Session Variables


This is definitely the easiest option available in .Net and most .Net freshers tend to use them, however Session variables should only be used in seldom circumstances which I will not discuss in this article.



Session data can be used to store user specific data and its usage is something like this:



Sessions are basically key-value pairs, while the key will remain the same for all users, the value will depend on the input for the user under which context the application is running.

Caution: A session variable is created for each user which means if your site is using 20 session variables and 20000 people are using your application it means 20*20000 = 400000 variables will be created in the server memory.


Supports: any object including strings, custom objects, integers etc and only serializable objects in case outProc session type is being used (default is InProc).





Cookies


Cookies is the method of adding small files into the client’s machine (temp internet files), which will contain the required information.







The advantage of using cookies is obviously that the data is completely stored in the client side and hence server is not loaded with thousands of variables data in its memory.



Supports: string data only.


Query String
An elegant way of passing information from one page across the other is to use the query string. A query string is the part of the URL which starts from the character “?” e.g.



http://blogger.com/home.aspx?Mykey=MyValue&ScondKey=SecondValue ; here “?MyKey=MyValue&ScondKey=SecondValue” is the query string.


Query strings can be accessed in the code behind like:





The value of the string variable “strValue” in the latter case would then become “MyValue”. Parameters can be differentiated by adding “&” in the query string.



Supports: string data only, in case of special characters in the query string, it can be URL encoded by using the “HTTPUtility.URLEncode” method.


Context


This method can only be used in Server.Transfers and the value persists for one transfer.


This can be done using the following code:





On the second page you can access the value simply by writing:





Supports: any object.



Static Variables


Static variables or “Shared” variables as they are known in VB have a single instance. This means that the value of the variable will remain the same for all users using the application and any changes made to the same will be reflected to all.


Shared variables will only lose their data in case the application pool or the app domain is restarted.




Supports: any object.

Web.Config


In case a variable is a constant and is used throughout the application Web.Config is a good place to store it. The appSettings section of the configuration file can be used for storing such values.




This can be accessed anywhere in the code using the following sample:




This method can be used for storing connection strings, file folder paths, application modes (if any) etc.


Supports: String data.


Thats it, please let me know if I have missed something, comments are of course welcome.

Followers