Sunday, January 31, 2010

ASP.NET Logout on Session Expire

Here's a way to enable logout after session has expired in your ASP.NET pages.


Let us begin with the sessionState tag inside the web.config file:


<system.web>
    <sessionState mode="InProccookieless="falsetimeout="30"/>
</system.web>


Make sure to place it inside the system.web tag. For the attributes, we use InProc mode to store the session on the local computer, cookieless is set to false which means it will store the session as cookies (if you set this to true, you will get some jumbled alphanumeric characters in your webpage's URL) and finally timeout which has a numeric value equal to how long you want your session in minutes before it expires.


For more information on sessionState attributes, check out msdn: http://msdn.microsoft.com/en-us/library/h6bb9cz9(VS.71).aspx


Now the snippet above alone will not make your page redirect automatically to your logout page after session has expired. We still need human intervention to enable that. So we add this next logic to the Master Page's page_load event (or to all pages of a website if you're not using master pages):



protected void Page_Load(object sender, EventArgs e)
{
    //1st: Every postback should pass through this code.
    //     Make a decision statement to check if user has already logged in.
    if (user has already logged in)
    {
        //2nd: Check your user session. 
               If session is null (expired) then continue.
        if (Session["user_session"] == null)
        {
            //3rd: Clear all sessions, data, connections, etc. (optional)
                   Redirect to logout page.
            .
            .
            .
            Page.Response.Redirect("logout_page", true);
        }
    }
}






Handling session expiration is required for web pages which uses sessions to store data so you won't encounter the object reference not set to an instance of an object error should your session objects expire.


-k


ASP.NET Server tag was not well formed

TIP: ASP.NET C# Expression Language with Javascript

Here's a tip on how to use C# bind code inline with javascript events, first let's use a LinkButton for example:

<asp:LinkButton ID="lnkBtn" runat="server" OnClick="lnkBtn_Click" OnClientClick='<%# "document.getElementById(\"txtHtmlText\").value = " + Eval("id") + ";" %>' />

Imagine this LinkButton is inside a binded control like Gridview or Repeater, etc., now look at the OnClientClick attribute. Remember to be careful with single and double quotes.

1. Use single quotes to contain the whole expresion.

          OnClientClick='  ...  '

2. Enclose inner javascript statements with double quotes and concatenate it with .NET bind statements (like Eval()) with the "+" symbol. 

          "document.getElementById(\"txtHtmlText\").value = " + Eval("id") + ";"

