







Protected Sub btnMultipleRowDelete_Click(ByVal sender As Object, ByVal e As EventArgs) ' Looping through all the rows in the GridView
For Each row As GridViewRow In GridView1.Rows Dim checkbox As CheckBox = CType(row.FindControl("cbRows"), CheckBox) 'Check if the checkbox is checked. 'value in the HtmlInputCheckBox's Value property is set as the //value of the delete command's parameter.
If checkbox.Checked Then
' Retreive the Employee ID
Dim employeeID As Integer = Convert.ToInt32(GridView1.DataKeys(row.RowIndex).Value)
' Pass the value of the selected Employye ID to the Delete //command.
SqlDataSource1.DeleteParameters("EmployeeID").DefaultValue = employeeID.ToString()
SqlDataSource1.Delete()
End If
Next row
End Sub
Use JavaScript to set up Microsoft's and the Mozilla-based browsers' different request objects.
Browser compatibility is an important consideration. You have to make sure the "engine" behind Ajax's server handshake is properly constructed, but you can never predict which browsers your users will favor.
The programming tool that allows Ajax applications to make HTTP requests to a server is an object that you can use from within JavaScript code. In the world of Firefox and Netscape (as well as Safari and Opera), this object is named XMLHttpRequest. However, continuing with the tradition established by IE 5.0, recent vintages of Internet Explorer implement the software as an ActiveX object named Microsoft.XMLHTTP or Msxml2.XMLHTTP.
Although Microsoft and the engineers on the Mozilla project have chosen to implement this object differently, we will refer to the ActiveX and XMLHttpRequest objects simply as "request objects" throughout this book, because they have very similar functionality.
As a first step in using Ajax, you must check if the user's browser supports either one of the Mozilla-based or ActiveX-related request objects, and then properly initialize the object.
Wrap the compatibility check inside a JavaScript function, then call this function before you make any HTTP requests using the object. For example, in Mozilla-based browsers such as Netscape 7.1 and Firefox 1.5 (as well as in Safari 2.0 and Opera 8.5), the request object is available as a property of the top-level window object. The reference to this object in JavaScript code is window.XMLHttpRequest. The compatibility check for these browser types looks like this:
if(window.XMLHttpRequest){
request = new XMLHttpRequest( );
request.onreadystatechange=handleResponse;
request.open("GET",theURL,true);
request.send(null);
}
The JavaScript variable request is to a top-level variable that will refer to the request object.
If the browser supports XMLHttpRequest, then:
if(window.XMLHttpRequest) returns true because the XMLHttpRequest is not null or undefined.
The object will be instantiated with the new keyword.
Its onreadystatechange event listener (see the section "XMLHttpRequest" earlier in this chapter) will be defined as a function named handleResponse( ).
The code calls the request object's open( ) and send( ) methods.
In this case, the window.XMLHttpRequest object will not exist in the browser object model. Therefore, another branch of the if test is necessary in your code:
else if (window.ActiveXObject){
request=new ActiveXObject("Microsoft.XMLHTTP");
if (! request){
request=new ActiveXObject("Msxml2.XMLHTTP");
}
if(request){
request.onreadystatechange=handleResponse;
request.open(reqType,url,true);
request.send(null);
}
}This code fragment tests for the existence of the top-level window object ActiveXObject, thus signaling the use of Internet Explorer. The code then initializes the request using two of a number of possible ActiveX program IDs (here, Microsoft.XMLHTTP and Msxml2.XMLHTTP).
You can get even more fine-grained when testing for different versions of the IE request object, such as Msxml2.XMLHTTP.4.0. In the vast majority of cases, however, you will not be designing your application based on various versions of the MSXML libraries, so the prior code will suffice.
The code then makes one final check for whether the request object has been properly constructed (if(request){...}).
Given three chances, if the request variable is still null or undefined, your browser is really out of luck when it comes to using the request object for Ajax!
Here's an example of an entire compatibility check:
/* Wrapper function for constructing a request object.
Parameters:
reqType: The HTTP request type, such as GET or POST.
url: The URL of the server program.
asynch: Whether to send the request asynchronously or not. */
function httpRequest(reqType,url,asynch){
//Mozilla-based browsers
if(window.XMLHttpRequest){
request = new XMLHttpRequest( );
} else if (window.ActiveXObject){
request=new ActiveXObject("Msxml2.XMLHTTP");
if (! request){
request=new ActiveXObject("Microsoft.XMLHTTP");
}
}
//the request could still be null if neither ActiveXObject
//initialization succeeded
if(request){
initReq(reqType,url,asynch);
} else {
alert("Your browser does not permit the use of all "+
"of this application's features!");
}
}
/* Initialize a request object that is already constructed */
function initReq(reqType,url,bool){
/* Specify the function that will handle the HTTP response */
request.onreadystatechange=handleResponse;
request.open(reqType,url,bool);
request.send(null);
}
While this article is placed in the upload subsection, it might not be the best place for ot. Because it's not a regular "how-to-upload- files-with-ASP.NET" article.
I might write such an article in the future but this is dealning with a problem you might encounter when using some sort of template-system on your site. I mean basically, all requests goes to a single ASPX page, such as default.aspx and depending on the context (for example sent in by a request variable) you load different user controls (ASCX) files.
For example:
default.aspx?page=start - might show start page
default.aspx?page=clientupload - might show a page when the client could upload a file to your server
Now, back to file upload. To upload a file you need to do two things:
1. Throw in a input type=file control
2. Set your forms enctype to multipart/form-data <form enctype="multipart/form-data" runat="server">
protected void EnsureEncType()
{
System.Web.UI.Control oParent = Parent;
while( oParent != null && oParent.GetType() != typeof( System.Web.UI.HtmlControls.HtmlForm ) && oParent.GetType().FullName != "System.Web.UI.Page" )
{
oParent = oParent.Parent;
}
System.Web.UI.HtmlControls.HtmlForm oForm = oParent as System.Web.UI.HtmlControls.HtmlForm;
if ( oForm != null )
oForm.Enctype = "multipart/form-data";
}
Setting up a live demo on your website is often important for your business - people want to see how the application looks and get a feeling of it and not all people are willing to download a trial version and go through a (painful?) install process just to get the first look. However, the problem is that you need to strip down the demo version a little bit. You don't want visitors to be able to change login password etc (after that noone would have access to the demo) or change information in your underlying database. Here's how I have solved it for my demosites for AdMentor and KBMentor. In short : I compile the application with an extra flag defined (DEMOVERSION) and in my code I insert some extra conditional code to behave differently when that flag DEMOVERSION is defined. First step is to create a custom project context Then we add the conditional variable (called DEMOVERSION): Now we can insert some conditional code.We do that by using the #if directive in our code. 

