Optimizing web pages for Google and other search engines is not enough. A successful concept for online marketing your blog or site has to be regarded in a more comprehensive way and must include the community [The Wisdom of Crowds!].
Web 2.0 is part of the community and vice versa. Social bookmarking is part of it, too. so you should make it as easy as possible for your visitors to bookmark your site. and gathering information on the best social bookmarking sites, their icons, submission URLs, and ranking is quite a pain.
This is a simple JavaScript that you can paste to any web page or blog to add the top 20 ranked social bookmarking sites as advised in [List of social bookmarking sites] and It should look like Icons on the right side -->>
And as you might know: loading many small images can slow down your page loading, as browser opens a new connection for each image to download, a well-known better approach is to put all this related images in one image, and use CSS to set background-position..
Here is the JavaScript to paste
<script type='text/javascript'>
function SocialBookmarks(){
var holder = document.getElementById("SocialButtonsPlace");
if (!holder) return;
var title = encodeURIComponent(document.title);
var url = encodeURIComponent(location.href);
/* these are the social bookmaking sites' icons ,ordered by rank, you can remove a line
but don't change the 'pos' so icon would show up correctly */
var socials = [
{'name':'Yahoo','pos':-16,'url':'http://myweb2.search.yahoo.com/myresults/bookmarklet?t='+title+'&u='+url},
{'name':'Google','pos':-32,'url':'http://www.google.com/bookmarks/mark?op=edit&bkmk='+url+'&title='+title},
{'name':'Live','pos':-48,'url':'https://favorites.live.com/quickadd.aspx?url='+url+'&title='+title},
{'name':'Facebook','pos':-64,'url':'http://www.facebook.com/sharer.php?u='+url+'&t='+title},
{'name':'Digg','pos':-80,'url':'http://digg.com/submit?phase=2&url='+url+'&title='+title},
{'name':'Ask','pos':-96,'url':'http://myjeeves.ask.com/mysearch/BookmarkIt?v=1.2&t=webpages&url='+url+'&title='+title},
{'name':'Technorati','pos':-112,'url':'http://technorati.com/faves?sub=addfavbtn&add='+url+'&title='+title},
{'name':'Delicious','pos':-128,'url':'http://del.icio.us/post?url='+url+'&title='+title},
{'name':'StumbleUpon','pos':-144,'url':'http://www.stumbleupon.com/submit?url='+url+'&title='+title},
{'name':'Squidoo','pos':-160,'url':'http://www.squidoo.com/lensmaster/bookmark?'+url},
{'name':'Propeller','pos':-176,'url':'http://www.propeller.com/submit/?U='+url+'&T='+title+'&C='+title},
{'name':'Slashdot','pos':-192,'url':'http://slashdot.org/bookmark.pl?url='+url+'&title='+title},
{'name':'Reddit','pos':-208,'url':'http://reddit.com/submit?url='+url+'&title='+title},
{'name':'Fark','pos':-224,'url':'http://cgi.fark.com/cgi/fark/submit.pl?new_url='+url+'&new_comment='+title+'&linktype='},
{'name':'Newsvine','pos':-240,'url':'http://www.newsvine.com/_wine/save?u='+url+'&h='+title},
{'name':'Furl','pos':-256,'url':'http://www.furl.net/storeIt.jsp?t='+title+'&u='+url},
{'name':'Blinklist','pos':-272,'url':'http://www.blinklist.com/index.php?Action=Blink/addblink.php&Url='+url+'&Title='+title},
{'name':'dzone','pos':-288,'url':'http://www.dzone.com/links/add.html?url='+url+'&title='+title},
{'name':'Magnolia','pos':-304,'url':'http://ma.gnolia.com/bookmarklet/add?url='+url+'&title='+title},
{'name':'SWiK','pos':-320,'url':'http://stories.swik.net/?submitUrl&url='+url}
];
for(var i=0; i<socials.length; i++)
holder.innerHTML = holder.innerHTML + '<li><A class=\'SocialButton\' style=\'background-position:0 '+socials[i].pos+'px\' href=\''+socials[i].url+'\' title=\''+socials[i].name+'\' target=\'_blank\'> </A></li>';
}
/* This call can be placed in body onload event */
SocialBookmarks();
</script>
And place this CSS code in the HTML Head or in an included CSS file
#SocialButtonsPlace {
list-style:none;
/* must do - Browsers WORLD WAR!*/
margin:0; padding: 0;
}
#SocialButtonsPlace Li{
float:left;
}
.SocialButton {
display:block;
height:16px;
width:16px;
line-height:16px;
margin:2px;
text-decoration:none;
background-image:url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikWuhPxjyWXhmT9ax0HQ-a-A1tkGL_hUK5WnSPdXu2uN9C1YsuEJMb5YyVD3rXtuMX4W3bRQDMMT5pWzXxBe5ezHun2B8uVxJzud3WwYjhWrScnKfoB8e3hT4kt7vqlxJzyzhFqLxcQf5_/s400/bar.gif);
}
And create a place holder UL where the icons will show up
<UL id="SocialButtonsPlace"></UL>
Don't forget to save the icons [Bar Image] and upload it some where on your site and change its location in CSS.
You may also use an Image-Map to display the bar image horizontally or vertically and define the clickable regions..
that's it.. enjoy!
If you are interested in SEO or web search or marketing your blog, you should check that great article
[Can Social Bookmarking Improve Web Search] by Paul Heymann , One look on the author photo and you will want to read it..
Or watch the video
Can Social Bookmarks Improve Web Search?
Presentation (February 12th, 2008)
Conference on Web Search and Data Mining (WSDM2008)
A very important method of increasing data access efficiency is to cache frequently accessed data. like country list or top articles.. in situations where the data changes less frequently, such as once a day or every few hours, it is inefficient to hit the database for every page request.
As many would suggest to cache the HTML Output of a portion of a page(Fragment Caching) as a country select box or caching the entire page(Output Caching), there are cases where Data Caching will be more powerful. for example you may need to display that list of countries in more than one page/Portion with different look and/or use that list programmatically.
In a previous post [Data Access Layer for Classic ASP]: I proposed DAL Classes to encapsulate Data Access code for a certain Table/Object, and now I'll extend the DAL to handle Data caching too, please refer to my previous post before continuing..
I've modified the "Users" class to handle saving and reading from cache, which is saved to ADO XML format or Advanced Data Tablegram (ADTG) Binary format using "Save" method of ADO Recordset, Which has many advantages :
- You don't need to change much of your Data Access code to read from cache
- Opening the recordset from XML will act the same as Opening Database when you use Paging
- You can use The "Filter" method of ADO Recordset to filter records as you would do in a SQL Query
Here is the New ClassClass Users
'private Arr to hold users Objects
Private arr
'0 : Binary ADTG , 1: XML
Public CacheType 'as Byte
' Cache File Path
Public CachePath 'as String
''''' Paging Variables
Private mPageCount 'as Long
Public PageIndex 'as Long
Public PageSize 'as Long
'for getting top records if larget than 0
Public TopRecords 'as Long
'destroy arr
Private Sub Class_Terminate()
Erase arr
end Sub
Private Sub Class_Initialize()
Initialize
TopRecords = 0
PageIndex = 0
PageSize = 0
CacheType = 0
CachePath = ""
end Sub
'Initialize collection
Public Sub Initialize()
redim Arr(-1)
mPageCount = 0
End Sub
'return Upper Bound of objects array
Public Property get UpperBound()
UpperBound = UBound(arr)
End Property
'return object at index i
Public Property Get ElementAt(i)
set ElementAt = arr(i)
End Property
'return Upper Bound of objects array
Public Property Get PageCount()
PageCount = mPageCount
End Property
'Select users by Status ( u can add more search parameters or create another selectUsers method)
Public Sub SelectUsers(Status)
Initialize
Dim rs : Set rs = server.CreateObject("ADODB.Recordset")
'Do paging
If PageSize>0 And PageIndex>0 Then
RS.CursorLocation = adUseClient
RS.CacheSize = PageSize
RS.PageSize = PageSize
End If
'if open from XML
If CachePath>"" Then
If Status>0 Then rs.Filter = "Status="& Status
Rs.Open CachePath,,,,adCmdFile
'if Open from DB
Else
If TopRecords>0 Then
rs.MaxRecords = TopRecords
Top = " top "& TopRecords &" "
End If
Dim SQL : SQL= "SELECT "& Top &" * From users"
If Status>0 Then SQL = SQL & " where Status="& Status
rs.Open SQL , ConnStr, adOpenForwardOnly,adLockReadOnly,adCmdText
End If
' if paging : get page count
If Not rs.EOF And PageSize>0 And PageIndex>0 Then
RS.AbsolutePage = PageIndex
mPageCount = RS.PageCount
End If
Dim i : i=0
'(TopRecords=0 Or i<TopRecords) condition is needed to get correct Top N records when opening from Cache
' ,MaxRecords doesn't seem to work in that case
While Not rs.EOF And (TopRecords=0 Or i<TopRecords) And (PageSize=0 Or i<PageSize)
'loop until EOF or Paging Size reached
'create Object and set Values then add to collection
Dim u : Set u = New User
u.ID = CLng(Rs("ID"))
u.Name = Rs("Name")
u.Email = Rs("Email")
u.Password = Rs("Password")
u.LastLogin = cdate(rs("LastLogin"))
u.Status = cbyte(Rs("Status"))
ReDim Preserve arr(i)
Set arr(i) = u
set u = Nothing
rs.MoveNext
i=i+1
Wend
rs.Close
Set rs = Nothing
End Sub
' Open Recordset and Save it
Public Sub CacheUsers(Status)
If CachePath="" Then Exit Sub
Dim rs : Set rs = server.CreateObject("ADODB.Recordset")
Dim Top
If TopRecords>0 Then
rs.MaxRecords = TopRecords
Top = " top "& TopRecords &" "
End if
Dim SQL : SQL= "SELECT "& Top &" * From users"
If Status>0 Then SQL = SQL & " where Status="& Status
rs.Open SQL , ConnStr, adOpenForwardOnly,adLockReadOnly,adCmdText
Call SaveRS(rs)
rs.Close
Set rs = Nothing
End Sub
'Handle saving Recordset to Stream
Private Sub SaveRS(rs)
Const adTypeText = 2
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
Const adPersistXML = 1
Const adPersistADTG = 0
Dim Stream : Set Stream = Server.CreateObject("ADODB.Stream")
If CacheType=1 Or CacheType=2 Then
Stream.Type = adTypeText
Stream.Open
rs.Save Stream, adPersistXML
Else
Stream.Type = adTypeBinary
Stream.Open
rs.Save Stream, adPersistADTG
end If
Application.Lock
Stream.SaveToFile CachePath,adSaveCreateOverWrite
Stream.Close
Application.UnLock
Set Stream = Nothing
End Sub
End Class
Sample Usage
1- Save Cache when Target Data is updatedDim aUsers : Set aUsers = New Users
aUsers.CacheType = 1 'XML cache
aUsers.CachePath = Server.MapPath("users.xml")
aUsers.TopRecords = Top
Call aUsers.CacheUsers(0)
Set aUsers = Nothing
2- Read CacheDim aUsers : Set aUsers = New Users
aUsers.CacheType = 1 'XML cache
aUsers.CachePath = Server.MapPath("users.xml")
aUsers.TopRecords = Top
Call aUsers.SelectUsers(0)
Dim i,aUser
For i=0 To aUsers.UpperBound
Set aUser = aUsers.ElementAt(i)
'do something
Set aUser = Nothing
Next
Set aUsers = Nothing
Time Comparison
I did a timing test to compare between reading from a SQL Server and from XML/Binary file, but Reading from a local SQL Server (on the same machine as IIS) will be always faster, so to get real world results i simulated a LAN/WAN Connection on SQL Server [How to? check: Simulating WAN Connection for SQL Server Performance Testing].
And to simulate concurrent connections on IIS and calculate timing i used the very neat [Microsoft Web Stress Tool] on a PC of P3.2GHZ, 1GB Ram, Windows XP, SQL Server 2005 Express.
method / Records | 100 | 500 | 1000 | 3000 |
---|---|---|---|---|
Open WAN SQL Server | 559.25 | 614.80 | 980.85 | 2489.85 |
Open LAN SQL Server | 276.70 | 436.00 | 777.60 | 2368.90 |
Open XML Cache | 72.25 | 369.95 | 821.10 | 2469.31 |
Open Binary Cache | 60.45 | 311.25 | 666.45 | 2062.20 |
As you can see reading less than 1000 records from XML Cache is slightly faster than reading from LAN SQL Server and time saving gets bigger when compared to WAN SQL server(reading >1000 records gets slower in XML due to loading&parsing overhead).
You can also notice that reading from Binary(ADTG) is faster than reading from XML and LAN/WAN SQL Server in all cases, and files created in binary are Approx. 50% smaller than the equivalent XML files.
it's all about Regular expressions; Regular expressions are a very powerful tool for performing pattern matches in strings. You can perform complex tasks that once required lengthy procedures with just a few lines of code using regular expressions...
in this example,i made a simple Code Beautifier and formatter for VB/VBScript/VB.net using JavaScript and CSS.
in this syntax highlighter There are patterns for matching Comments lines,Quoted strings,Escape HTML tags,and Language Keywords..
To extend this to format C# for example; all you need to change is the keywords of that programming language at the line
s = keywords_Beautifier("New|Class|..",s);
where you should place language keywords as one string separated by | as the first parameter
Go ahead try it your self
Output will look like this
Copy & paste this
You will need to include this css
<style>
b.KW {
color:blue;
}
b.Cm , b.Cm b.KW , b.Cm b.QS {
color:green;
font-weight:lighter;
}
b.QS, b.QS b.KW {
color:maroon;
font-weight:lighter;
}
</style>
Code Beautifier And Formatter Source Code
<SCRIPT LANGUAGE=javascript>
function Code_Beautifier(){
var a = document.getElementById("codearea");
if (!a) return;
var s = a.value;
//escape HTML Tags <>
s= s.replace(/</g ,"<");
s= s.replace(/>/g ,">");
//next will use regular expressions patterns, and surround matches with <b ClssS="[Css class]"></b>
// but note that 'ClssS' is misspelled so it don't get changed by keywords pattern
//Beautify a quoted string
s= s.replace(/(\"[^\"]*\")/gi ,'<b ClssS="qs">$1</b>');
//Beautify Comments
s = Comments_Beautifier(s);
//escape lines
s= s.replace(/\n/g ,"<br />");
//escape spaces
s= s.replace(/\s\s/gi ," ");
//Beautify keywords
s = keywords_Beautifier("New|Class|Shared|Protected|Friend|byval|byREF|Optional|RETURN|GET|Property|Erase|LBound|UBound|Let|Set|Rem|Const|Empty|Nothing|Null|True|False|Control|Do|Loop|For|Next|For|If|Then|Else|select|While|Wend|end|Abs|Asc|AscB|AscW|Chr|ChrB|ChrW|CBool|CByte|CDate|CDbl|Cint|CLng|CSng|CStr|DateSerial|DateValue|Hex|Oct|Fix|Int|Sgn|TimeSerial|TimeValue|date|Time|DateSerial|DateValue|Day|Month|Weekday|Year|Hour|Minute|Second|Now|TimeSerial|TimeValue|Dim|Private|Public|ReDim|Sub|On|Err|InputBox|MsgBox|Atn|Cos|Sin|Tan|Exp|Log|Sqr|Randomize|Rnd|Mod|Is|And|Or|Xor|Eqv|Imp|CreateObject|IsObject|option|Call|FUNCTION|Sub|Instr|InStrB|Len|LenB|Lcase|Ucase|Left|LeftB|Mid|MidB|Right|RightB|Space|StrComp|string|Ltrim|Rtrim|Trim|IsArray|IsDate|IsEmpty|IsNull|IsNumeric|IsObject|VarType|ERROR",s);
s = CorrectCssClass(s);
var o = document.getElementById("output") ;
if (o) o.innerHTML = s;
var oa = document.getElementById("outarea");
if (oa) oa.value=s;
}
function keywords_Beautifier(keys,s) {
var rx = new RegExp("(\\b)("+ keys +")(\\b)", "gi")
return s.replace(rx ,'$1<b ClssS="Kw">$2</b>$3');
}
function Comments_Beautifier(s) {
return s.replace(/\'([^\n]+)\n/gi ,'<b ClssS="Cm">\'$1</b>\n');
}
function CorrectCssClass(s) {
return s.replace(/ClssS/g ,'class');
}
</SCRIPT>
Some fine JavaScript Regular Expressions References
Using Regular Expressions with JavaScript and ActionScript
javascript regual expressions
JavaScript RegExp Object Reference
I needed to do some testing on SQL Server on my PC, but response was of course very fast, so i needed to simulate WAN connection to get some real world results..
i found a good article [How To: Simulate WAN Connections in Your Own Test Lab, For Free!] by Michel Roth
Since WAN main characteristics are : limited in bandwidth and high in latency, we can use one of two software:
1- NetLimiter Pro (commercial-28-day evaluation period)
it can limit the bandwidth per process. You can use this ability in two ways:
a. You can install it on the Server (ex:SQL Server) and limit the incoming bandwidth.
b. You can install it on the Client machine(ex:IIS) and limit the outgoing bandwidth for the client(Preferred).
2. TMnetSim Network Simulator (free!)
a *free* tool to allow you to simulate network latency & packet loss!,You can install it on the client or on the server. I gonna use the tool on the Server.
Here are the steps to setup that tool for testing SQL Server 2005 Express on your local PC:
- Download zip file and run executable
- SQL Server default port is 1433 so:
Under 'Outbound Connection' >> enter IP: 127.0.0.1, Port : 1433
Under 'Inbound Connection' >> enter port: 1422 (any other port!)
Under 'inbound-->outbound policies' >> Delay Type : Gausian, Delay Base:250 , Daley Jitter : 25 - click "Start"
- Setup your Connection String on ASP
Provider=SQLOLEDB; Data Source=127.0.0.1\sqlexpress,1422;Initial Catalog=db;User Id=user;Password=pass;
or ASP.Net :<connectionStrings>
<add name="SQLConn" connectionString="Data Source=127.0.0.1\sqlexpress,1422;Initial Catalog=DB;Persist Security Info=False;User ID=user;Password=pass;Network Library=dbmssocn" providerName="System.Data.SqlClient"/>
</connectionStrings> - If things running ok, you should see connection information (Latency- Bandwidth- Packet Loss)
Data Access layer(DAL) is is a layer of code which provides simplified access to data stored in persistent storage of some kind (DBMS, XML,..)
DAL would return a reference to an object [in terms of object-oriented programming(OOP)] with its attributes instead of a recordset of fields from a database table. This allows presentation layer to be created with a higher level of abstraction, and make project database independent.
So, instead of using SQL commands such as insert, delete, and update to access a specific table in a database, a method would be called from inside the class, which would return an object containing the requested values. instead of making a query into a database to fetch all users from several tables the application can call a single method from a DAL which encapsulate those database calls.
As an example of DAL, we'll use a simple Table of 'Users', here is the SQL Create script:CREATE TABLE [dbo].[Users](
[ID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
[Name] [varchar](100) NOT NULL DEFAULT (''),
[Email] [varchar](100) NOT NULL DEFAULT (''),
[Password] [varchar](20) NOT NULL DEFAULT (''),
[LastLogin] [smalldatetime] NOT NULL DEFAULT ('1/1/1900'),
[Status] [tinyint] NOT NULL DEFAULT (0)
)
We will create 2 classes for users table, Object Class and Object Collection Class with support of paging
Object Class'few needed ADO Constants, instead of including adovbs.asp
Const adCmdText = &H0001
Const adCmdTableDirect = &H0200
Const adCmdFile = &H0100
Const adOpenForwardOnly = 0
Const adOpenKeyset = 1
Const adLockReadOnly = 1
Const adLockOptimistic = 3
Const adExecuteNoRecords = &H00000080
Const adUseClient = 3
''''''''''''''' Object class '''''''''''''''
Class User
' Object Attributes / Table Fields
Public ID 'as Long
Public Name 'as String
Public Email 'as String
Public Password 'as Strng
Public LastLogin 'as Date
Public Status 'as byte
Private Sub Class_Initialize()
Initialize
End Sub
'default values
Public Sub Initialize()
ID=0
Name=""
Email = ""
Password = ""
LastLogin = Now()
Status=0
End Sub
'Select user by ID
Public Sub SelectUser(UserID)
Initialize
if UserID=0 then exit Sub
Dim rs : Set rs = server.CreateObject("ADODB.Recordset")
Dim SQL : SQL= "SELECT * From users where ID="& UserID
rs.Open SQL, ConnStr ,adOpenForwardOnly, adLockReadOnly,adCmdText
If Not rs.EOF Then
ID = CLng(Rs("ID"))
Name = Rs("Name")
Email = Rs("Email")
Password = Rs("Password")
LastLogin = Cdate(rs("LastLogin"))
Status = cbyte(Rs("Status"))
End If
rs.Close
Set rs = Nothing
End Sub
'Insert New User and get new ID
Public Sub InsertUser()
if ID<>0 then exit Sub
Dim rs : Set rs = server.CreateObject("ADODB.Recordset")
rs.Open "Users", ConnStr ,adOpenKeyset,adLockOptimistic,adCmdTableDirect
rs.AddNew
Rs("Name") = Name
Rs("Email") = Email
Rs("Password") = Password
rs("LastLogin") = LastLogin
Rs("Status") = Status
rs.update
ID = CLng(Rs("ID"))
Rs.Close
Set rs = Nothing
End Sub
'Update User
Public Sub UpdateUser()
if ID=0 then exit Sub
Dim rs : Set rs = server.CreateObject("ADODB.Recordset")
Dim SQL : SQL= "SELECT * From users where ID="& ID
rs.Open SQL, ConnStr ,adOpenForwardOnly,adLockOptimistic,adCmdText
If Not rs.EOF then
Rs("Name") = Name
Rs("Email") = Email
Rs("Password") = Password
rs("LastLogin") = LastLogin
Rs("Status") = Status
rs.update
End If
Rs.Close
Set rs = Nothing
End Sub
'delete user
Public Sub DeleteUser()
if ID=0 then exit Sub
Dim conn : Set conn = server.CreateObject("ADODB.Connection")
conn.Execute "Delete From users where ID="& ID, ,adExecuteNoRecords
Conn.Close
Set Conn = Nothing
Initialize
End Sub
End Class
Object Collection ClassClass Users
'private Array to hold users Objects
Private arr
''''' Paging Variables
Private mPageCount 'as Long
Public PageIndex 'as Long
Public PageSize 'as Long
'for getting top records if larger than 0
Public TopRecords 'as Long
'destroy arr
Private Sub Class_Terminate()
Erase arr
end Sub
Private Sub Class_Initialize()
Initialize
TopRecords = 0
PageIndex = 0
PageSize = 0
end Sub
'Initialize collection
Public Sub Initialize()
redim Arr(-1)
mPageCount = 0
End Sub
'return Upper Bound of objects array
Public Property get UpperBound()
UpperBound = UBound(arr)
End Property
'return object at index i
Public Property Get ElementAt(i)
set ElementAt = arr(i)
End Property
Public Property Get PageCount()
PageCount = mPageCount
End Property
'Select users by Status (you can add more search parameters or create another select method)
Public Sub SelectUsers(Status)
Initialize
Dim rs : Set rs = server.CreateObject("ADODB.Recordset")
'Do paging
If PageSize>0 And PageIndex>0 Then
RS.CursorLocation = adUseClient
RS.CacheSize = PageSize
RS.PageSize = PageSize
End if
If TopRecords>0 Then rs.MaxRecords = TopRecords
Dim Top
If TopRecords>0 Then Top = " top "& TopRecords &" "
Dim SQL : SQL= "SELECT "& Top &" * From users"
If Status>0 Then SQL = SQL & " where Status="& Status
rs.Open SQL, ConnStr, adOpenForwardOnly,adLockReadOnly,adCmdText
' if paging : move to PageIndex and get page count
If Not rs.EOF And PageSize>0 And PageIndex>0 Then
RS.AbsolutePage = PageIndex
mPageCount = RS.PageCount
End If
Dim i : i=0
'loop until EOF or Paging Size reached
while Not rs.EOF And (PageSize=0 Or i<PageSize)
'create Object and set Values then add to collection
Dim u : Set u = New User
u.ID = CLng(Rs("ID"))
u.Name = Rs("Name")
u.Email = Rs("Email")
u.Password = Rs("Password")
u.LastLogin = cdate(rs("LastLogin"))
u.Status = cbyte(Rs("Status"))
ReDim Preserve arr(i)
Set arr(i) = u
set u = Nothing
rs.MoveNext
i=i+1
Wend
rs.Close
Set rs = Nothing
End Sub
End Class
Sample UsageDim Usrs : Set Usrs = New Users
Usrs.PageIndex = 1
Usrs.PageSize = 10
Call Usrs.SelectUsers(0)
Dim i,Usr
For i=0 To Usrs.UpperBound
Set Usr = Usrs.ElementAt(i)
'Do something
Set Usr = Nothing
Next
Set Usrs = Nothing
Note that the paging method used in the collection class is the usual ADO method,since it is not the optimal or the fastest,Please check my article on [Paging in ASP and ASP.Net] for better paging methods..
This Data access layer can be later extended to be also a Business Logic Layer(BLL) by enforcing business rules that may apply (permissions, validations, formatting..)
Also if you have a lot of DAL classes, DAL can be moved to ActiveX DLL (Com Object) to improve performance..[25+ ASP Tips to Improve Performance and Style]
When error occurs while you compile or run an ASP page, IIS generates a 500;100 error and executes a Server.Transfer() method to pass control to the currently defined custom error page. (By default this page is "WinDir/help/iishelp/common/500-100.asp")
When control is passed to the custom error page, the Server.GetLastError() method can be used to obtain detailed information regarding the error that occurred. for more info [Creating Custom ASP Error Pages]
While you can setup a custom ASP error page for some website as described in the MSDN article mentioned before; why not customize the default IIS error 500 page [WinDir/help/iishelp/common/500-100.asp] directly,To present users with a friendly error message and do server-wide error logging and/or send it to IT Email..
This is modification for the 500-100.asp to display an error message and send email to IT:<%@ language="VBScript" %>
<% Option Explicit
If Response.Buffer Then
Response.Clear
Response.Status = "500 Internal Server Error"
Response.ContentType = "text/html"
Response.Expires = 0
End If
Call SendError()
%>
<html>
<head>
<style>
Body,TD {FONT-SIZE: 11px; FONT-FAMILY: Tahoma }
</style>
<META NAME="ROBOTS" CONTENT="NOINDEX">
<title>Unexpected Error</title>
<META HTTP-EQUIV="Content-Type" Content="text-html; charset=Windows-1252">
</head>
<body>
<h3 align="center">Unexpectd Error</h3>
An unexpected error has occurred. We apologize for the inconvenience.
<p>Please try the following:</p>
<ul>
<li>Click the <a href="javascript:location.reload()">Refresh</a> button, or try again later.</li>
<li>Open the home page, and then look for links to the information you want. </li>
</ul>
</body>
</html>
<%
Sub SendError()
Dim er : Set er = Server.GetLastError
Dim msg : msg = "Error 500 on "& Now &"<br>"
msg = msg & "category:"& er.Category & "<br>"
If er.ASPCode>"" Then msg = msg & "aspcode:"& er.ASPCode & "<br>"
msg = msg & "number:"& hex(er.Number) & "<br>"
If er.ASPDescription > "" Then
msg = msg & "description:"& er.ASPDescription & "<br>"
ElseIf er.Description >"" Then
msg = msg & "description:"& er.Description & "<br>"
end If
If er.Source > "" Then msg = msg & "source:"& er.Source & "<br>"
If er.File <> "?" Then
msg = msg & "file:"& er.File & "<br>"
If er.Line > 0 Then msg = msg & "line:"& er.Line & "<br>"
If er.Column > 0 Then msg = msg & "column:"& er.Column & "<br>"
End If
msg = msg & "USER_AGENT:"& Request.ServerVariables("HTTP_USER_AGENT") & "<br>"
msg = msg & "REQUEST_METHOD:"& Request.ServerVariables("REQUEST_METHOD") & "<br>"
msg = msg & "SCRIPT_NAME:"& Request.ServerVariables("SCRIPT_NAME") & "<br>"
if Request.QueryString>""Then msg = msg & "QueryString:"& Request.QueryString & "<br>"
if Request.Form>""Then msg = msg & "Post:"& Left(Request.Form,500) & "<br>"
Call SendEmail(IT_Email,IT_Email,"Error 500",msg)
End Sub
%>
* don't forget to disable "Show friendly HTTP error messages" In IE under Tools/Internet Options/Advanced
VMG Files are Plain text format used for storing SMS text messages on Nokia cell phones; contains header information such as the sender, date, and time, as well as the actual message encoded as UTF-16LE..
at some Application i needed a way to Export SMS Messages to be able to Copy it to my Nokia phone, of Course to drafts folders.. since you can't copy it directly to outbox..
well, here is a function to save an sms to a .VMG file using ADODB.Stream''''' Save SMS as VMG file
Sub SaveSMS(FilePath,Receipents,SMS,SMSTime)
Const adTypeText = 2
Const adSaveCreateOverWrite = 2
Dim stream : Set stream = Server.CreateObject("ADODB.stream")
stream.Type = adTypeText
stream.Charset = "UTF-16LE"
Stream.Open
stream.WriteText "BEGIN:VMSG" & vbCrLf & _
"VERSION:1.1" & vbCrLf & _
"X-IRMC-STATUS:DRAFT" & vbCrLf & _
"X-IRMC-BOX:INBOX" & vbCrLf & _
"BEGIN:VCARD" & vbCrLf & _
"VERSION:2.1" & vbCrLf & _
"N:" & vbCrLf & _
"TEL:" & vbCrLf & _
"END:VCARD" & vbCrLf
Dim i
For i = 0 To UBound(Receipents)
stream.WriteText "BEGIN:VENV" & vbCrLf & _
"BEGIN:VCARD" & vbCrLf & _
"VERSION:2.1" & vbCrLf & _
"N:"& Receipents(i)(0) & vbCrLf & _
"TEL:" & Receipents(i)(1) & vbCrLf & _
"END:VCARD" & vbCrLf
Next
stream.WriteText "BEGIN:VENV" & vbCrLf & _
"BEGIN:VBODY" & vbCrLf & _
"Date:" & VMGTime(SMSTime) & vbCrLf & _
SMS & vbCrLf & _
"END:VBODY" & vbCrLf & _
"END:VENV" & vbCrLf
For i = 0 To UBound(Receipents)
stream.WriteText "END:VENV" & VbCrLf
Next
stream.WriteText "END:VMSG" & vbCrLf
stream.Flush
stream.SaveToFile FilePath, adSaveCreateOverWrite
stream.Close
Set stream = Nothing
End Sub
Function VMGTime(d)
VMGTime = pad2(Day(d)) & "." & pad2(Month(d)) & "." & Year(d) & " " & Hour(d) & ":" & Minute(d) & ":" & Second(d)
End Function
Private Function pad2(str)
If Len(str)<2Then
pad2 = "0" & str
Else
pad2 = str
End If
End Function
'' A sample Call
Call SaveSMS(Server.MapPath("1.vmg"),array(Array("John","22222222"),Array("Paul","11111111")),"Hello SMS",now)
in a ASP.Net 2.0 web Application, to get a connection string from Web.config, you would write:
ConfigurationManager.ConnectionStrings("DB").ConnectionString
trying to do the same in a Windows application, would give you the error :
Name 'ConfigurationManager' is not declared
even you did import "System.Configuration"...
well, after searching i found that you need to add reference to "System.Configuration.dll" : under Project > Add refrence > .Net > select System.Configuration
Sometimes, you may need to change the owner of an object. This article contains a code sample that you can use to change ownership of objects. :
INF: SQL Server Procedure to Change Object Owner
also this seems to work: Change the owner of all db objects
The most common reason for ending up with orphan users is, moving databases from one server to another or from one domain to another. Restoring an old copy of master database can also result in this problem. Moving databases between servers is quite a common task. So, what's exactly resulting in orphan users?
Well, all SQL Server logins are stored in the system table sysxlogins (in master database). Whenever you create a new login (or grant access to a Windows account), a corresponding entry gets added to the sysxlogins table. So, you could say, each login has a corresponding row in sysxlogins table. In sysxlogins, each login has an associated SID (Security Identifier), which is of type varbinary(85).
How to troubleshoot orphan users in SQL Server databases?
URL rewriting is usually needed to make a URL for a dynamic web page more presentable for the reader or for search engines optimization.
For example, a regular ASP URL might look like this:
http://www.site.com/Articles/Article.asp?id=20
A more presentable way of rewriting the URL might be:
http://www.site.com/Articles/20.htm
of course, you can write HTML/ASP file for each article, but that would be much of I/O overhead on adding/updating articles and for reading too..
one solution is to use an ISAPI filter but many people want to avoid this for due to either the limitation on the skills, a limitation of the hosting service they use, or just to avoid complexity and potential risk. It also makes the solution less portable.
A much simple solution, is to use 404 custom error page in IIS, here are steps and code:
1- Create "URL-Rewrite.asp", under Articles folder.
2- in IIS , right-click on "Articles" folder > properties > Custom errors > Select 404 and click "Edit Properties" ..
set Message Type : "URL", and set URL : "/Articles/URL-Rewrite.asp"
3- Place this code in "URL-Rewrite.asp" <% option Explicit
Dim Er,ID
Set Er = Server.GetLastError()
If Not Er Is Nothing Then
'' For 404: URL will be passed as query string
ID = GetURLID(Request.QueryString )
'Http error 400 won't raise a code error
If ID>0 And Er.Number=0 Then
Response.Status = 200
Call DisplayArticle(ID)
' error 500 or similar
ElseIf Er.Number<>0 Then
Response.Write "Unexpected error was occured"
' undesired URL
Else
Response.Status = 404
Response.Write "Page cannot be found"
End if
End If
Set Er = Nothing
Function GetURLID(URL)
' Extract ID using regular expressions
Dim ID : ID = 0
Dim reg : Set reg = New RegExp
reg.Global = False
reg.IgnoreCase = True
reg.Pattern = "^404;http://www.site.com/Articles/(\d+).htm$"
if reg.Test(URL) Then
ID= reg.Replace(URL ,"$1")
End If
Set reg = Nothing
GetURLID = ID
End Function
Sub DisplayArticle(ID)
'''' here you will place the real code that read article form database and write it
Response.Write "<html>" &_
"<head>" &_
"<title>Article "& ID &"</title>" &_
"</head>" &_
"<body>" &_
"Content " & ID &_
"</body>" &_
"</html>"
End Sub
%>
now,when requesting the url "http://www.site.com/Articles/20.htm", the IIS doesn't find the file so it transfer execution to the custom error page "http://www.site.com/Articles/URL-Rewrite.asp" and sending "404;http://www.site.com/Articles/20.htm" as query string.
The Transfer happens by calling "server.Transfer" which keeps the existing query string and any form variables available to the page it is transferring to, in our case "URL-Rewrite.asp".