3. Use escaped double quotes (the one with the slash) if ever you'll use double quotes inside another one.

          getElementById(\"txtHtmlText\")

So the next time you get the error "Server tag was not well formed" just remember these 3 tips.



-k

Thursday, January 28, 2010

Change Web Service name in ASP.NET

For example you have a Web Service named AAAWebService


And you want to change its name to let's say BBBWebService. If you open your code and change it like this..

public class BBBWebService : System.Web.Services.WebService

{

}

... and then run it, you would get an error like this...







The solution is to right click on your web service asmx file and click view markup.




Change the name here and you're done.

<%@ WebService Language="C#" CodeBehind="AAAWebService.asmx.cs" Class="Web_Services.BBBWebService" >



-k

ASP.NET C# Refresh page from code behind

To refresh your page you may use the javascript function:


window.location.reload();


For example you can use that on the OnClientClick attribute of an ASP.NET button:


<asp:button ID="btnRefresh" OnClick="btnRefresh_Click" runat="server" Text="REFRESH" 
OnClientClick="window.location.reload();" />


The code above will work fine, but if let's say you have some other server-side logic you want to run on the code for btnRefresh_Click, it won't be executed because the page would already be refreshed by then.


So to run your server-side code, first remove the OnClientClick attribute on the asp button tag above. Then place the following code inside your button click event:



protected void btnRefresh_Click(object sender, EventArgs e)
{
    //Your logic here...
    Page.Response.Redirect(HttpContext.Current.Request.Url.ToString(), true);
}


We simply redirect the page to its current url and that does the trick.



-k





Wednesday, January 27, 2010

Javascript Window.Open() in .NET

Here's an example on how to popup a new window using javascript in .NET. First we'll use a simple button as the trigger source for the popup.

<asp:Button ID="btnPopup" runat="server" />

Then on the page load in the code behind, add an onclick attribute to the button.

protected void Page_Load(object sender, EventArgs e)
{
    btnPopup.Attributes.Add("onclick", "window.open('http://" + Page.Request.Url.Authority + "/TestPage.aspx','Test','status,toolbar,location,menubar,directories,resizable,scrollbars,width=400,height=400')");
}
 
The Page.Request.Url.Authority in the code above will retrieve the root url of your site. Then just add the name of the aspx file to popup after the forward slash (if it is within another directory, just add the directory name before the aspx file, and so forth).
 
To explain the javascript part, window.open() accepts 3 parameters: the url of the site to popup, the window name (not title, the title should be in the head part of the new page, so make sure it doesn't have spaces), and window features.
 
Here's some of the commonly used window features:
 
status:
 

   
toolbar:


 
location:


 
menubar:


 
directories:


 
resizable: window can be resized


 
scrollbars:


 
width: the width of the window in pixels
 
height: the height of the window in pixels



To use these features simply add them to the list like this:

"window.open
('http://www.testpage.com','Test','status,toolbar,location,menubar,directories,resizable,scrollbars,width=400,height=400')"




If not then simply omit them:

"window.open('http://www.testpage.com','Test','width=400,height=400')"





That's it, one note though, make sure that the aspx page in the url exists or you'll get an error.



-k

Monday, January 25, 2010

Login failed for user 'NT AUTHORITY\IUSR'

If you encountered this error while running your published website or web service in IIS7:

Message: Sys.WebForms.PageRequestManagerServerErrorException: Cannot open database "[DB_NAME]" requested by the login. The login failed.

Just follow these simple steps to solve the problem.

1. Open SQL Server Management Studio.



2. On the left menu, expand Security then Logins. Check if 'NT AUTHORITY\IUSR' exists. If not then that is the cause of the problem.




3. Right-click on Logins then click New Login...



4. On the General page, click Search...



5. On the next popup window, click Advanced...



6. Then on the following window, click Find Now and find IUSR on the Search Results. Then click OK.



7. Back on the left menu, you'll now see the 'NT AUTHORITY\IUSR' user. Right click on it and click Properties.




8. On the Server Roles page, check on sysadmin.



9. Then on the User Mapping page check on the database name you need access to; and below that on the database role membership make sure to also check on db_owner then click OK.






...And that's a wrap, you shouldn't be seeing the login failed error now.



-k

Friday, January 22, 2010

Internet Explorer 6 for Windows Vista / Windows 7

If you're running on Vista or Windows 7 it's sure you're IE browser is already IE7 or IE8, but suppose you're developing for clients who will still use the "buggy" IE6 (so it simply means you have to develop sites which takes those bugs into consideration), one way is to install a Virtual Machine on your PC that will run Windows XP which will surely use much of your PC's resources (hard drive space and memory). The other is this program I found called IETester. Check it out here.




It's still an alpha release so there might be bugs here and there but it will only take you a minute to download its 25mb filesize and it's free. Now you can live with those cross-browser compatibility issues all over again, one of those I will be tackling on my next post so keep tuned.


-k

How to use events like onblur, onfocus, etc. for ASP.NET Texbox and other controls

Have you ever wondered if you can use other event attributes for some ASP.NET controls, say an ASP.NET Textbox?



When upon checking, all you see that's available is a TextChanged event. And you know that the html input tag can support other events like:


Source: w3schools



A workaround is to create an ASP.NET Button and place it inside a hidden div:

<div style="display: none;">
    <asp:Button ID="btnTextBoxEventHandler" runat="server"
    OnClick="btnTextBoxEventHandler_Click" />
</div>
 
And here's the markup for the textbox, just a regular one:

<asp:Textbox ID="txt1" runat="server" />

Now on your page onload event, add an attribute to your textbox:

protected void Page_Load(object sender, EventArgs e)
{
    txt1.Attributes.Add("onblur", this.Page.ClientScript.GetPostBackEventReference(this.btnTextBoxEventHandler, ""));
}

Then of course, the event handler for the button:

protected void btnTextBoxEventHandler_Click(object sender, EventArgs e)
{
    //Place code here for onblur..
}

Now place the code you want to trigger (when the textbox loses focus) inside the button event and see what happens. Try experimenting with other event attributes and ASP.NET control combinations too.


-k

Thursday, January 21, 2010

Visual Studio Line Numbers

Ever wondered why errors in Visual Studio show you line numbers where it occured yet upon checking back on your code you found none? That is because by default, on installation of Visual Studio, line numbers are disabled. To enable it simply go to menu then tools then options.





Once the options window pop up, expand on Text Editor and select the language you want to show line numbers and simply click the checkbox "Line numbers".





You can do this to other languages you want, better if you do it on all.





That's it, the only thing I've been wondering is why Microsoft opted to disable it by default when we all know that line numbers are important for debugging..




-k

Get Client CPU ID with Javascript

For whatever purpose it may serve, here's how to get the client CPU ID through javascript. Just a warning though, this script uses ActiveX object which is disabled by default on browsers and I'm not sure if you can enable it on non-IE. So for now we'll just do it with Internet Explorer.


Go to Tools then Internet Options.





Then on the Security tab click on "Custom Level..."





Go down until you see "Initialize and script ActiveX controls not marked as safe..." and enable it then click Ok.


Now we go to the scripting part. Add this next snippet in your html page.



<script type="text/javascript">
    var str = "";
    var wmi = GetObject("winmgmts:{impersonationLevel=impersonate}");
    e = new Enumerator(wmi.InstancesOf("Win32_Processor"));
    for(; !e.atEnd(); e.moveNext()) {
        var s = e.item();
        str = s.ProcessorID;
    }
</script>


You can add the script above anywhere on your html head or body, but if you chose to put it on the body be sure to place it anywhere above this next snippet, which just displays the CPU ID in the page.


<b>Client CPU ID : </b><span id="spanCPUID" />

<script type="text/javascript">

    document.getElementById("spanCPUID").innerHTML = str;
</script>
                        


And that's it, you should now see the client computer's cpu id when you run the page.


-k

Source for AJAX loading gif

Here's a good website to grab some free loading animation gif's for your websites.


Ajaxload.Info






A sample one, cool facebook-style loading gif




Creating Scalar-valued Functions in SQL Server Management Studio

We use functions in T-SQL to return a value based on passed parameters just like we do on any other language. But in SQL one use of functions is to provide in-line data processing in our queries like you will see in our example today.

Begin by expanding the database in your SQL Management Studio, then Programmability, Functions, and right-clicking on Scalar-valued Functions and then select "New Scalar-valued Function...".




Notice Table-valued functions? We won't cover it for now as those kind of functions return a whole table like Stored Procedures. Maybe we'll do that in another lesson. But right now let's focus on Scalar-valued functions which will return a single value.

From the template, you may delete the comments if you want.

Our sample function will be returning a string value (varchar in SQL) of the month depending on the passed integer, which can range from 1-12. Let's call our function GetMonthName.

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[GetMonthName]
(
    -- Add the parameters for the function here
    @month int
)

RETURNS varchar(10)
AS
BEGIN
    DECLARE @month_name varchar(10)

    IF @month = 1
    BEGIN
        SET @month_name = 'January';
    END
    ELSE IF @month = 2
    BEGIN
        SET @month_name = 'February';
    END
    ELSE IF @month = 3
    BEGIN
        SET @month_name = 'March';
    END
    ELSE IF @month = 4
    BEGIN
        SET @month_name = 'April';
    END
    ELSE IF @month = 5
    BEGIN
        SET @month_name = 'May';
    END
    ELSE IF @month = 6
    BEGIN
        SET @month_name = 'June';
    END
    ELSE IF @month = 7
    BEGIN
        SET @month_name = 'July';
    END
    ELSE IF @month = 8
    BEGIN
        SET @month_name = 'August';
    END
    ELSE IF @month = 9
    BEGIN
        SET @month_name = 'September';
    END
    ELSE IF @month = 10
    BEGIN
        SET @month_name = 'October';
    END
    ELSE IF @month = 11
    BEGIN
        SET @month_name = 'November';
    END
    ELSE IF @month = 12
    BEGIN
        SET @month_name = 'December';
    END
    ELSE
    BEGIN
        SET @month_name = 'Invalid month number!';
    END


    RETURN @month_name;
END

So to explain, we use the CREATE FUNCTION keyword to create our function followed by our desired name then the parameters (name and type) enclosed in parentheses. Then the RETURNS keyword followed by its type which in our case is a varchar. It's just to say that our function must return a varchar. After that follows our logic which is just a basic if..else.. that will return the corresponding month name or invalid if it is not between 1 to 12. Then of course return that string for our varchar return value.

Here's sample output from our scalar-valued function:



In our 4th example we use the built-in SQL function getdate() to get the current system date then enclose it with another built-in function month() which accepts datetime as parameter and returns the month in integer form, which our function accepts as parameter and finally returns the name of the month.

'Til our next lesson... I hoped you learned/remembered something today.

-k

Wednesday, January 20, 2010

Failed to access IIS metabase

So after publishing your asp.net website to IIS you've tried to view the webpage in the browser and you get the error Failed to access IIS metabase



Go to command prompt, and go to C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727

From there, type aspnet_regiis -i and you should see something similar to this..




There, that should do the trick, try browsing the page again and you shouldn't be seeing that error anymore.


-k

ASP.NET Gridview Paging and Sorting with AJAX

To enable paging and sorting of our gridviews with ajax, we must first include the prerequisites of any ajax-enabled asp.net website, the script manager and the update panel.

We place the scriptmanager inside of our form (note the enable partial rendering attribute, it must be set to "true" to enable asynchronous postbacks):

<asp:ScriptManager ID="sm" runat="server" EnablePartialRendering="true" />

Then enclose our gridview with the update panel.

<asp:UpdatePanel ID="up" runat="server">
    <ContentTemplate>
        <asp:GridView ID="gv" runat="server"
        AllowSorting="true" AllowPaging="true" PageSize="10"
        OnSorting="gv_Sorting" OnPageIndexChanging="gv_PageIndexChanging">
        </asp:GridView>
    </ContentTemplate>
</asp:UpdatePanel>

Notice we set both AllowSorting and AllowPaging to true, then add PageSize for the number of items to be shown per page. Next we'll add the code behind for the sorting and paging events.



Let's start first with the sorting part.

We'll assume in this next snippet that we're getting our data from the database or whatsoever then assign it to a DataSet, then finally bind the dataset to our GridView.

private void BindGridView()
{
    //Get data from there..
    //Assign to dataset here..
    DataSet ds = TheData;

    //Bind dataset to gridview
    gv.DataSource = ds;
    gv.DataBind();

    //We persist DataTable from our DataSet through session.
    Session["sess_table"] = ds.Tables[0];
}

To explain the code above, this function can be placed anywhere in your code behind, it's where you load data into your gridview (*note: imagine TheData already has our data from the database or any other source, loading data to a dataset will be in another lesson). What's new here is the assigning of the DataTable from our DataSet through session. We need that to preserve our data asynchronously.


Then the next step will be to add this other function, again it can be placed anywhere in the code behind.


private string GetSortDirection(string column)
{
    //By default, set the sort direction to ascending.
    string sortDirection = "ASC";

    //Retrieve the last column that was sorted.
    string sortExpression = ViewState["SortExpression"] as string;

    if (sortExpression != null)
    {
        //Check if the same column is being sorted.
        //Otherwise, the default value can be returned.
        if (sortExpression == column)
        {
            string lastDirection = ViewState["SortDirection"] as string;
            if ((lastDirection != null) && (lastDirection == "ASC"))
            {
                sortDirection = "DESC";
            }
        }
    }

    //Save new values in ViewState.
    ViewState["SortDirection"] = sortDirection;
    ViewState["SortExpression"] = column;

    return sortDirection;
}

The code above was taken directly from the msdn website, what it does is just return Ascending or Descending depending on the gridview column header that was clicked.

And finally the sorting event handler..

protected void gv_Sorting(object sender, GridViewSortEventArgs e)
{
    //Retrieve the DataTable from the session object.
    DataTable dt = Session["sess_table"] as DataTable;

    if (dt != null)
    {
        //Sort the table.
        dt.DefaultView.Sort = e.SortExpression + " " + GetSortDirection(e.SortExpression);
        //Bind the sorted table to the gridview.
        gv.DataSource = Session["sess_table"];
        gv.DataBind();
        //Update the UpdatePanel or the changes won't show.
        up.Update();
    }
}




Okay we're already halfway there, next is the paging part, this is really short and simple compared to the sorting one.

protected void gv_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    gv.PageIndex = e.NewPageIndex;
    BindGridView();
    upTransactions.Update();
}

3 lines and that's it. Okay to explain: the first line just sets the new page index to the gridview's PageIndex attribute. Next we use the function we created earlier to bind our data to the gridview again (that's assuming the imaginary code, remember?). And then finally update our UpdatePanel to reflect the changes.

...And thanks, I hope you learned something from this post, or remembered something you forgot.

-k