Blogger Widgets
  • Sharing Photos using SignalR
  • TFS Extenstion - allows copy work items between projects
  • Displaying jquery progressbar with ajax call on a modal dialog
  • Managing windows services of a server via a website
  • Exploring technologies available to date. TechCipher is one place that any professional would like to visit, either to get an overview or to have better understanding.

Search This Blog

Showing posts with label ASP.NET Ajax. Show all posts
Showing posts with label ASP.NET Ajax. Show all posts

Tuesday, 13 September 2011

JQuery dialog inside update panel generating duplicate elements

JQuery dialog is a nice feature provided by JQuery UI, having said care should be taken when using dialog boxes inside an update panel.

Consider a dialog box is inside an update panel as shown below :-








Now javascript for displaying the dialog

var btnAddBloggerData= $("#btnAddBloggerData");
btnAddBloggerData
  .unbind("click")
  .bind("click", function () {
  this.disabled = true;
  $("#bloggerdata_dialogform").dialog("destroy");
  $("#bloggerdata_dialogform").dialog({
            autoOpen: true,
            modal: true,
            width: 500,
            buttons: {
                Cancel: function () {
                    $(this).dialog("close");
                },
                "Create": function (evt) {
                /*ajax call to update */
               }
            },
            close: function () {

            }
        });

});

All seems right and works fine. If this has been an asp.net server control (.ascx) would have completely weird behaviour. Each time a post back occurs a new dialog is added and finally there would be duplication of ids ie.. number of elements with id as "bloggerdata_dialogform" will increase for every postback.

Hence to resolve this issue do not use $("#bloggerdata_dialogform").dialog("destroy"); which is a killer. Now modify your script to

$.ready(function(){
   $("#bloggerdata_dialogform").dialog({
            autoOpen: false,
            modal: true,
            width: 500,
            buttons: {
                Cancel: function () {
                    $(this).dialog("close");
                },
                "Create": function (evt) {
                /*ajax call to update */
               }
            }
        });
});
var btnAddBloggerData= $("#btnAddBloggerData");
btnAddBloggerData
  .unbind("click")
  .bind("click", function () {
  this.disabled = true;
  $("#bloggerdata_dialogform").dialog("open");

});


So instead of destroying the element and use the same element for every postback.

Errors using inadequate data are much less than those using no data at all.
Charles Babbage

Friday, 17 June 2011

Disable a button after onclick inside an update panel

Avoiding users to click on a button more than once can be done as follows :-

btnSubmit.Attributes.Add("onclick", "this.disabled=true;" + Page.ClientScript.GetPostBackEventReference(btnSubmit, "").ToString());

This method is quite nice but if you would want to apply for entire website then you would have to duplicate the code in every page, usercontrols etc. Instead this simple script allows you to handle once for all

 var prm = Sys.WebForms.PageRequestManager.getInstance();
    prm.add_initializeRequest(InitRequest);
    prm.add_endRequest(EndRequest);
    function InitRequest(sender, args) {
        var btn = $get(args._postBackElement.id);
        if (btn && btn.type == "submit") {
                btn.disabled = true;
        }
    }
    function EndRequest(sender, args) {      
        var btn = $get(sender._postBackSettings.sourceElement.id);
        if (btn && btn.type == "submit") {
                btn.disabled = false;
        }
    }

Above mentioned method is for ASP.NET ajax where update panels are used.

Hardware: the parts of a computer that can be kicked. ~Jeff Pesis

Wednesday, 4 May 2011

Improving Performance of JQGrid for millions of records : Part2


This article will address more from ASP.NET point of view assuming you have already read Part 1


Now that you have all the back-end available lets get on with developing the website.

Start with the usual steps

1. Create an ASP.NET website
2. Add the required java scripts (JQuery, JQueryUI, JQGrid plugin)
3. Now add a new web service to the project and name it InvoicingService

