How to set focus on text box and set cursor position when page loads

by Naveen 2. September 2010 05:34

While implementing a high performance search functionality for a site, I ran into some interesting issues with some UI aspects. So I thought I would share it with everybody so you have answers to some of the following questions when you run into similar issues.

  • How to set focus in text box when page load

    This is a very common requirement that when you are implementing a search box for your site, you want the users to be able to start typing in search keywords when the page load. Well it is pretty simple by using a small javascript on the page. Since Microsoft shipd jQuery with Visual Studio now and jQuery provides very concise implementation of some very common tasks, so I used jQuery to accomplish the task. Following snippet shows how to use jQuery to set focus on text box.

     $(document).ready(function () {
     	var keywordTextBox = $get("<%=keywordTextBox.ClientID%>");
     	keywordTextBox.focus();
     }
    

    Yes, I could have done whole thing in one line instead of storing the element in local variable first. But I needed this element for some other user as well. Soon you will see why. The code simple translates to when document has been loaded and DOM is ready get text box html element and call focus method to set focus on it.

  • How to set cursor position at end of text in text box

    Now that you have seen how to set focus on text box, next thing you will run into is that when page post backs when you have text in search text box, the focus is set on the text box but it is set at the start of the text. What you are really looking for is that when you have some text in text box, the focus should be set at the end of the text so user can either continue with what is already there or start deleting for a new search term. The following snippet shows how you can use setSelectionRange or createTextRange depending on browser, javascript method on text box to set the cursor at the end of the text in text box. Or for that matter you can use this technique to set cursor in text box at any position.

    $(document).ready(function () {
    try {
      var keywordTextBox = $get("<%=keywordTextBox.ClientID%>");
      if (null != keywordTextBox) {
          var pos = keywordTextBox.value.length;
          if (keywordTextBox.setSelectionRange) {
             keywordTextBox.setSelectionRange(pos, pos);
          }
          else if (keywordTextBox.createTextRange) {
            var textRange = keywordTextBox.createTextRange();
            textRange.collapse(true);
            textRange.moveEnd("character", pos);
            textRange.moveStart("character", pos);
            textRange.select();
          }
          keywordTextBox.focus();
       }
    });
    
  • How to handle enter key click in text box to submit page

    Now that we have set focus in text box. Now your user should be able to enter some text in the text box and hit ENTER key to perform search. Following code snippet shows how you can hook key events of your text box to look for ENTER key press and then submit the page.

    $(document).ready(function () {
    try {
      var keywordTextBox = $get("<%=keywordTextBox.ClientID%>");
      if (null != keywordTextBox) {
          var pos = keywordTextBox.value.length;
          if (keywordTextBox.setSelectionRange) {
             keywordTextBox.setSelectionRange(pos, pos);
          }
          else if (keywordTextBox.createTextRange) {
            var textRange = keywordTextBox.createTextRange();
            textRange.collapse(true);
            textRange.moveEnd("character", pos);
            textRange.moveStart("character", pos);
            textRange.select();
          }
          keywordTextBox.focus();
           $("input").keydown(function (e) {
           if (e.keyCode == 13) {
             __doPostBack("<%=searchButton.UniqueID%>", "");
            return false;
           }
          });
       }
    });
    

    The above code javascript snippet demonstrates all three features of handling various text box features together. You can see all this in real action at the following page. Start typing some search term and see how autocomplete start providing hints and then when you hit ENTER key, page posts back and returns with search results and then text box focus is set at the end of text in text box.

Live Demo Of Text Box Features

 

Give your advice to big bosses and make money

Views: 168

Tags: ,

ASP.Net | Javascript | JQuery

Ajax AutoComplete Control Not Working

by Naveen 25. August 2010 17:19

While implementing integrating ASP.Net Ajax AutoComplete control on a site's search text box, I ran into an issue. While I was typing inside the text box, no request was getting sent to my web service to get the list of previously used search terms with a given prefix that user was typing. I checked the mark up for AutoCompleteExtender on the page and all the required properties etc. There was nothing out of place. Obviously request was not making it to my web service method. That's when I called on handy dandy Fiddler. And there it was the following response from the web service request with Http Status code of 500.

Only Web services with a [ScriptService] attribute on the class definition can be called from script

Thats when I realized that I forgot to enable this attribute on my ASP.Net web service. So remember that if you are using an ASP.Net web service with Ajax toolkit controls, you have to enable ScriptService on your service.

Give your advice to big bosses and make money

Views: 256

Tags: ,

AJAX | ASP.Net

How to insert new row in GridView?

by Naveen 23. August 2010 13:40

Its been a while since I did some custom work on controls like GridView, DataGrid etc. Last week I was working on a prototype of some application that required me to add some records into the database. So I decided to give GridView control in ASP.Net a try. I needed a very simple UI so I decided to use as much built in functionality of this control. Since I needed to add a new record, so I needed a way to be able to add a new row into GridView. So I looked at the CommandField column. One of the properties it has is ShowInsertButton . So I added this property and set it to true. So now my mark up on ASP.Net on the page looked as shown below.

<Columns>
 <asp:CommandField ShowEditButton="True" 
    ShowDeleteButton="true" 
    ShowInsertButton="true"></asp:CommandField>
 .... othe bound columns.
</Columns>

I ran the application and my grid shows up and has all three data manipulation links visible. So I clicked on New link button. Well, I did not see an empty row appear where I was going to add new data for new row in database. I checked, everything looked in order. I have event handler correctly mapped and code looked fine. After trying few things around, I searched on internet. I could not find any useful information on why my event is not firing or why new row is not getting added. All the posts and articles that I ran into talked about adding a new button in the grid to accomplish taks of added new records. Well that sounded a little odd that why would I need to add my own button when there is already a command link buttoon available. Thats when I decided to read the documentation on this property ShowInsertButton. Here is something in documentation that stood out.

This property applies only to data-bound controls that support insert operations, such as the DetailsView control.

When you look at various events in GridView control, you will not find any related to Insert. Now that explained why I am not getting new row added to my grid.

Adding new row to GridView

So here is quick solution that I came up with for my prototype. When you click on New link button in GridView, it does fire RowCommand event. Here you can check for CommandName value of New. In this event handler, I added a new empty record into the data source to which my GridView was bound, set the EditIndex of the grid to first record and bind the grid again. Now I have an empty row in Edit mode open for me to add some data.

if (e.CommandName == "New")
{
 ViewState["_inserting_"] = 1;
 var glossaryTerm = new Services.GlossaryTerm();
 _terms.Insert(0, glossaryTerm);
 GlossaryGrid.EditIndex = 0;
 BindGrid();
}

You can see that I added a flag in ViewState that grid is in Insert mode. The reason for this is that since GridView does not support Insert directly, when you will click on Update link button, you are going to get RowUpdated event handed to you. So you will need some way of knowing that this record is actually to be added and not edit some existing one. The way I did is not one of the best and elegant way. But you get the idea. One nice of doing is to have an hidden field where some unique ID of each record is stored. And you can keep this field hidden. Since I did not have any unique ID in my data source, I had to do it differently. But most grids are bound to some data source with some unique ID. So when you add a new empty record for adding, you can set its Unique ID value to some token valur like -1. When you handle RowUpdated event, then you can look for this unique ID value and perform the database accordingly.

This trick should allow you to use built in command buttons to add new row in GridView.

Give your advice to big bosses and make money

Views: 501

Tags:

ASP.Net | GridView

How to configure SMTP server for CreateUserWizard send email functionality

by Naveen 19. August 2010 11:21

As part of using Membership controls in ASP.Net, one thing lot of people do as part of user creation is send some sort of email to the new user when they register. This email could be some welcome email or email that send the user their password etc. Good news is that CreateUserWizard control takes care of most of the email functionality for you. Here is what you need to make it all work.

How does it work?

CreateUserWizard control sends an email to the newly registered when the new user has been created. SendEmail event is fired after CreatedUser event has been successfully fired and handled. Interestingly, CreateUserWizard sends this email using method SendPasswordMail. It seems this email feature was designed for sending passwords to user when password is automatically generated. But this does not mean that it is only going to be called when certain password option is chosen.

MailDefinition is the key

CreateUserWizard control does not try to send email all the time. It looks for MainDefinition template to be set in the control. If you do not definie MailDefinition template, control will not send the email. So what you need to do is fill this template inside your control container. Here is sample implementation from my sample code.

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <asp:CreateUserWizard ID="RegisterUser" 
    runat="server" EnableViewState="false" 
    OnCreatedUser="RegisterUser_CreatedUser" 
    OnCreatingUser="RegisterUser_CreatingUser"
    BorderStyle="Dotted" 
    OnSendingMail="RegisterUser_SendingEmail" 
    OnSendMailError="RegisterUser_SendingEmailError">
       <LayoutTemplate>
         <asp:PlaceHolder ID="wizardStepPlaceholder" runat="server"></asp:PlaceHolder>
         <asp:PlaceHolder ID="navigationPlaceholder" runat="server"></asp:PlaceHolder>
        </LayoutTemplate>
        <MailDefinition 
         From="xyz@mymail.com" 
         IsBodyHtml="true" 
         Priority="Low" 
         BodyFileName="~/WelcomeEmail.htm"
         Subject="Welcome to Project Helpers from ByteBlocks.com">
         <EmbeddedObjects>
            <asp:EmbeddedMailObject Name="LogoImage" Path="~/Images/ByteBlocksLogo.png" />
         </EmbeddedObjects>
        </MailDefinition>
</asp:CreateUserWizard>

As you can see, MailDefinition template allows you to configure email parameters. You do not have to hard code some string as body of your email. It will actually become problem when you have long HTML content to be sent in email body. You can put content of your email in external file and then set the path to that file in BodyFileName attribute of MainDefinition. You can put some token or markers inside that body to replace them with appropriate values at run time. More about it little later. So remember that MailDefinition is key to sending email as part of CreateUserWizard control.

Customize email content and attachment

Some time you want to send welcome email to new users with some documents and also want to have some logo image inside the email body. Well, this all can be handled by using a standard format that the control provided. You will make use of EmbeddedObjects section of MailDefinition template. This is where you can include all the external objects or file paths. Make sure that you have unique names for these objects.

  • To include images inside email body, use the following syntax in HTML email body content.

    	<img src="cid:LogoImage" alt="ByteBlocks Project Helpers" />
    	<h2>Welcome To ByteBlocks Project Helper</h2>
    	

    This is part of HTML file that I use for email body. The key to this is src=cid:uniqueid part. This uniqueid is the name of the object that you added in EmbeddedObjects section. You can see from the markup that I showed earlier that I have included my logo image inside EmbeddedObjects section.

  • If you need to attach some documents, then include them in EmbeddedObjects section.

Following screenshot shows sample of email that get sent from my application. You can see that at the top of the email is sample logo image as well.

Configure SMTP Server for CreateUserWizard Email

This is one of the most asked question to me. Where do I set SMTP server settings for emails from CreateUserWizard?. When SendEmail event is fired, you get MailMessageEventArgs object as parameter of event handler. This object only provides you access to email message only. It does not provide a way to configure SMTP settings for outgoing email. Then how do you set it?

See the following call stack when CreateUserWizard control is trying to send the email out.

System.Net.Mail.SmtpClient.Send(MailMessage message)
   System.Web.UI.WebControls.LoginUtil.SendPasswordMail(String email, String userName, 
        String password, MailDefinition

Now if you look at constructor of SmtpClient, it initializes the settings of email transport from mailSettings section of web.config. That means the place to configure your SMTP server is in web.config file. Add mailSettings section in system.net section of web.config value. Following snippet shows you an example from my site.

<system.net>
    <mailSettings>
      <smtp deliveryMethod="Network" from="xyz@myisp.com">
        <network host="localhost" />
      </smtp>
    </mailSettings>
  </system.net>

You can provide the values as per your server settings. If you are just testing using your local machine as email relay then you do not have to specify these settings. SmtpClient by default will use local machine.

Important things

There are few things that you will need to pay attention to when setting up this MailDefinition template and changing settings for MailMessage.

  • Make sure that you have specified an email address in From section. This does not have to be a valid emails address. You can simply put something like noreply@mydomain.com. But do not leave it empty.
  • If your process does not require the users to provide their email address but you still want to send some email for record keeping then you can add a placeholder email to To collection. You can not leave To collection empty. Otherwise SmtpClient object will throw exception at you.

    protected void RegisterUser_SendingEmail(object sender, MailMessageEventArgs e)
    {
       var sendTo = RegisterUser.Email;
       if (string.IsNullOrEmpty(sendTo))
       {
          sendTo = "foo@bar.com";
          e.Message.To.Add(sendTo);
        }
    }
    
  • Do provide an event handler for SendEmailError. If there is some error or exception thrown during outoging email process, you can look at the error message. Handle this error gracefully and then set Handled properly.

    protected void RegisterUser_SendingEmailError(object sender, SendMailErrorEventArgs e)
    {
     System.Diagnostics.Trace.WriteLine(e.Exception.Message);
     e.Handled = true;
    }
    

    If you do not handle this error, then it will get propagated to the top as unhandled exception and depending on your CustomError settings, users may see ugly yellow screen with full stack trace and all.

Give your advice to big bosses and make money

Views: 406

Tags:

ASP.Net

How to use reCaptcha with CreateUserWizard In ASP.Net

by Naveen 18. August 2010 10:50

I was working on using CreateUserWizard ASP.Net control on my web site to allow users to create their account for authorized and authenticated access to certain access of sites. One of the problems you face on the web sites is that spammers tend to run bots to create accounts on sites using direct HTTP requests and things like that. One of the ways to fight this is the use of some CAPTCHA control on the pages. Yes, there are some hackers who claim to bypass some of these counter measures. But still it protects you from about 80% or so of these spam bots.

So one of things you can do is to add ASP.Net plugin for reCaptcha control in template for CreateUserWizard control. There are few issues that I ran into when I tried to integrate into my page. So here are some of the things you can learn from my experience to integrate reCaptch in ASP.Net.

  • There seems to be a validation bug in older version of reCaptcha control plugin. So I had to download the latest source code from google SVN and recompile it to use in my ASP.Net web site. The problem I was running into with bugged plugin was that Postback was not getting fired. After I will click on Create button, the page will just not fire event handler to postback the page. Once I replaced it with recompiled version of reCaptch control, the page worked fine.

  • In the post back event handler, add the following code to validate reCaptcha challenge. This will provide you server side validation of the control. I added following code to my event handler.

    protected void RegisterUser_CreatingUser(object sender, LoginCancelEventArgs e)
    {
      var captcha = 
       (Recaptcha.RecaptchaControl)RegisterUser.CreateUserStep.ContentTemplateContainer.FindControl("recaptchaCtl");
      if (null == captcha)
      {
        e.Cancel = true;
        return;
      }
      captcha.Validate();
      if (!captcha.IsValid)
      {
        //TODO: Display validation message.
        e.Cancel = true;
        return;
      }
      e.Cancel = false;
    }
    
Give your advice to big bosses and make money

Views: 391

Tags:

ASP.Net

How to add rounded corner div on web page using Ajax Toolkit

by Naveen 13. August 2010 13:35

Adding a panel on a web page with rounded corners is something very common that we all do at some point in web application development. We all have been thought standard solution of using a collection of images to arrange them in a manner that they form a rectangle with rounded corners. If you are developing ASP.Net web site then, Ajax Toolkit makes this task every easy for you. By adding one additional control tag you end up adding a rounded corner panel around an existing panel. Let's see how this done.

  • I am going to skip the discussion on download of Ajax toolkip, installation and all that good stuff. I am going to assume that you have already done it.
  • Add reference to AjaxControlToolkit.dll assembly to your ASP.Net project if you do not already have it added.
  • At the top of the page add tag for registering TagPrefix for the controls in this Ajax assembly.
    <%@ Register Assembly="AjaxControlToolkit" 
     Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>
    
  • Make sure that you add ScriptManager server control tag on the page as well. Otherwise you will end up with the following run time error.
    The control with ID 'intoPanelRoundedCornersExtender' requires a ScriptManager on the page. The ScriptManager must appear before any controls that need it.
    In my case I just added in the master page of the site.
    <asp:ScriptManager ID="masterScriptManager" runat="server" />
    
  • Now add RoundedCornersExtender control on the page. The most important property to set is TargetControlID. This ID of the control around which rounded corner panel is going to be added. Without it, the control will not work.
    <ajaxToolkit:RoundedCornersExtender ID="intoPanelRoundedCornersExtender" runat="server"
     BehaviorID="RoundedCornersBehavior1"
     TargetControlID="siteIntroPanel"
     Radius="6"
     BorderColor="#111"
     Color="#696969"
     Corners="All" />
    
    Other property that can be set to control behavior of rounded corner panel are Color,BorderColor, Radious and Corners. The names of these properties pretty much tell what these are supposed to control.

See how easy it is to add these rounded corners. You can see the demo on this live site. The top two panel are created using this RoundedCornerExtender control from Ajax toolkit.

Give your advice to big bosses and make money

Views: 386

Tags:

AJAX | ASP.Net

Avoid Multiple Form Tags To Add Google Search To ASP.Net Page

by Naveen 13. August 2010 09:12

Last week I was updating the site to include some new features. I realized that I was missing a very important component on the blog and that was google search box. I had this search on my other sites for quite some time. I remember that I had to deal with the fact that Google Custom Search script is implemented as a POST FORM with the action set to a URL that will be used to display results.

First you have to deal with the fact that ASP.Net framework does not allow you to have multiple FORM tags on the page. But if you want have more than one then only one can have runat='server' attribute on it. And then you have to make sure that your FORM tags are not nested. Well, depending on your layout of the site and implementation, you may or may not be able to control location of this google search form. Here is the solution that I implemented few years ago and deployed on this site as well.

Use of iform

Yes, took the Google Custom Search script and put it in a static HTML page. And then put an IFRAME on the page where I wanted to display the search box. This is where you will have to be little careful. You will have to make sure that style of the HTML page matches your main site. Next make sure that height and width of iframe is big enough to accomodate the search box otherwise you will end up with horizontal and vertical scroll bars around the frame and that will not be a pretty sign for site users. You want to give the illusion to users that this search box is sitting on the page itself. Now perform search and it works. But there is a problem. Search result target URL is being opened in the frame where search box is. Well that is a little problem.

Fix target of FORM

This is where you will have to make a change in the script that Google Custom Search generated for you. In FORM tag, set target to _top. Now when this form is submitted, the action is sent to page contained this iframe. The following snippet is what I have in my HTML page.

<div class="cse-branding-bottom" style="background-color:#FFFFFF;color:#000000">
  <div class="cse-branding-form">
    <form action="http://localhost/ByteBlocksWeb/SearchResults.aspx" 
      id="cse-search-box" 
      target="_top">
      <div>
        <input type="hidden" name="cx" value="partner-pub-xxxxxxxxxxxxx:wcbg5i-ahdn" />
        <input type="hidden" name="cof" value="FORID:11" />
        <input type="hidden" name="ie" value="ISO-8859-1" />
        <input type="text" name="q" size="60" />
        <input type="submit" name="sa" value="Search" />
      </div>
    </form>
  </div>
  <div class="cse-branding-logo">
    <img src="http://www.google.com/images/poweredby_transparent/poweredby_FFFFFF.gif" alt="Google" />
  </div>
  <div class="cse-branding-text">
    Custom Search
  </div>
</div>

Now perform a search and you will notice that your results show up in main page and not in iframe anymore. Give it a try right here in this site by using search at top of the page and see how it works.

Give your advice to big bosses and make money

Views: 502

Tags:

ASP.Net | Google

How to use Linq with ASP.Net GridView

by Naveen 12. August 2010 10:08

Linq is one of the best things that has happened in recent past in .Net framework world. It has made data manipulation so much easy. Yes, Linq has its own set of limitations but for most part it does the job. For those special cases you can always go back to classic ways. In this post, I will describe use of Linq for Sql and provide some simple answers to questions like:

  • How to connect to database using Linq?
  • How to query data from a table using Linq?
  • How to use Linq with GridView, DataGrid etc.?

Namespace and reference to use Linq with Sql

The classes that you need to use Linq with Sql live in System.Data.Linq namespace. So in your project you will have to add the following line at top of your source code file.

using System.Data.Linq;

This namespace lives in System.Data.Linq assembly. That means that you will have to add reference to this assembly in your project. Now you are all set to us Linq.

How to connect to the databae?

You have been using ADO.Net for a while now and first thing we all do is have a connection object that will be used to connect to database, open it and later on close it. Well when you are using, all that plumbing is taken care of for you by Linq frameework. The entry point to all actions in Linq for Sql is DataContext object. This object takes care of establishing connection with the database. You can provider either a connection string or connection object to create instance of DataConext object. Rest will get taken care of for you.

var dataContext = 
new DataContext(ConfigurationManager.ConnectionStrings["blogengine"].ConnectionString);

Query data using Linq

Now you have set up DataContext object, it is time to get some data from the database. You will notice that DataContext object provides methods like GetTable, ExecuteQuery, ExecuteCommand etc. All the methods that return collection of data, expect another parameter which is Type of an object that represent the data returned from query or command. In otherwords, the method is looking for a mapping between table in the database to an object. Here is an object definition that I used in my code to map to fields from a datatable that I wanted to fetch.

[Table(Name="be_Posts")]
public class BlogPost
{
  [Column(IsPrimaryKey=true)]
  public Guid PostID
  {get;set;}

  [Column]
  public string Title
  {get;set;}

  [Column]
  public string MiniUrl
  {get;set;}
}

There are few attributes on this class that are to be notices. First, there is TableAttribute on the class itself. By default Linq assumes that name of the class or object is same as table in the database. But if your table name does not match with the class name, then you can use this attribute to provide the name of the table that maps witht this obejct. For example in my case table name be_Posts is to be mapped to BlogPosts object which is my ViewModel. Next attribute is ColumnAttribute. You will assign this attribute to properties or fields that needs to be queried. If your column name does match with name of the property or field, you can provide that mapping as well. There are more values you can set in the column attribute. I will discuss those in subsequent posts. For now this simple definition of .Net object will work for our simple query purposes.

Bind Linq To GridView

Now we have our Linq query set to go, rest is just setting this collection to our GridView object on ASP.Net page and rest is all taken care of for us. Following code snippet shows how in few lines we are able to connect to database, query the data and bind it to a GridView.

void BindGrid()
{
 var dataContext = 
  new DataContext(ConfigurationManager.ConnectionStrings["blogengine"].ConnectionString);
 var posts = dataContext.GetTable<BlogPost>();
 postsGridView.DataSource = posts;
 postsGridView.DataBind();
}

It is as simple as these 4 lines of code to connect to database, query the table and bind to a gridview using Linq to Sql.

Give your advice to big bosses and make money

Views: 619

Tags: , ,

ASP.Net | GridView | LINQ

How to embed YouTube video in ASP.Net page - Server Control

by Naveen 3. June 2010 04:37

Download Source Code (9.09 kb)

Download Binaries (6.28 kb)

Recently I started created some YouTube videos and wanted to embed them in my ASP.Net web site. YouTube provides Embed button next to each video and that helps you create HTML code that you can put on your page. But that would mean that you will have to hard code this HTML on all pages where you want to embed videos. Also if you want to show some random videos on the pages, then this approach is not flexible.

I created this ASP.Net server control that allows to embed YouTube videos on any page. The control allows you to embed videos for which you already have URL or you can configure it to fetch any of the standard YouTube feeds and then display random video from that feed.

How to use it?

  • Download source code of the control and compile it or download pre-compiled binaries of the control.
  • Add reference to ByteBlocks.YouTubeWeb assembly in your project.
  • On the page where you want to embed YouTube video, add the following directive at the top of the page.

    <%@ Register TagPrefix="ByteBlocks" Assembly="ByteBlocks.YouTubeWeb" Namespace="ByteBlocks.Web.Control" %>

  • Now add the control on the page.

    <ByteBlocks:YouTube id="youTubeVideo" runat="server" Width="480" Height="385" VideoUrl="" FeedType="MostRecent" RandomResults="true" />

  • And you are all set to show random video from Most Recent video feed from YouTube.

Configurable Properties

  • VideoUrl: This property allows you to set URL of the video that needs to be embeded.
  • Width: Sets the width of the video player
  • Height: Set the height of the videeo player
  • FeedType: If you do not want to use a pre-defined video URL, you can pick a standard feed type. The control will fetch that feed from YouTube and display it based on value set for RandomResults and IndexToShow. This property is mututally exlcusive with VideoUrl. If you want the control to fetch standard feed, then do not set any URL in VideoUrl.
  • RandomResults: This property indicates to control to pick a random Video Url from the list of videos from standard feed type.
  • IndexToShow: If you set RandomResults to false, then the control will fetch the video at this index value. If this index is out of range, then the control picks the last entry in the feed list.

See it in Action

The following web site uses this control to show videos from most featured standard feed.

YouTube Server Control Demo

Under the covers

When you generate HTML code for a video from YouTube, it looks something like as shown below.


<object width="480" height="385">
<param name="movie" value="http://www.youtube.com/v/XcugLsKDmRs&hl=en_US&fs=1&rel=0"></param>
<param name="allowFullScreen" value="true"></param>
<param name="allowscriptaccess" value="always"></param>
<embed src="http://www.youtube.com/v/XcugLsKDmRs&hl=en_US&fs=1&rel=0" 
  type="application/x-shockwave-flash" allowscriptaccess="always" 
  allowfullscreen="true" width="480" height="385"></embed>
</object>

So the control simply renders this HTML on ASP.Net page and uses the control properties to configure the display accordingly. The important components of this HTML is video ID used with the video player. I have shown that in bold in snipper above. A video URL looks like as shown below.

http://www.youtube.com/watch?v=Qp9_6ACSWug

Video ID is provided in v query string parameter. The control parses this ID and replaces it in the URL that is required for URL for video player.

Source Code and Binaries

Attached code is compiled using Visual Studio 2010 and .Net 4.0 framework. If you need code for earlier versions of Visual Studio, feel free to conttact me.

Give your advice to big bosses and make money

Views: 919

Tags: ,

.Net | ASP.Net

Server Error - Upgrading Existing ASP.Net 2.0 Web site to ASP.Net 4.0

by Naveen 24. May 2010 10:09

Recently I was working on upgrading this site to from ASP.Net 2.0 to ASP.Net 4.0. As a first quick pass, I followed my usual procedure of loading the projects into Visual Studio 2010 and set the target for all projects to use .Net 4.0 framework. So far so good. I tested it on my development machine which is Windows 7 and everything worked as I expected.

So I went ahead with deployment on my production Windows server. I changed the target ASP.Net framrwork of my web site to ASP.Net 4.0 from ASP.Net 2.0. And site loaded and started serving requests. After few hours I got an email from another site owner who is hosting site on my server that all sites have stopped working and we were getting Server Error or Application Error. I have about dozen sites hosted on the server and all but one stopped working. Only one that was working was this site that I just upgraded to use ASP.Net 4.0. Right there I realized the mistake I made. This is the samee mistake that was made when sites were upgraded from ASP.Net 1.1 to ASP.Net 2.0.

Mixed ASP.Net versions in Application Pool

Yes, now I had one site in the application pool that was using ASP.Net 4.0 and others were using ASP.Net 2.0. Application pools do not allow mixed version of .Net framework. Here are some things that you will have to take into consideration when migrating your existing ASP.Net sites from 2.0 t0 4.0 or when adding new sites on Windows 2003 server.

  • Make sure that you do not mix use of ASP.Net version in same pool
  • Best option is to make a new Application Pool and put your new or migrated ASP.Net 4.0 sites in there.
  • If you have already made a mistake (like I did) of mixing ASP.Net versions on application pool, then there are few options you can use:
    • Move the sites using ASP.Net 4.0 framework to a new pool or move ASP.Net 2.0 sites into new pool depending on whatever is less work.
    • I have run into cases where moving ASP.Net 4.0 out of pool did not work. If upgrading all sites to ASP.Net4.0 framework is not going to break anything, then you may have to consider that option.
    • When you start upgrading existing sites to use new pool or upgrade to new ASP.Net 4.0 you may run into problem that all sites start showing Service Unavailable error. This has been happening a lot on Windows 2003 server. During process of upgrading and pool switching, some time IIS stops working. You will notice a red cross mark on Web Sites node in IIS. You will have to goto Service Control Manager to restart worldwide web publishing service on your server

I hope this little piece of information helps you get out of problem of upgrading existing site to ASP.Net 4.0 when there are other sites in same pool that use older version of ASP.Net.

Give your advice to big bosses and make money

Views: 674

Tags: ,

ASP.Net | IIS

How to deploy another web application under DNN as virtual directory

by Naveen 31. March 2010 05:37

Here is the scenario that this post is about. You have an existing DotNetNuke (DNN). Now you have to configure a new ASP.Net web application under this site as virtual directory. So you follow the standard procedure of creating a new virtual directory under your parent DNN site and point it to the location where the new web application's files are. Try to access this site and you will run into the following error.


Server Error in '/DNN53/ProductsSearch' Application.
--------------------------------------------------------------------------------

Configuration Error 
Description: An error occurred during the processing of a configuration 
file required to service this request. Please review the specific error details
below and modify your configuration file appropriately. 

Parser Error Message: The code subdirectory '/DNN53/ProductsSearch/App_Code/IFrame/' 
does not exist.

Source Error: 

Line 168:      -->
Line 169:      <codeSubDirectories>
Line 170:        <add directoryName="IFrame" />
Line 171:        <add directoryName="Survey" />
Line 172:        <add directoryName="XML" />

Source File: C:\Projects\DNN\DNN_V531\Install\web.config    Line: 170

Now you are wondering what does these folders and files have to do anything with your web application that is hosted under DNN site. The thing that you need to understand is that when you are hosting a child application under parent ASP.Net application, it inherits web.config settings from all the parents as well. So in this case your application is inheriting DNN related settings as well. I have some one suggesting to add these missing folders in your new application as well. Next thing you will run into is that your site is complaining about missing DNN related assemblies.

The solution to this problem is not copy DNN assemblies or mimic the folder structure in your application as well. Because now you have added a very strong dependency on parent application. There is a very simple and elegant solution to this problem.

  • Open Web.config file of your parent DNN site.
  • Look for system.web entry in the file.
  • Enclose that whole section in location tag and set the attributes of that tag as below.
    
    <location path="" inheritInChildApplications="false">
     <system.web>
    ..
    ..
     </system.web>
    </location>
    
    
  • By setting inheritInChildApplications to false you indicate to ASP.Net pipe line that any settings for the specified path and for the section are not to be propagated to the child application.

You can use this technique to restrict propagation on page by page or by folders etc.

Give your advice to big bosses and make money

Views: 1345

Tags: ,

ASP.Net | DotNetNuke

ASP.Net controls not firing postback event

by Naveen 26. March 2010 06:19

When you add an ASP.Net control like button, linkbutton, combobox etc. you expect that when you will click on this control, the page will cause a post back and you will be handling server side event handler for click on that control. Sometime you run into an issue when postback event does not fired. The clicking on control does not do anything. You get the feeling that no event is getting fired. There are only couple of reasons that can cause postback to not fire.

The least like cause can be that there is some client side javascript code that is cancelling event bubbling for your click event to respond. This is something that is highly unlikely because if you have some very custom implementation like this, then you are probably aware of it.

Most likely cause is that you have a control validator on the page and validation conditions are not satisfied when you are clicking on that control. And this problem becomes more cryptic when you forgot to add any visual indicator or error that tells you about validation condition violation. Here is another obvious cause of this problem. If you have a tab control on the page and one or more of the tabs have validation control(s). And then you are on tab that does not validation control. So you try to click on some control that has to cause PostBack. Now the problem is that although you are on different tab, but validators from other tabs are still part of the page. So before postback occurs, page is going to try to validate those validators. And if for some reason any of those validators fail, then postback action is cancelled.

So if you are running into this postback issue because of validators on tabs, then you need to handle tab switching event and then enable or disable those validators depending on your application rules etc.

Give your advice to big bosses and make money

Views: 2761

Tags:

ASP.Net

How to programatically set meta tags on ASP.Net page

by Viper 5. November 2009 06:19

When we are creating a web site, one of the main goal we all have is that out site should be listed on first page of search engines like Google, Bing, Yahoo, Baidu etc. As we all know that in SEO world, one of the first thing we all look for in the page is meta tags in header of the page. In the past there was no direct way to set the meta tags on a page programatically when developing ASP.Net web site. We all used the work around of adding metaelements in header element of the page. You can read my previous post Adding meta tags to asp.net page dynamically about that technique. With ASP.Net 4.0 microsoft has introduced following two properties on that allow you to set the meta tags on a page.

  • MetaDescription
  • MetaKeywords

Following code snippet shows how it is used in your code.


public partial class _Default : System.Web.UI.Page
{
 protected void Page_Load(object sender, EventArgs e)
 {
  SetMetaTags();
 }
 private void SetMetaTags()
 {
  Title = "Hello Meta";
  MetaDescription = "This is description of my ASP.Net 4.0 page.";
  MetaKeywords = "ASP.Net,.Net4.0,Meta";
 }
}

And it works. You can see from the source of the page as shown below.

<head>
<title>Hello Meta</title>
<meta name="description" content="This is description of my ASP.Net 4.0 page." />
<meta name="keywords" content="ASP.Net,.Net4.0,Meta" />
</head>
Give your advice to big bosses and make money

Views: 1200

Tags:

.Net | ASP.Net

How to implement OWA style new message notifier poup using Silverlight and javascript

by Viper 6. October 2009 14:06
OWA style new message notification popup

Download Demo Projects

This is one of the projects I have been planning to work on for some time. I was looking into building an event notifier in one of my ASP.Net application. I wanted it to be more like Outlook Web Access (OWA) new email notifier pop-up. It is the one that slides up from bottom right corner of your browser when there is a new email in your inbox. I had built it in the past using all javascript solution. Yes, this Microsoft is one of the earliest implementation of so called AJAX applications. I did not want to deal with all the javascript code related to setting up HTTP calls and then dealing with response and rendering the results.

I wanted to leverage Silverlight to do all the heavy lifting. And use light weight javascript implementation on client to do animated sliding and positioning of the popup notifier box. At the end it turned out be quite an elegant solution that worked on major browsers like Internet Explorer, FireFox and Chrome. This article is an attempt to describe How to implement OWA style new email notifier popup using Silverlight and Javascript.

The implementation involved the following technologies and I will describe how each component was implemented

  • ASP.Net web application
  • ASP.Net web service
  • Silverlight application

ASP.Net Web Service

Let's start with discussion of the component that is responsible for communication of data between client and server application. The client requests data from server at certain frequency to check if there are any new messages. So I implemented as simple ASP.Net web service application with few web methods. For this demo I had a simple method with following signature.


[WebMethod]
public string GetGlobalMessages()
{
 List msgs = MockData.GetGlobalMessages();
 return msgs.ToJson();
}

For demo application, I implemented a MockData class that creates a random list of messages and then serializes that collection as JSON and sends it in response. I implemented ToJson as an extension method on List<StatusMessage> object. You will find it in Extension.cs file in ActivityData project.


public static string ToJson(this List<StatusMessage> msgs)
{
 var ser = new DataContractJsonSerializer(msgs.GetType());
 var ms = new MemoryStream();
 ser.WriteObject(ms, msgs);
 var serializedData = System.Text.UTF8Encoding.UTF8.GetString(ms.ToArray());
 return serializedData;
}

You can see there is nothing fancy about this whole implementation to make it work with a Silverlight client. A very simple ASP.Net web service.

Silverlight Application

This is where all the action happens. There are few components of this application, rendering and data access. Lets us first discuss data access. The client application is to talk to server at certain frequency. That means I need some kind of timer going in the application. When this timer ticks at specified interval of time, it send asynchronous request to server to get new messages. I have implemented this whole mechanism in MessageMonitor application. When this class is constructed, it creates an instance of DispatchTimer. You may be asking why DispatchTimer and why not simple Timer application. The problem is that when you are dealing with user interface application, you can only update the controls on the thread on which they were dispatched. Regular timer does not executes on that dispatcher thread. So if you will try to update your user interface on that thread you will get exception complaining about cross threaded access. Here is the code that created DispatcherTimer for my application.


private void CreateMessagePollTimer()
{
 _messagePollTimer = new DispatcherTimer();
 _messagePollTimer.Tick += new EventHandler(MessagePollTimer_Tick);
 _messagePollTimer.Interval = new TimeSpan(0, 0, MessagePollInterval);
}

When the timer ticks it calls MessagePollTimer_Tick method. And that method makes async request to server to get new messages.


void MessagePollTimer_Tick(object sender, EventArgs e)
{
 if (Stopping || MessagePollInProgress) return;
 GetMessages();
}

When async request to server completes, the following method gets called. You can see that now it uses the same JsonSerializer class to de-serialize the response into list of StatusMessage objects. And then it raises event for objects that have subscribed to the event.


void GetGlobalMessagesCompleted(object sender, 
  SiteMessagePanel.ActivityDataServices.GetGlobalMessagesCompletedEventArgs e)
{
if (e.Error != null)
{
 return;
}
 var msgsData = e.Result as String;
 var msgs = msgsData.FromJson();
 System.Diagnostics.Debug.WriteLine(msgs);
 StatusMessageEventArgs args = new StatusMessageEventArgs(msgs);
 OnStatusMessageReceieved(args);
}

Page class that implements user interface for popup, handles this event and renders all the messages.


void Monitor_StatusMessageReceieved(object sender, 
 ByteBlocks.ActivityData.StatusMessageEventArgs arg)
{
 if (arg.Messages.Count == 0)
 {
 msgTextBlock.Text = "No messages received";
 ShowClientPanel(false);
 return;
 }

 msgTextBlock.Text = string.Empty;
 messagesPanel.Children.Clear();
 foreach (var msg in arg.Messages)
 {
  StackPanel sp = new StackPanel();
  TextBlock tb = new TextBlock();
  tb.Text = msg.Title;
  tb.TextWrapping = TextWrapping.Wrap;
  sp.Children.Add(tb);
  messagesPanel.Children.Add(sp);
 }
 ShowClientPanel(true);
}

ASP.Net application and javascript

ASP.Net application acts as a host for the silverlight control that I created to render messages. I have implemented a simple Server Control that hosts it. Then I added that control inside a simple div on the master page. And I have very simple vanilla implementation of the server control. It does not have very complicated implementation. I simply copied the code generated by silverlight wizard for test page into that control


<div id="statusslideup">
<ByteBlocks:StatusPanel runat="server" id="statusPanel" />
</div>

Calling Javascript Method From Silverlight

So far we have implemented two pieces of the application that drive the data and render it. Now comes the fun part. How are we going to trigger the client to show the popup and animate it to come up from bottom. First, it is Silverlight application that is running the timer. So it is the one that has to trigger the client. I implemented some java script code that shows the DIV that hosts silverlight client component. And then small piece of code that implements animation. Silverlight framework provides a very simple mechanism to invoke any Javascript method that is implemented on client side. I implemented a very simple method in silvelight application to call my JS method whenever there are new messages for the user.


private void ShowClientPanel(bool show)
{
 HtmlPage.Window.Invoke("_showStatusPanel", show);
}

It could not be any simpler. And the following Javascript function implements small piece of code that calculates position of popup notifier window based on browser height and height of element containing silverlight control.


setStatusPanelPosition = function() {
 if (_statusdiv) {
 _maxPanelPos = document.body.scrollTop + ($(document).height() - _statusdiv.clientHeight);
 _curPanelPos = $(document).height();
 if (!_isStatusVisible) {
  _sliderInterval = setInterval("_slidePanel()", 5);
 }
 else {
  _statusdiv.style.top = _maxPanelPos + "px";
 }
 _isStatusVisible = true;
 }
}

Demo Project

Attached demo project is a collection of Visual Studio 2010 projects and solution. If you do not have VS2010, you can simply create a new solution and projects in VS2008 and copy the source files in there. You are also going to need to download Silverlight 3 Toolkit because I use theming controls from that toolkit to give some zing to the UI.

I hope this demo project helps you in building cooler implementations of OWA like message and event notifier windows.

Give your advice to big bosses and make money

Views: 5126

Tags: , ,

ASP.Net | Javascript | JQuery | Silverlight

Unable to start debugging on the web server - Error when starting ASP.Net debugging

by Viper 1. October 2009 13:59

Recently I installed Visual Studio 2010 and was working on a prototype User Activity Monitoring administration application. When I tried to launch the application in Visual Studio IDE, I got the following error message box.

---------------------------
Microsoft Visual Studio
---------------------------
Unable to start debugging on the web server. Debugging failed because integrated 
Windows authentication is not enabled. Please see Help for assistance.
---------------------------
OK   Help   
---------------------------

As the error suggests that I need to enable windows authentication. And that is a pre-requisites for running ASP.Net application under debugger. But thing that was different is that till Visual Studio 2008 when you made the IDE to create Virtual Directory, it used to enable windows authentication in IIS for that virtual directory. It seems that Visual Studio 2010 does things differently. It only enables anonymous access. You will have to explicitly enable windows authentication. It is simple procedure.

  • Launch IIS manager
  • Right click on virtual directory and select Properties menu option
  • Select Directory Security tab on the dialog box.
  • On this view click on Edit button in Anonymous access and authentication control section at top
  • On this dialog box, check the check box at the bottom in front of Integrated Windows Authentication option.
  • Click OK and apply your changes.
Give your advice to big bosses and make money

Views: 2571

Tags: ,

ASP.Net | IIS | Visual Studio

How to check for loopback IP address on Windows 7

by Viper 2. September 2009 06:02

Transition from Windows XP to Windows 7 has been raising new issues every day during development of desktop as well as web applications. Most of these are not issues per se. They are changes that were introduced during Windows Vista and are part of Windows 7 as well. This piece of information has to do with network protocols on Windows 7. Here is what happened. I am developing a web application. One of the things I had to do in the application is to check if the request URL is from localhost or loopback address then do something different otherwise follow normal routine. So I was comparing Request.UserHostAddress with standard loopback address of 127.0.0.1. It was working fine. Then I started an instance of IE and tried to test the page. Well, nothing seemed to work. When I debugged the code, I saw that value of Request.UserHostAddress was ::1 instead of 127.0.0.1. By looking at the IP address I could tell that it was standard IPv6 loop back IP address. Actually the loopback address on an IPv6 network is 0:0:0:0:0:0:0:1 which is abbreviated as ::1. Then I paid close attention to IPAddress class in .Net framework. There is a method IsLoopback that you can use to test for loopback address. And you will use Parse method to create instance of IPAddress object. After making these changes, my implementation looked as below.


private void GetUserFromIp()
{
 UserGeoLocator geoLocator = new UserGeoLocator();
 _userLocation = null;
 var ip = IPAddress.Parse(Request.UserHostAddress);
 if (IPAddress.IsLoopback(ip) ||
  string.Compare(Request.UserHostAddress, "127.0.0.1", 0) == 0)
 {
  _userLocation = geoLocator.GetUserLocationByIp("68.xxx.xxx.xxx");
 }
 else
 {
  _userLocation = geoLocator.GetUserLocationByIp(Request.UserHostAddress);
 }
}

IPv6 is enabled by default on Windows Vista as well as Windows 7. If you use Visual Studio Development Server to debug your application, you will notice that loopback address is in IPv4 format but if you use IIS to debug your ASP.Net application, the loopback address is in IPv6 format. To avoid any issues like this, using IsLoopback makes the implementation neutral to format because framework will take care of interpretting the IP address correctly when you use Parse to create instance of IPAddress object.

You can diable use of IPv6 on Windows 7 by following instructions in How to disable certain Internet Protocol version 6 (IPv6) components in Windows Vista, Windows 7 and Windows Server 2008. If you are not using any format specific implementation, then you do not have to do that and I would not suggest doing it if you are not comfortable dealing with changing registry entries.

Give your advice to big bosses and make money

Views: 2174

Tags: ,

ASP.Net | Windows 7

ASP.Net version getting set to 4.0 in IIS manager

by Viper 6. August 2009 05:26

I have been working with VS2010 and ASP.Net 4.0 for quite some time now. Every time i create a web application, I just use the handy feature of Visual Studio of creating virtual directory for web application. Last week I was manually creating virtual directory for a web application using IIS manager. Since the application was targeting ASP.Net 2.0, so from ASP.Net tab of IIS, I selected V2.0 framework. Now there is a confirmation dialog box that comes up when you change ASP.Net framework.

Changing the Framework version requires a restart of the W3SVC service. Alternatively, you can change the Framework version without restarting the W3SVC service by running: aspnet_regiis.exe -norestart -s IIS-Viirtual-Path Do you want to continue (this will change the Framework version and restart the W3SVC service)?

Everything is good so far. Moment i accessed the application in browser, I got the following error message.

Server Error in '/Foo' Application.
The application domain or application pool is currently running version 4.0 or later of the .NET Framework. This can occur if IIS settings have been set to 4.0 or later for this Web application, or if you are using version 4.0 or later of the ASP.NET Web Development Server. The <compilation> element in the Web.config file for this Web application does not contain the required 'targetFrameworkMoniker' attribute for this version of the .NET Framework (for example, '<compilation targetFrameworkMoniker=".NETFramework,Version=v4.0">'). Update the Web.config file with this attribute, or configure the Web application to use a different version of the .NET Framework.

I was little surprised because I never configured virtual directory for this application to use ASP.Net 4.0. I fired up IIS manager and went to ASP.Net tab. There it was, the application was configured to use ASP.Net 4.0. So I changed it back to use ASP.Net 2.0. Accessed the application in browser and got the same error again. I experimented with the drop down box for ASP.Net version in IIS manager. The application will get configured to use ASP.Net 4.0 no matter what option I picked from the drop down box. It seems that this is some bug in beta version of Visual Studio 2010 installation.

For now the work around I have been using is to let Visual Studio create virtual directory for my web application. It targets the correct ASP.Net version and modifies IIS meta data correctly.

Give your advice to big bosses and make money

Views: 3256

Tags: , ,

ASP.Net | IIS

This operation requires IIS integrated pipeline mode - PlatformNotSupportedException

by Viper 22. July 2009 12:31

While experimenting with setting up of Cache-Control headers on Response object, i ran into following exception when I tries to access Headers property of Response object directly.


Exception type: PlatformNotSupportedException 
Exception message: This operation requires IIS integrated pipeline mode.

If i had read the documentation for Headers property I would have not done it at the first place. Here is what documentation says. The Headers property is only supported with the IIS 7.0 integrated pipeline mode and at least the .NET Framework 3.0. So if you are setting an headers in the response on IIS6 or earlier, use AddHeader method of Response object.

Give your advice to big bosses and make money

Views: 5193

Tags:

ASP.Net

How to set correct cache control headers for AJAX response

by Viper 22. July 2009 03:43

I have been developing AJAX enabled applications before the term AJAX was coined. I have been doing it for so long that some of things that I do come kind of naturally. And one of the things that I always do is to make sure that response is not cached to ensure that client is never working on stale response even though it sent new request every few seconds. So I have a small piece of code that I pretty much use in all applications that sets some headers.


Response.ContentType = "text/plain";
Response.Expires = -1;
Response.CacheControl = "no-cache";

These are not just the only headers but gives you an idea how cache was being control. I never ran into any trouble with any applications till last week when I was told that our application is filling up Temporary Internet Files folder of the users. This was the first time ever I was reported such issue and actually this was first time I observed this behavior in my applications. So I fired up Fiddler to see whats going on with my requests. I looked at the response headers and saw the following.

First, I was not expecting to see Cache-Control: private. So that was little out of whack. Second, the expiration time was correct because I always set to an hour behind the response time to make sure that it is stale for caching. I have been using the same caching utility routine for so long that I did not suspect that something is wrong there. Then I looked inside Temporary Internet Files folder again and noticed that this was the only request that was being saved in the folder, others were not. So I looked at the implementation and found that the server side implementation for this request was not using my standard utility to set cache headers. Following is the code snippet that I ad in place. Well why i changed the implementation for this particular call is whole different story.


Response.ContentType = "text/plain";
Response.Expires = -1;

Notice that it is missing Cache-control : no-cache header. That explained everything. After I added this header, everything went back to normal. So I decided to do some experiment to observe behavior of setting different headers.

No Cache-control: no-cache header on any call

You will notice that from my earlier post How to serialize multiple AJAX calls in jQuery, I have two AJAX calls being made. And you can see from snapshot above that both are being saved in Temporary Internet File folder.

Cache-control: no-cache header set on one request only

Now you can see that only one request is being saved in the folder and other has disappeared.

Cache-Control:no-cache header set on all requests

Well, there is nothing to show here in Temporary Internet Files folder because nothing is being saved there any more. But here is the snapshot of response headers as seen in Fiddler.

Now you can see that no-cache header and pragma has been set correctly.

Set cache-control header correctly

As more and more applications are using AJAX or Web2.0 style of implementations, if you do not set these cache control headers correctly, you will see that browser cache folders will accumulate lot of entries. It is not that big of a deal as far as application working goes because this temporary cache will not grow beyond specified limits for a particular browser. But it will hurt performance of other internet sites that you visit because their content will not be found in cache and will have to reloaded from server again. Other performance hit you will take is that now browser has to spend an extra CPU cycle to save these entries on the disk.

Give your advice to big bosses and make money

Views: 3604

Tags: , , , , ,

AJAX | ASP.Net | JQuery

How to use jQuery to make AJAX requests in ASP.Net?

by Viper 20. July 2009 15:06

Download Sample Project

For one of my current project, I have been using ASP.Net AJAX to make async request into my ASP.Net to get some time related data. First, I am not a big fab of ASP.Net AJAX implementation. I will not go into debate on why. There are plenty of discussions on this topic. I will just spare myself from it. Second, the application was already using jQuery for other javascript related implementation. I was like, if we are already using jQuery why have an overhead of introducing Ajax tool kit. So I started porting the implementation to use jQuery. Through this series of posts, I will describe how you can use jQuery to make AJAX calls in ASP.Net applications. Well, the client side javascript can be used in any browser. So other than the server side implementation, there is no nothing specific to ASP.Net per se.

The sample project for these articles is a time synchronization service. The idea is that I want to display clock on the client machine that will display server time. Well you can say there is no big deal with that implementation. On page load, get the server time. Save in some client side variable and run one second timer on it. Well, that works for most part. There are situations where clients are behind really slow connections that can cause of lot latency in request and response. So in those cases, by the time your response gets to the client side, the server time that you returned to client is already behind by few seconds. For applications that has users who depend very heavily on this server time, this latency of few seconds can be very critical. In this first post I am not going to go into details of algorithm that I implemented to reduce this latency adjustment over time. This first sample does a very simple task. It sends asynchronous request to server every 10 seconds. The server returns its time and then client uses that to display clock.

Server Side Implementation

I have a class ClockData that has DataContract attribute set on it. You can pretty much figure out that I am planning on converting this service to WCF service and use the framework facilities to serialize and de-serialize data as well. So I am populating this class with three pieces of data (server time, latency and a cookie) and then using DataContractJsonSerializer class to serialize the data into JSON format and sending it to client.


private void SerializeServerClockData(ClockData data, Stream strm)
{
 var spSer =
   new DataContractJsonSerializer(typeof(ClockData));
 spSer.WriteObject(strm, data);
}

void SendResponse()
{
 long ms = (long)(_serverTime - new DateTime(1970, 1, 1)).TotalMilliseconds;
 var clockData = new ClockData()
  {ServerTime = ms.ToString(), Latency = _latency, ResponseKey = Guid.NewGuid().ToString("N")};
 Response.ContentType = "text/plain";
 Response.Expires = -1;
 Response.CacheControl = "no-cache";
 SerializeServerClockData(clockData, Response.OutputStream);
 Response.End();
}

From the code snippet above, you can see how plain and simple server side implementation is for this first sample. This will get little complicated as I get more into the actual algorithm of calculation of latency reduction.

Client Side Implementation

Since we are going to be using jQuery to make Ajax call, so we will need to include reference to jQuery javascript file. For this sample, I am going to show the AJAX request you can send using jQuery. The library has method named .getJSON that you can call to send the request. You can set the URL where request is to be sent, set the parameters that needs to be passed with request and set the callback function that should be called when request completes. It is that simple. Here is the implementation from the sample.


function getServerTime() {
 cTime = firstRequest ? -1 : curTime.getTime();
 $.getJSON(clockServiceUrl, { clientTime: cTime, requestKey: respKey }, gotServerTime);
}

function gotServerTime(data) {
 firstRequest = false;
 latency = data.Latency;
 curTime = new Date(parseInt(data.ServerTime));
 if (!clockTicking) createClockTimer();
 createServiceTimer(defaultServiceTimer);
}

function clockTick() {
 clockTicking = true;
 curTime.setTime(curTime.getTime() + 1000);
 elClockDisplay.text(curTime.toString());
 if (latency == -1)
 { elLatencyDisplay.text(""); }
 else
 {elLatencyDisplay.text(latency + " ms");}
}

$(function() {
 elClockDisplay = $('#clockDisplay');
 elLatencyDisplay = $('#latencyDisplay');
 getServerTime();
});

In subsequent posts I will discuss how you can control the request little bit more instead of using .getJSON to use default settings.

Give your advice to big bosses and make money

Views: 1068

Tags: , ,

.Net | ASP.Net | JQuery | AJAX

Powered by BlogEngine.NET 1.5.1.7
Theme by Naveen Kohli

By Categories