#if (DEMOVERSION)
here we can add code which only will be compiled in the special demoversion
#endif
I want to throw up a JavaScript when the user tries something not allowed - for example when trying to change password:

So, this is done by adding a JavaScript alert box to the onclick event:
private void Page_Load(object sender, System.EventArgs e)
{
EnsureEncType();
EnsureChildControls();
if ( !IsPostBack )
{
#if (DEMOVERSION)
btnUpdate.Attributes.Add("onclick", "alert('Not possible in demo version'); return false;");
btnDelete.Attributes["onclick"] = "alert('Not possible in demo version'); return false;";
#endif
Now, this is done in Page_Load and while this example is pretty easy to understand you might have a more finegrained structure of how to enable/disbale controls, for example based on current user rights, and/or after a lot of postbacks a certain button might be enabled etc. The easiest way to override such code without needing to make the original code much more complex is to leave it at is and make your changes in OnPreRender: protected override void OnPreRender(EventArgs e)
{
#if (DEMOVERSION)
btnDelete.Enabled = false;
btnDoUpload.Enabled = false;
btnOK.Enabled = false;
#endif
Here it doesn't matter what code has been executed and checked against all different kind of state - we just disable the buttons regardless of which. Now, the last thing to do. Not all people have JavaScript enabled - so those people must also be stopped. Here we need to add some serverside code in the actual handler functions: private void btnOK_Click(object sender, System.EventArgs e)
{
#if (DEMOVERSION)
return;
#endif
..regular code to save etc
While I bet you all know how to (from your own webpage) read another webpage, even located on another site/server, so while I will show you the code for it, I also want to show you a very practical use of it.
Background
As you might have seen I have created a new layout for this site, ASPCode.net. I am using the beta version of KBMentor but that's not what I want to talk about here. However, for reasons I won't get into, I wanted to create the site in directory aspcode.net/articles/ and therefore I naturally created a vdir (own application) in the articles drectory and thereaftter installed my KBMentor CMS.
Problem
One of the functions of KBMentor is to produce a Google SiteMap out of all the articles and pages. So I wanted to test it out - but ran into a big problem. The page to submit to Google SItemap is http://www.aspcode.net/articles/googl...map.ashx - but it wouldn't let me - simply because it is not located in the root of my domain. Moving the ashx page to the root wouldn't help at all, simply because another application is installed in that location.
Solution
Now to the solution. I did add a new ashx page in the root domain - and what is does is simply "screenscrape" the ashx file in the articles directory.
public void ProcessRequest (HttpContext context)
{
//Screenscrape
CookieContainer CC = new CookieContainer();
HttpWebRequest Req = (HttpWebRequest) WebRequest.Create("http://www.aspcode.net/articles/googlesitemap.ashx");
Req.CookieContainer = CC;
WebResponse webResponse = Req.GetResponse();
string sTxt = new System.IO.StreamReader(webResponse.GetResponseStream(),
System.Text.Encoding.Default).ReadToEnd();
webResponse.Close();
context.Response.ContentType = "text/xml";
context.Response.ContentEncoding = System.Text.Encoding.UTF8;
context.Response.Write( sTxt);
//
// TODO: Add constructor logic here
//
}
When moving your pages from one place to another it is very tempting to handle old inlinks by creating a simple Response.Redirect( sNewPage, true );
This sure will work, but this type of redirect is a 302 and is meant for temporary relocations of pages. But your pages are permanently moved and therefore you should use a 301 Moved Permanently status code. This should preserve your search engine rankings for that particular page.
To solve it you could install some sort of redirect filter(ISAPI dll). I was looking into those type of solutions and found IISMods URL Rewrite Filter for IIS.
Such a solution is very flexible and since it is a IIS filter it is possible to rewrite URL:s for all kind of filetypes, not only for aspx pages but say images (ex http://www.hello.com/*.gif could be transferred to http://www.hello.com/test/*gif ).
It is however not possible for everyone to install a ISAPI filter on their website, therefore I here present a solution on how you can achieve 301 redirects with pure ASP.NET code instead.
In your old page you can write code such as
private void Page_Load(object sender, System.EventArgs e)
{
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location","http://www.aspcode.net/newpage");
}
For me who wanted to redirect all calls to http://kbmentor.aspcode.net/whatever/it/could/be/foo.aspx to http://www.aspcode.net/articles/whatever/it/could/be/foo.aspx took and didn't have to think about pictures, cause they were "base" linked with the application took the idea one step further.
I created a new web application to install on kbmentor.aspcode.net. Basically it only contains a global.asax which handles Application_BeginRequest like this:
protected void Application_BeginRequest(Object sender, EventArgs e)
{
string sOldPath = HttpContext.Current.Request.Path.ToLower();
string sPage = "http://www.aspcode.net/articles/" + sOldPath;
Response.Clear();
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location",sPage);
Response.End();
}
The ASP.NET cache is simply fantastic, but there are some shortcomings. While it is so easy to create a cache item dependent on, say for example a XML file (meaning the cache item will expire when the file xxx.xml is changed) it is not so common for such scenarios in my opinion. Also, now in .NET 2.0 you can create SqlCacheDependencys, meaning an cached item will be expired (and therefore a fresh read fromthe database will be executed) when something in the database is changed (could be set on query level actually).
However, to me such solutions are so much overkill, lots of overhead and also (for SqlCacheDependency ) you tie your solution pretty much to SQL 2005.
Most often you just want to cache some data in your application, example
string sTxt = "";
if ( context.Cache["RSSFEED123"] == null )
{
sTxt = BuildXmlString(context);
context.Cache.Insert( "RSSFEED123", sTxt, ..some depencency object... );
}
else
sTxt = context.Cache["RSSFEED123"].ToString();
work with txt...
My point is that most often YOU have the control of knowing when the Cache item should expire. In 99.99% of my cases it should trigger when an administrator enters a new/changes an existing article or whatever in the admin GUI.
So, my solution (here I show it with no cachedependency at all, living for the lifetime of the whole application) but you can of course use it in conjunction with a cachedependency.
Code using it:
string sTxt = "";
if ( context.Cache["RSSFEED123"] == null )
{
sTxt = BuildXmlString(context);
context.Cache.Insert( "RSSFEED123", sTxt );
}
else
sTxt = context.Cache["RSSFEED123"].ToString();
Admin GUI:
private void btnUpdate_Click(object sender, System.EventArgs e)
{
//Save to database, then call global static function
HelpClasses.Context.InvalidateAllCache();
}
HelpClasses.Context:
public static void InvalidateAllCache()
{
if ( System.Web.HttpContext.Current.Cache["RSSFEED123"] != null )
System.Web.HttpContext.Current.Cache.Remove("RSSFEED123");
}
So inessence, when the administrator clicks the Save button we go to HelpClasses.Context.InvalidateAllCache() and it simply removes the item(s) from the cache.
I know I could maybe create a specialized cache dependency class derived from CacheDependency - but then the problem is that the GUI needs to communicate with it. I always take the easy way out, cause in the end it is all about delivering a working solution for the customer - not creating the most .NETed solution possible :)
I'm publishing this list for my own sake actually, never seem to remember which variable gives you what. Sourcecode and description behind the scenes to generate this table is available in Related articles.
ALL_HTTP HTTP_CONNECTION:Keep-Alive HTTP_ACCEPT:*/* HTTP_ACCEPT_ENCODING:gzip, deflate HTTP_ACCEPT_LANGUAGE:sv HTTP_HOST:localhost:1229 HTTP_USER_AGENT:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1) ALL_RAW Connection: Keep-Alive Accept: */* Accept-Encoding: gzip, deflate Accept-Language: sv Host: localhost:1229 User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1) APPL_MD_PATH APPL_PHYSICAL_PATH D:\code\web\demos\membership\ AUTH_TYPE NTLM AUTH_USER SYSTEMEN-D9AE02\Stefan Holmberg AUTH_PASSWORD LOGON_USER SYSTEMEN-D9AE02\Stefan Holmberg REMOTE_USER SYSTEMEN-D9AE02\Stefan Holmberg CERT_COOKIE CERT_FLAGS CERT_ISSUER CERT_KEYSIZE CERT_SECRETKEYSIZE CERT_SERIALNUMBER CERT_SERVER_ISSUER CERT_SERVER_SUBJECT CERT_SUBJECT CONTENT_LENGTH 0 CONTENT_TYPE GATEWAY_INTERFACE HTTPS HTTPS_KEYSIZE HTTPS_SECRETKEYSIZE HTTPS_SERVER_ISSUER HTTPS_SERVER_SUBJECT INSTANCE_ID INSTANCE_META_PATH LOCAL_ADDR 127.0.0.1 PATH_INFO /membership/servervariables.aspx PATH_TRANSLATED D:\code\web\demos\membership\servervariables.aspx QUERY_STRING REMOTE_ADDR 127.0.0.1 REMOTE_HOST 127.0.0.1 REMOTE_PORT REQUEST_METHOD GET SCRIPT_NAME /membership/servervariables.aspx SERVER_NAME localhost SERVER_PORT 1229 SERVER_PORT_SECURE 0 SERVER_PROTOCOL HTTP/1.1 SERVER_SOFTWARE URL /membership/servervariables.aspx HTTP_CONNECTION Keep-Alive HTTP_ACCEPT */* HTTP_ACCEPT_ENCODING gzip, deflate HTTP_ACCEPT_LANGUAGE sv HTTP_HOST localhost:1229 HTTP_USER_AGENT Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)
While this solution might seems a little odd (or more correctly the problem might seem very odd) but this technique has sure solved a lot of problems for me. What I'm gonna show you is a was to manipulate the resulting HTML and ASP.NET page has generated just before it's sent to the browser. Now you might ask, isn't that what ASP Server controls are made for? To generate the HTML for you? Because there are certain times when the HTML or JavaScript it generates are not right and you might even not (if using a third party control) be able to modify the underlying control generating the code. For example I've had problems with some thirdparty components where I was unable to get it to render the correct paths for including images etc (it simply couldn't point to the specific location I had them stored). So, the plan is to somehow intercept the rendering, make my modifications to the HTML generated and then just pass my modified copy on to the browser. One other example (which I actually have used in some projects) is to create some sort of "template replacer", where others can create their own templates and also write some special tags that your application is supposed to replace with some meaningful - for example Thats the type of example I am gonna show you, consider this layout: Now, we are supposed to replace the $CURRENT_DATETIME text with current date and time. I.e we want this result when running: So first the code - all the magic happens in Render:
$currentarticle_name might be replaced with
the name of the current article (the one the user is browsing)

protected override void Render(HtmlTextWriter writer)
{
using(System.IO.MemoryStream msOur = new System.IO.MemoryStream())
{
using(System.IO.StreamWriter swOur = new System.IO.StreamWriter(msOur))
{
HtmlTextWriter ourWriter = new HtmlTextWriter(swOur);
base.Render(ourWriter);
ourWriter.Flush();
msOur.Position = 0;
using(System.IO.StreamReader oReader = new System.IO.StreamReader(msOur))
{
string sTxt = oReader.ReadToEnd();
sTxt = sTxt.Replace("$CURRENT_DATETIME", DateTime.Now.ToString());
Response.Write(sTxt);
oReader.Close();
}
}
}
}
What are we doing? Our overridden Render method gets called (not the Page.Render - which would render it to the browser). We create a new HtmlTextWriter ourWriter - which we send to the base.Render (i.e Page.Render()). However, ourWriter is connected to the streamwriter swOur - which in turn is connected to the memorystream msOur (instead of the outputstream of the response object). This way, ASP.NET does handle all the rendering the way it usually does - but the resulting HTML ends up in the memorystream msOur.
We then set the reading position of msOur to 0 - which means we can read from it from the beginning.And now we read everything from it (using the streamreader object) to our sTxt variable.
And now we have all the rendered HTML in sTxt - we can just replace the fabricated template tag $CURRENT_DATETIME with the current time.
And finally send it to the browser by Response.Write.
While there aren't much code for you to copy to get it going in your own project I have included a download zip file containing the solution and code files.
This function can be used to retrieve the current page:s name, i.e default.aspx, hello.aspx or whatever.
public string GetCurrentPageName()
{
string sPath = System.Web.HttpContext.Current.Request.Url.AbsolutePath;
System.IO.FileInfo oInfo = new System.IO.FileInfo(sPath);
string sRet = oInfo.Name;
return sRet;
}
By going through System.Web.HttpContext.Current object we are able to have this function in a generic dll or class - and not in each and every page needing to call it.
In this article we will create a simple one page ASP.NET web application, implementing paging using the cool MySQL feature LIMIT and SQL_CALC_FOUND_ROWS.
One of the coolest things about MySQL is some of its non standard features. It might sound like a weird thing to say, but being a web developer I just love the simplicity and performance MySQL gives me when it comes to paging. Cause in the typical web app you need paging.
The two problems a developer faces in such a paged web application
1. Two questions.
It's pretty neat to present a list of links to all pages available to the user, instead of just a next/prev link. Typically that means two questions.
select count(*) from bla bla ALL WHERE CONDIITIONS
select * from bla bla ALL WHERE CONDIITIONS
2. Just retrieving the rows for current page from the database.
It a waste memory to read 100000 records into a dataset and the use a pagedatasource. It's of course better to let the database engine do the filtering and having it just return the actual records to be displayed on the current page.
And also - you probably need to show the total number of pages available.
However when using the LIMIT clause in MySQL you solve the problem number two. As for number one - since we still need to get the total number of records, there is a feature for that as well, SQL_CALC_FOUND_ROWS.
So in short here's the code for reading the data:
public DataTable GetData
{
get
{
//Where to start???
long lStart = 0;
if (Request["p"] != null && Request["p"].Length > 0)
{
lCurrentPage = Convert.ToInt32(Request["p"]);
}
if ( lCurrentPage < 1 )
lCurrentPage = 1;
lStart = (lCurrentPage * lPageSize) - lPageSize;
string sSQL = "select SQL_CALC_FOUND_ROWS table_schema, table_name from information_schema.tables ";
sSQL += " order by table_schema, table_name ";
sSQL += "limit " + lStart.ToString() + "," + lPageSize.ToString() + ";";
sSQL += "select found_rows();";
DataSet ds = MySql.Data.MySqlClient.MySqlHelper.ExecuteDataset(System.Configuration.ConfigurationManager.AppSettings["ConnectionString"],
sSQL);
m_Data = ds.Tables[0];
lTotalCount = Convert.ToInt32(ds.Tables[1].Rows[0][0]);
return m_Data;
}
}
We add the SQL_CALC_FOUND_ROWS select modifier before the column list. This will tell MySQL to calculate the TOTAL number of rows and make it available in a special variable - which we get with select found_rows(). As you can see we do send both the queries in one command top the server and get them back in a dataset with the result in one table and the count in the second. That's so cool.
The rest of the code is just a matter of some math to calculate the current page (`query params ?p=12 etc) and of course rendering (the example uses a simple repeater)


© All Rights Reserved. DOTNET TUTORIALS
Theme by : PHP Web Hosting | Converted into Blogger Templates by Theme Craft | Falcon Hive