InvoicingService.cs should look like
[WebMethod, ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string GetInvoiceData(int? page, int? rows, string sidx, string sord, bool _search, string searchField, string searchOper, string searchString)
{
// code to run stored procedure and get the relavent data from database 
// need to pass the search condition, page and rows to stored procedure
}

refer to call a stored procedure .

Now modify default.aspx to have the following :-

Create a new script file common.js with following code

$(function () {

  $("#grid_invoices_tbl").jqGrid({
        url: "InvoicingService.asmx/GetInvoiceData",
        datatype: "json",
        mtype: 'POST',
        ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
        colNames:
            ['INVOICEID',
            'CUSTOMER NAME',
            'PRODUCT NAME',
            'UNIT PRICE',
            'QUANTITY',
            'TOTAL PRICE'],
        colModel: [
        { name: 'INVOICEID', index: 'INVOICEID', align: 'left'},
  { name: 'CUSTOMERNAME', index: 'CUSTOMERNAME', align: 'left'},
  { name: 'PRODUCTNAME', index: 'PRODUCTNAME', align: 'left'},
  { name: 'UNITPRICE', index: 'UNITPRICE', align: 'left'},
  { name: 'QUANTITY', index: 'QUANTITY', align: 'left'},
  { name: 'TOTALPRICE', index: 'TOTALPRICE', align: 'left'}
  ],
        rowNum: 10,
        rowList: [5, 10, 20, 50],
        pager: '#grid_invoices_pager',
        sortname: 'INVOICEID',
        viewrecords: true,
        sortorder: "asc",
        caption: 'Invoice Details',
        serializeGridData: function (postData) {
            if (postData.searchField === undefined) postData.searchField = null;
            if (postData.searchString === undefined) postData.searchString = null;
            if (postData.searchOper === undefined) postData.searchOper = null;            
            return JSON.stringify(postData);
        },
        loadError: function (xhr, status, error) {
            alert(status);
            alert(xhr);
            alert(error);
        },
        loadComplete: function (data) {
           // alert(data);
        },
        jsonReader: {
            root: function (obj) { return obj.d.rows; },
            page: function (obj) { return obj.d.page; },
            total: function (obj) { return obj.d.total; },
            records: function (obj) { return obj.d.records; }
        },             
        autowidth: true
    }).jqGrid('navGrid', '#grid_invoices_pager', { edit: false, add: false, del: false, search: true });

});


Hope this should have helped you to handle huge amounts of data.


Computers make it easier to do a lot of things, but most of the things they make it easier to do don't need to be done.
~Andy Rooney

Improving Performance of JQGrid for millions of records : Part 1

JQGrid plugin does not require any introduction for itself. As everyone already knows the fact that JQGrid plugin is a powerful plugin for serving data from server to the client. Also it provides very good features such as sorting, paging, filtering etc.

Now lets look at how JQGrid can be used in ASP.NET for serving millions of records with out having the following effects:-

- website hanging
- memory leaks
- page time out
- taking 5 to 6 mins to serve data (only after increasing page timeout)
-
etc.

Well if you have come before you have decided on the implementation this is the right article for you.

But if you have come here after facing the issue then the changes you would have to make will be little painful but will solve your nightmares once for all.

Now enough of the explanation lets start with step by step guidelines.

This article will address more from database point of view.

Assume a simple database with 2 tables (Customer and Invoice) as follows:-

CREATE TABLE [dbo].[CUSTOMER](
   [CUSTOMERID] [bigint] IDENTITY(1,1) NOT NULL,   
   [CUSTOMERNAME] [nvarchar](255) NULL,
   [ADDRESS] [nvarchar](255) NULL
);

CREATE TABLE [dbo].[PRODUCT](
   [PRODUCTID] [bigint] IDENTITY(1,1) NOT NULL,   
   [PRODUCTNAME] [nvarchar](255) NULL,   
   [UNITPRICE] [int] NULL
);

CREATE UNIQUE NONCLUSTERED INDEX [CUSTOMER_CUSTOMERID_IDX] ON [dbo].[CUSTOMER] ([CUSTOMERID] ASC);

CREATE TABLE [dbo].[INVOICE](
   [INVOICEID] [bigint] IDENTITY(1,1) NOT NULL,      
   [CUSTOMERID] [bigint] NOT NULL,      
   [PRODUCTID] [int] NULL,
   [QUANTITY] [int] NULL
  );

CREATE UNIQUE NONCLUSTERED INDEX [INVOICE_INVOICEID_IDX] ON [dbo].[INVOICE] ([INVOICEID] ASC);
CREATE NONCLUSTERED INDEX [INVOICE_CUSTOMERID_IDX] ON [dbo].[INVOICE] ([CUSTOMERID] ASC);

Now create a view to get the data from both the tables

CREATE VIEW [dbo].[INVOICE_VIEW]  
AS  
SELECT   
 INV.[INVOICEID],  
 CUS.[CUSTOMERNAME],  
 PRD.[PRODUCTNAME],  
 PRD.[UNITPRICE],   
 INV.[QUANTITY],  
 (PRD.[UNITPRICE] * INV.[QUANTITY]) AS [TOTALPRICE]   
FROM   
 INVOICE INV,  
 CUSTOMER CUS,  
 PRODUCT PRD  
WHERE  
 INV.CUSTOMERID = CUS.CUSTOMERID AND  
 INV.PRODUCTID = PRD.PRODUCTID  

Now crucial part is to get the data from the server and the data you need to display in a page (either 10,20 etc based on the page size).

Now lets create a stored procedure to serve the data required for jqgrid.
CREATE PROCEDURE [dbo].[GETINVOICES]
 @CONDITION nvarchar(255) = NULL,
 @SORTCONDITION nvarchar(255) = NULL,
 @PAGE INT,
 @ROWS INT,
 @RECORDCOUNT INT OUTPUT
 AS 
 DECLARE
  @params nvarchar(4000),
  @sql    nvarchar(4000),
  @STARTRECORD INT,
  @ENDRECORD INT
 BEGIN

  -- SET NOCOUNT ON added to prevent extra result sets from
  -- interfering with SELECT statements.
  SET NOCOUNT ON;

  SET @RecordCount = 0;

  SET @SQL = 'SELECT @cnt = COUNT(*) FROM [INVOICE_VIEW] WHERE ' + COALESCE(@CONDITION,' 1 = 1');
  SELECT @params = N'@cnt int OUTPUT';
  EXEC sp_executesql @sql, @params, @cnt = @RecordCount OUTPUT
  
  if(@RecordCount > 0)
  begin
  
   SET @ENDRECORD = @PAGE * @ROWS;
   SET @STARTRECORD = @ENDRECORD - @ROWS + 1;      
   
   SET @SQL = 'select INVOICE_VIEW.INVOICEID,CUSTOMERNAME,PRODUCTNAME,UNITPRICE,QUANTITY,TOTALPRICE from [INVOICE_VIEW],'; 
   SET @SQL = @SQL  + '(select row_number() over (' + COALESCE(@SORTCONDITION,' order by INVOICEID asc ') + ') as rowid,INVOICEID';   
   SET @SQL = @SQL  + ' from [INVOICE_VIEW]) INVOICEROWS';
   SET @SQL = @SQL  + ' where ' + COALESCE(@CONDITION,' 1 = 1');
   SET @SQL = @SQL  + ' and (INVOICEROWS.rowid between @PARAM_STARTRECORD and @PARAM_ENDRECORD)';
   SET @SQL = @SQL  + ' and INVOICE_VIEW.INVOICEID = INVOICEROWS.INVOICEID';
   
   SELECT @params = N'@PARAM_STARTRECORD int,
       @PARAM_ENDRECORD int';

   EXEC sp_executesql @SQL,@params,@PARAM_STARTRECORD=@STARTRECORD,@PARAM_ENDRECORD=@ENDRECORD
  end;

 END;

continue to Improving Performance of JQGrid for millions of records : Part2

Database: the information you lose when your memory crashes.
~Dave Barry, Claw Your Way to the Top

Monday, 1 November 2010

Server.GetLastError() giving error as 'File does not exist.'

In general Server.GetLastError() is the more used way of getting the last generated error. But have you ever got an error message and does not exactly know what went wrong. Such as the error below:-

{"File does not exist."}

which has actually occurred in the source code at

protected void Application_Error(Object sender, EventArgs e)
{
    HttpException Error = Server.GetLastError() as HttpException;
    Session["Error"] = Error;
    Response.Redirect("Error.aspx", true);
}


The error by itself is self explanatory that says a file is missing and might be because of an .aspx, .gif, .js file missing or does not have permission to read the file.

Well finding the cause for this might look daunting when you see it. But its very simple, just follow these steps :-

1. Set a breakpoint at the Server.GetLastError()
2. Now open quickwatch
3. Type Request.CurrentExecutionFilePath

this should give the file that is missing. Also this might generally occur at places such as binding a data grids where an image is bound to a column.

The first rule of intelligent tinkering is to keep all the pieces. -Aldo Leopold

Tuesday, 26 October 2010

Invalid postback or callback argument on Post back

One of the most familiar error while working on ASP.NET ajax update panels is :-

505|error|500|Invalid postback or callback argument. Event validation is enabled using in configuration or in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.



Well its not quite easy and literally its frustrating to find out the cause. Everything is working fine in IE but not on firefox, chrome etc. So what went wrong is something very simple no one would expect.

Loading a webpage that contains number of user controls and one of which has a dropdown. The dropdown is binded to an array of strings. Now who would expect binding a string array to drop down would go wrong, no one but it does go wrong.

One of the string has a "\r" character which was messing the complete postback. Some how this is handled in IE but not on other browsers.

Any way after investing so much and finding so little to fix was a relief.

It has become appallingly obvious that our technology has exceeded our humanity.

~Albert Einstein

Tuesday, 19 October 2010

LoadViewState not firing on post back in custom control

Recently started developing a custom control with complex data handling. So far so good. Now lets try adding view state content to the custom control. Oh no! its not working. What's wrong is there a design flaw or some thing overlooked.

Have been struggling for quite a decent number of hours to fix this. After revisiting the code and looking into event life cycle for ASP.NET .

Ha ha ... yes overlooked a basic detail but have given me a severe headache. Never load any custom control in Page_Load but load them in OnPreInit.

Instead of loading

    protected void Page_Load(object sender, EventArgs e)
    {
       if (!Page.IsPostBack)
       {
       }
    }

load the controls in

    protected override void OnPreInit(EventArgs e)
    {
       if (!Page.IsPostBack)
       {
       }
    }

This very detail can be more daunting after the design had become more complicated.

To err is human, but to really foul things up requires a computer. ~Farmer's Almanac, 1978

Tuesday, 28 September 2010

Displaying jquery progressbar with ajax call on a modal dialog

Working on a website of which one of the requirement is to display a progress bar while completing an ajax call. Yes this is a simple and straight forward requirement and lets look to the details of how to implement it.

1. Create a web service

2. Using jQuery do the following :-
2.1 Show modal dialog box
2.2 show progress bar on the modal dialog box as 0% completed
2.3 Make an ajax call (estimated time of 5 mins)
3. While ajax call is processing make another ajax call to the web service to find the percentage completed and do this using set interval (or) using jquery count down plugin

Now that we have the design aspect, lets start implementing this.

At first an ajax call (ProcessRequest() - webservice method) is made and after 10 secs another ajax call ProcessStatus() - webservice method) is made to retrieve the percentage completed.

AjaxWebService.asmx
[WebMethod, ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string ProcessRequest()
{
   return AjaxData.AjaxProcess();
}

[WebMethod, ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public int ProcessStatus()
{
   return AjaxData.AjaxStatus();
}


AjaxData.cs
public class AjaxData
{
    private static int status = 0;

 public AjaxData()
 {
        status = 0;
 }

    public static string AjaxProcess()
    {
        string retValue = "Started";
        status = 0;
        for(int i=1;i<=100;i++)
        {
            System.Threading.Thread.Sleep(100);
            status++;
        }

        retValue = "Completed Successfully !";
        return retValue;
    }

    public static int AjaxStatus()
    {
        return status;
    }

}
default.aspx (script)

The complete project source code is available on Codeplex

“Physics is the universe’s operating system.” – Steven R Garman

Tuesday, 7 September 2010

Sys._ScriptLoader is null or not an object

Working on a website and have got following error :-

"Sys._ScriptLoader is null or not an object"

Have been using the methodology of downloading multiple javascript files after the visible content. When combine script is enabled the above error is displayed.

The reason for this error being the definition of the following function :-

$type = Sys._ScriptLoader = function _ScriptLoader() {

has not been loaded so need to exclude respective scriptResource.axd during combine scripts mode. Hope this might help to fix some of the issues.

“Real knowledge is to know the extent of one’s ignorance.”
– Confucius

Monday, 16 August 2010

Ajax Control Toolkit 3.5 : The script 'Timer.js' has been referenced multiple times.

Developed a website using Fast ASP.NET Web page loading by downloading multiple JavaScripts after visible content and in batch using .NET 2.0, Ajax 1.0 and Ajax Control toolkit. After migrated to .NET 3.5 getting the following error:-

"Microsoft JScript runtime error: Sys.InvalidOperationException: The script 'Timer.js' has been referenced multiple times. If referencing Microsoft AJAX scripts explicitly, set the MicrosoftAjaxMode property of the ScriptManager to Explicit."

As per the methodology used to delay loading of JavaScripts after visible content, all resource files(.axd) should be included in Filesets.xml.

Now find out where the error has occured in the script reference for eg:
ScriptResource.axd?d=PG8nyU-48dBLIokilQnXoklX6EpGEQ3aTy3vcRWmvg0DcIYhtPYFxJ8hwJRjuu3W0&t=ffffffffd40de07f

comment out the script resource in the xml. Timer control should not be included as part of combine scripts and hence the respective script resource should be commented.

Also to view any resource file that has been included in the xml just open the resource in Visual Studio (File -> Open when website is running) . for eg: if the location is

ScriptResource.axd?d=PG8nyU-48dBLIokilQnXoklX6EpGEQ3aTy3vcRWmvg0DcIYhtPYFxJ8hwJRjuu3W0&t=ffffffffd40de07f

the url for this would be

http://localhost:49405/WebSiteOne/ScriptResource.axd?d=PG8nyU-48dBLIokilQnXoiLgocTATYIx-0XXTsaGMX5FZyBIBPiYYV8fYhHJhy9o0&t=ffffffffd40de07f


Computers can figure out all kinds of problems, except the things in the world that just don't add up.
James Magary

Migrating Web application from .NET 2.0 with Ajax 1.0 to .NET 3.5

Migrating a web application developed in .NET 2.0, Ajax 1.0 and Ajax control tool kit 2005 to .NET 3.5 is quite simple following below steps :-

1. Open the solution using Visual Studio 2008 (this is migrate automatically all the projects in the solution and will update the references accordingly.

2. Remove the reference to Ajax control toolkit 2.0 and add the new reference to ajax control toolkit 3.5.

3. Since Ajax control toolkit is being used in your solution update tag to .

4. To improve performance load all .js file using a single user control and assign attribute CombineScripts attribute of scripmanager to "True". Reference CombineScripts.

5. Build the solution and web application should work absolutely fine.

To err is human, but to really foul things up requires a computer.

-Farmers' Almanac, 1978

Friday, 2 July 2010

Type Sys.UI._Timer has already been registered

Having a webpage with multiple update panels and multiple timers might be bit annoying when you the below error:-
Sys.InvalidOperationException: Type Sys.UI._Timer has already been registered

If scripts are loaded using an user control update attributes for asp:ScriptManager as follows
  


















Hope this have helped someone like me hanging around.

"It’s hardware that makes a machine fast. It’s software that makes a fast machine slow."
- Craig Bruce

Thursday, 1 July 2010

Displaying elapsed time with multiple asp:timer's on a page

In cases where a web page consists of multiple asp:updatepanel and multiple asp:timer controls. Each update panel getting refreshed at specific timer intervals (different timings), instead of display stale data before the refresh its good to display the user with elapsed time for an update panel. This gives users feel of live data and user knows exactly when an update panel will be refreshed.

Sample display of how the page looks



Here is the code below :-
TimerWidget





























code-behind

contd...

Monday, 28 June 2010

Issue with user control getting loaded with asp:timer

I have been working on a web application which requires loading a user control using asp:timer control. Application is completely based on widgets.

The default page has number of widgets that are loaded dynamically at runtime and all widgets has the facility to enable or disable timer.

All events were working fine except "User Widget" not firing any events. Here is how the code is :-

WidgetTimer.ascx















UserControl.ascx


<%@ Control Language="C#" AutoEventWireup="true" CodeFile="DataListMgrReal.ascx.cs" Inherits="DataListMgrReal"%>










Select Repository






PageSize="25"
AutoGenerateColumns="false"
GridLines="None"
CssClass="gridViewData"
Height="159px">











I have been struggling to find the issue. Then i have tried creating a new web app and have tried with just the above snippet and that works fine.

After some modifications the btnUpdate_Click stated working but only works for the second click.

i have come accross the following articles...

http://forums.asp.net/t/1079709.aspx


http://bytes.com/topic/net/answers/730873-ajax-updatepanel-dynamic-controls-registerstartupscript-click-twice

Application was so complicated so the only detail that has skipped out of my mind is "UserControl" ID property.

I am not assigning ID property manually which has been causing the issue all the time. I have finally fixed the issue now its a relief......

Hope this might be helpful for someone like me with this odd combination.

Never overlook a minute detail !!!
Copyright © 2013 Template Doctor . Designed by Malith Madushanka - Cool Blogger Tutorials | Code by CBT | Images by by HQ Wallpapers