Introducing SourceCodeReader

Have you ever tried to understand a project just by going through the source code?

That’s how I do most of the time, till now I haven’t seen any up to date documentation which gives the clear understanding of how the code is implemented. In reality after a certain period during the development, documentation goes out of sync with the source code. So some one joins the project lately has only one way to understand the project Go through the source code

Sometimes I go through the open source projects hosted on either Github, Codeplex or Google code. All the hosting site provide you with a user interface for browsing through the source code with syntax highlighting support, which is nice. The problem I had with this is – if I see a object creation statement, method call there is no way for me to find out how it is implemented other than manually going through the files and finding it out.

Most of the full blown editors provide a feature where you can navigate to the implementation directly from where it is used for e.g. Microsoft Visual Studio provides Go To Definition feature. I find this feature very much useful for understanding the project. Only draw back with this approach is you have to completely get the latest version of source code to your local machine.

SourceCodeReader is trying solve this navigation problem on the web. With this application you can open a project and browse through the files with code navigation support.

Source code for this project can be found at https://github.com/cvrajeesh/SourceCodeReader

Limitations

  1. Now supports only Github code repository
  2. Only supports .Net C# projects, other type of projects also works without code navigation support

###How to use this application

Go to SourceCodeReader and enter the URL of a C# project on Github

SourceCodeReader home page

Once you have entered a Github project link and open the project, it get the source code from the Github and present you with file browser.

SourceCodeReader project directory

When you navigate to a C# file you will be able to see clickable links for identifiers which takes you the file location where that is declared.

SourceCodeReader Go To Definition feature

Sample projects :

Hope you liked this idea, please provide me with your valuable feedback.

Integrating BrowserID In To Your ASP.NET MVC Application

BrowserID is a decentralized identity system which verifies the ownership of an email address in a secure manner, without the use of any application specific authentication mechanism. Which means, you don’t need to provide an login forms in your application, instead use BrowserID feature.

BrowserId screenshot

I am not going to explain in detail about this, but you can follow the links below to know more about it

I have created demo application to show how it could be integrated into ASP.NET MVC (it could applied to ASP.NET Forms also) application.

###How the Demo Application works

In this demo, Secret page link can only accessed if you have logged into the application. In order to login I have provided a Sign in button, like most of the applications, but when you click on it. It will open a pop-up window (make sure you have disable pop-up blockers), which is a URL from https://browserid.org not from my application. If you don’t have a BrowserID create one, otherwise enter the Email address and Password. Then follow the steps and finally click on the Sign in button, which log you into the application and from there you can access the Secret page link.

###How to implement this in ASP.NET MVC

Enable BrowserID in your application :

Include the BrowserID javascript file https://browserid.org/include.js to your master page
<script src="@Url.Content("https://browserid.org/include.js")" type="text/javascript"></script>

Identify the User :

Instead of displaying a login form on your site which takes a username and password, it uses the BrowserID JavaScript API when the user clicks your sign-in button. For that I have added the below script to the _LogOnPartial.cshtml which comes with the ASP.NET MVC application you have created

1
2
3
4
5
6
7
$(document).ready(function () {
$('#login').click(function () {
navigator.id.getVerifiedEmail(gotVerifiedEmail);
});
.....
.....
});

Upon a successful sign-in, you’ll be called back with an assertion, a string containing a signed claim that proves the user is who they say they are. Which is passed to a method called gotVerifiedEmail

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// a handler that is passed an assertion after the user logs in via the
// browserid dialog
function gotVerifiedEmail(assertion) {
// got an assertion, now send it up to the server for verification
if (assertion !== null) {
$.ajax({
type: 'POST',
url: '/Account/LogOn',
data: { assertion: assertion },
success: function (res, status, xhr) {
if (res != null) {
loggedIn(res.email);
}
},
error: function (res, status, xhr) {
alert("login failure" + res);
}
});
}
}

Which then sends a POST Request to the LogOn method on the Account controller, for verifying the assertion is correct or not. If it is a verified correctly, we will set up a forms authentication cookie so that ASP.NET feels that user has logged in to the application. Then returns the Email address back.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[HttpPost]
public ActionResult LogOn(string assertion)
{
var authentication = new BrowserIDAuthentication();
var verificationResult = authentication.Verify(assertion);
if (verificationResult.IsVerified)
{
string email = verificationResult.Email;
FormsAuthentication.SetAuthCookie(email, false);
return Json(new { email });
}

return Json(null);
}

In order to do the verification, we post the assertion to the URL provided by the Identity Authority itself (https://browserid.org/verify in this case), which will give a valid response if it is valid. The Verify method looks like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public VerificationResult Verify(string assertion)
{
JObject verificationResult = this.GetVerificationResult(assertion);
string email = "";
bool verified = false;

if (verificationResult != null && verificationResult["status"].ToString() == "okay")
{
email = verificationResult["email"].ToString();
verified = true;
}

return new VerificationResult {Email = email, IsVerified = verified };
}

/// <summary>
/// Gets the verification result from Identity Authority.
/// </summary>
/// <param name="assertion">The assertion.</param>
/// <returns></returns>
private JObject GetVerificationResult(string assertion)
{
// Build he request
var req = (HttpWebRequest)WebRequest.Create(IdentityAuthorityVerificationUrl);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";

if (HttpContext.Current == null)
{
throw new NullReferenceException("HttContext is null. Please make sure that, your application is running in a web scenario");
}

// Build the data for posting
var payload = string.Format("assertion={0}&audience={1}", assertion, HttpContext.Current.Request.Headers["Host"]);
byte[] payloadInBytes = Encoding.UTF8.GetBytes(payload);
req.ContentLength = payloadInBytes.Length;

var dataStream = req.GetRequestStream();
dataStream.Write(payloadInBytes, 0, payloadInBytes.Length);
dataStream.Close();

JObject result = null;

var res = req.GetResponse();
dataStream = res.GetResponseStream();
if (dataStream != null)
{
var responseData = new StreamReader(dataStream).ReadToEnd();
res.Close();
dataStream.Close();
result = JObject.Parse(responseData);
}else
{
res.Close();
}

return result;
}

Hope this will help you to setup an authentication system to your application very easily and in a more secure way.

Attach to Any ASP.NET Web Server from Visual Studio in One Click

This is an update to my previous blog post Attach to Visual Studio Development Server with One Click.

The Visual Studio Macro from previous article doesn’t support IISExpress or IIS; it only supported the Visual Studio Development Server, more over it doesn’t detect latest Development Web Server WebDev.WebServer40.exe.

Now I have updated the Macro so that it will automatically detect the Web Server setting from the project properties and attach it accordingly.

Below is the code for the new Macro, I think it is self-explanatory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Public Sub AttachToWebServer()
Dim attached As Boolean = False
Dim project As EnvDTE.Project = GetStartupProject()

If (project Is Nothing) Then
MsgBox("Couldn't find a web project that can be attached")
Return
End If

attached = AttachToProcess(project)

If (Not attached) Then
MsgBox("Couldn't attach to the process")
End If
End Sub

Private Function GetStartupProject() As EnvDTE.Project
Dim startUpProject As String = DTE.Solution.Properties.Item("StartupProject").Value

For Each currentProject As EnvDTE.Project In DTE.Solution.Projects
If currentProject.Name = startUpProject Then
Return currentProject
End If
Next
Return Nothing
End Function

Private Function AttachToProcess(ByVal project As EnvDTE.Project) As Boolean
Dim serverProcessNamePattern As String
' Using either IIS express or IIS
If project.Properties.Item("WebApplication.UseIIS").Value = "True" Then
' Using IIS Express
If project.Properties.Item("WebApplication.DevelopmentServerCommandLine").Value.ToString().Length > 0 Then
serverProcessNamePattern = ".*iisexpress.exe"
Else ' Real IIS
serverProcessNamePattern = ".*w3wp.exe"
End If

Else ' Assume development web server
serverProcessNamePattern = ".*WebDev.WebServer\d+.EXE"
End If

Return AttachToWebServer(serverProcessNamePattern)

End Function

Private Function AttachToWebServer(ByVal serverProcessNamePattern As String) As Boolean

Dim attached As Boolean = False

For Each process In DTE.Debugger.LocalProcesses
If (Regex.IsMatch(process.Name, serverProcessNamePattern)) Then
process.Attach()
attached = True
Exit For
End If
Next

Return attached
End Function

Read my previous article Attach to Visual Studio Development Server with One Click to understand how we can add this Macro as command to the Visual Studio toolbar.

Attach to Visual Studio Development Server with One Click

In my day to day work, during the development I had to attach an ASP.NET application to the development server (Cassini) several times in order to debug and fix a problem.

This task is little bit time consuming because this is how we normally do it

  1. Click on the “Attach to Process” menu under the Debug menu
  2. Select the correct process from the list of available processes
  3. Either double click on the select process or click the “Attach” button

You can reduce these into two steps, if you assign a short cut key to the Attach to Process command.

What I found is, most of the time is lost for finding and selecting the correct process from the available list of processes in the Attach to Process dialog.

So in order to be more productive, I have created a macro which will automatically attach to the Visual Studio Development Server automatically, saves your time from scroll through the big list of processes.

Below is the code for this macro

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Public Sub AttachToDevelopmentServer()
Dim attached As Boolean = False
Dim process As EnvDTE.Process
For Each process In DTE.Debugger.LocalProcesses
If (process.Name.EndsWith("WebDev.WebServer20.EXE")) Then
process.Attach()
attached = True
Exit For
End If
Next

If (Not attached) Then
MsgBox("Couldn't attach to the process")
End If

End Sub

If you don’t know to how to create a macro, these are the steps for doing it

  1. In Visual Studio Go To the Tools menu
  2. Then select the Macros and then Macros IDE (Short cut is Alt+F11). This will open up a new IDE similar to Visual Studio.
  3. In the project explorer under My Macros you will see My Module or you can create a new module by right clicking on the project, then Add -> Add Module. In my case I created a new module and called it as Extensions
  4. Copy and paste above subroutine to that module.

Now we have to execute the newly created macros on clicking on a toolbar button. For that, follow these steps

  1. In Visual Studio, go to the Tool menu, under that select the Customize menu. This will open up the Customize dialog
  2. Select the Commands tab
  3. Select the Toolbar checkbox and then select the Toolbar on which you want this button to appear from dropdown list. I chose the Standard Toolbar
  4. Now click on the “Add Command” button. Then select the Macros from the categories in the Add Command dialog.
  5. Now you will see the list of available macros on the list box on. From that list select your Macro AttachToDevelopmentServer and click OK
  6. If you want, you can customize the text which appears on the command button, by clicking on the Modify Selection
    Here it is how it looked in my machine

Adding Command to the Visual Studio Toolbar

That’s it, now you will be able to new button appeared in the standard toolbar. If you click on that, it will automatically attach your web project to the running application in the development server.

Visual Studio Toolbar after Customization

Note: There are couples of problems here

  1. This doesn’t work if you have set the IIS Express/IIS itself as the server for running the application.( Update: A new macro to support this feature is exlplained here Attach to Any ASP.NET Web Server from Visual Studio in One Click )
  2. If you have multiple web applications in your project, it will attach to the first development server. So I suggest you to read my previous post about disabling multiple Visual Studio development webservers

Multiple Visual Studio Development Servers while Debugging

You might have noticed that when you start debugging an ASP.NET web application, it start more than one visual studio development servers and in the system tray you see something like this

Multiple Development Servers

This happens when your solution contains more than one web application, setting one as the StartUp project is not going to help..

The reason for this is - by default any web application is set to start when we trigger the debugging process in visual studio. We need to disable that auto start feature so that only one visual studio development server is getting started when we are debugging.

These are the steps for disabling it

  1. Select the web project which you don’t want to start
  2. Go to the properties window (Shortcut – press F4)
  3. Set “Always Start When Debugging” to False

Disable always start

This is how you could do it in Visual studio 2010, I hope the same applies to Visual studio 2008 too. Now if you start debugging, you will see only one development webserver.

Hope this helps

Abstractions can also put you in Trouble

We all have enjoyed the beauty of abstracting out functionality, so that it simplifies the underlying complexity. Sometimes it can come back and hit you on the forehead like a boomerang if we don’t know what is going underneath those hidden layers.

Recently it happened to me with the LINQ provider. If you have a data source then you can build your own Query provider on top of it, so that the users can access your data using the LINQ statements without understand how it is fetched.

For e.g. Linq2Twitter it provides the IQueryable interface which you can use fetch the twitter API without understanding the REST API’s exposed by the Twitter.

Similarly Ayende has created a Linq provider for NHibernate (NHibernate.Linq) which hides complexities of writing Criteria API’s.

This is what happened to me – we had a repository method which is using the NHibernate.Linq and it returned an IQueryable interface of domain model.

Like to the below code(only an example, this is not from the actual codebase itself)

1
2
3
4
5
public IQueryable<Customer> QueryableCustomers()
{
session = SessionFactory.OpenSession();
return session.Linq<Customer>().AsQueryable();
}

In the consumer part (Action method in the controller), we are filtering the customer with a name containing particular string using the Contains method

this.dataProvider.QueryableCustomers().Where(x => x.Name.Contains("custo")).ToList();

Everything worked as expected, but one day the filtering stopped working, I couldn’t figure it out initially, but when I looked into the QueryableCustomers() method, it has been changed to something like this

1
2
3
4
5
public IQueryable<Customer> QueryableCustomers()
{
session = SessionFactory.OpenSession();
return session.Linq<Customer>().ToList().AsQueryable();
}

Not much difference in the code wise, but internally the earlier code will filter the customers using the SQL statement by adding a where clause to the SQL it generated and later one will fetch all the customers from the DB and filter that result using the LINQ on objects.

SQL generated for initial code

1
2
3
4
5
6
7
8
9
SELECT
this_.Id as Id0_0_,
this_.Name as Name0_0_,
this_.Address as Address0_0_
FROM
Customer this_
WHERE
this_.Name like @p0;
@p0 = '%custo%'

After code change, the query generated SQL was

1
2
3
4
5
6
SELECT
this_.Id as Id0_0_,
this_.Name as Name0_0_,
this_.Address as Address0_0_
FROM
Customer this_

By now you might have realized the reason why the I didn’t get the expected result from the new code change – if not here is the explanation, Contains in the earlier code is translated by the NH LINQ provider to a where clause which is case insensitive by default unless you have set any specific Collation in the database or on the column itself but in the other hand new code returned a collection of Customer itself, then we applied String.Contains on the Name property which is case sensitive.

My point here is - we can’t blindly believe in the abstractions provided by anyone without understanding what is happening underneath.

How to Move Directories Across SVN Repositories

Recently we were restructuring our project repositories, where I had to move a project from it’s own repository to another repository.

When do a move under SVN you need to make sure that the history is not lost, so I will explain two common scenarios and how you could do the SVN move

###Scenario 1 - Moving files or directories with in a SVN repository

Below is a screen shot of my existing repository and I want to move the configuration directory to the project directory without loosing the history.

SVN repository structure

First of of all this will work only for the versioned items, so please commit your changes to the directory you want to move before doing this. The steps explained below assumes that you are using Tortoise SVN

Here are the steps

  1. Right click on the directory you want to move
  2. Drag and drop on to the directory where you want to move this.
  3. Choose the SVN Mover Versioned item(s) here item from the context menu.
    Context Menu with move
  4. Now commit the changes back to the repository.

Don’t forget to uncheck Stop on copy/rename option in the Log messages dialog if you are trying to see the history of the moved directory.

Move configuration

###Scenario 2 – Moving directories across SVN repositories

In this case I want to move Project directory to another repository Repo2

The first technique I have mentioned will work only if the source and target are under same repository, but in some cases you have to move the directories across different SVN repositories. This cannot be done from a SVN client slike TortoiseSVN, you need o use the utilities that comes with SVN.

Follow these steps

  1. Dump the repository to a file using the svnadmin tool – e.g. svnadmin dump c:\Repositories\Repo1 > Repo1file
  2. Now load the dumped filed into the target repository – e.g. svnadmin load c:\Repositories\Repo2 < Repo1file

Here is the full syntax for svnadmin tool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ svnadmin dump --help
dump: usage: svnadmin dump REPOS_PATH [-r LOWER[:UPPER] ] [--incremental]

Dump the contents of filesystem to stdout in a 'dumpfile'
portable format, sending feedback to stderr. Dump revisions
LOWER rev through UPPER rev. If no revisions are given, dump all
revision trees. If only LOWER is given, dump that one revision tree.
If --incremental is passed, then the first revision dumped will be
a diff against the previous revision, instead of the usual fulltext.

Valid options:
-r [--revision] arg : specify revision number ARG (or X:Y range)
--incremental : dump incrementally
--deltas : use deltas in dump output
-q [--quiet] : no progress (only errors) to stderr

Stay Away from Request.Url

The title might be misleading but I will explain why we shouldn’t use the Request.Url in any asp.net application directly.

If you are writing an web application and you don’t know the environment of the server where it is getting deployed, then it is better not to use Request.Url it directly.

This blog is running on a home grown blog engine, which is written using asp.net MVC 3. For implementing some of the functionalities like generating sitemap.xml I had to get the root of the url(i.e. without any path). So I used the Request.Url.GetLeftPart(UriPartial.Authority) method and it worked perfectly on my local machine even when it is deployed my local machine IIS server. When I deployed my blog engine to Appharbor environment, the generated sitemap.xml has a URL with port number like www.rajeeshcv.com:4566 instead of just www.rajeeshcv.com.

###Why?

After googling for some time I came across the solution posted Appharbor knowledge base - workaround for generating absolute urls without port number. In their environment there are load balancers which sits in front on the webserver, which uses a specific port number for contacting the server where the application is running. Below is a simple pictorial representation of that

Network with load balancer

So whenever we try to get Request.Url, application will get the actual request Url received by that webserver, which will have the port number also.

###How to solve it

Appharbor has provided a code snippet in the same article but it didn’t worked for me, I was still getting port number in the generated Url. My assumption is that, there is condition check for ignoring the local request so that it will work correctly in the local development environment.

1
2
3
4
if (httpContext.Request.IsLocal)
{
uriBuilder.Port = httpContext.Request.Url.Port;
}

According to the MSDN documentation

The IsLocal property returns true if the IP address of the request originator is 127.0.0.1 or if the IP address of the request is the same as the server’s IP address.

In my case I think IsLocal was true (I really don’t the exact reason!!!). So instead of using the appharbor code snippet I came across a code from FunnelWeb which does the same (HttpRequestExtensions.cs)

Here is my version of that code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/// <summary>
/// Environments the specific request URL.
/// </summary>
/// <param name="request">The request.</param>
/// <returns></returns>
/// <remarks>
/// Code from FunnelWeb: https://bitbucket.org/TheBlueSky/funnelweb/src/b64c74f361d3/src/FunnelWeb/Utilities/HttpRequestExtensions.cs
/// </remarks>
public static Uri EnvironmentSpecificRequestUrl(this HttpRequestBase request)
{

UriBuilder hostUrl = new UriBuilder();
string hostHeader = request.Headers["Host"];

if (hostHeader.Contains(":"))
{
hostUrl.Host = hostHeader.Split(':')[0];
hostUrl.Port = Convert.ToInt32(hostHeader.Split(':')[1]);
}
else
{
hostUrl.Host = hostHeader;
hostUrl.Port = -1;
}

Uri url = request.Url;
UriBuilder uriBuilder = new UriBuilder(url);

if (String.Equals(hostUrl.Host, "localhost", StringComparison.OrdinalIgnoreCase) || hostUrl.Host == "127.0.0.1")
{
// Do nothing
// When we're running the application from localhost (e.g. debugging from Visual Studio), we'll keep everything as it is.
// We're not using request.IsLocal because it returns true as long as the request sender and receiver are in same machine.
// What we want is to only ignore the requests to 'localhost' or the loopback IP '127.0.0.1'.
return uriBuilder.Uri;
}

// When the application is run behind a load-balancer (or forward proxy), request.IsSecureConnection returns 'true' or 'false'
// based on the request from the load-balancer to the web server (e.g. IIS) and not the actual request to the load-balancer.
// The same is also applied to request.Url.Scheme (or uriBuilder.Scheme, as in our case).
bool isSecureConnection = String.Equals(request.Headers["X-Forwarded-Proto"], "https", StringComparison.OrdinalIgnoreCase);

if (isSecureConnection)
{
uriBuilder.Port = hostUrl.Port == -1 ? 443 : hostUrl.Port;
uriBuilder.Scheme = "https";
}
else
{
uriBuilder.Port = hostUrl.Port == -1 ? 80 : hostUrl.Port;
uriBuilder.Scheme = "http";
}

uriBuilder.Host = hostUrl.Host;

return uriBuilder.Uri;
}

###Conclusion

IMHO this is a limitation with .Net framework itself because here we have to modify the behaviour of the framework class to achieve what we really want . If there is way in which the IIS web server can detect the topology on which it is running, then the HttpRequest.Url could be implemented correctly. So that the developer need not to worry about the deployment scenarios(at least in this simple case).

New Outlook – Rolling out My Own Blog Engine

For the last couple of years I was using wordpress as my blogging platform, it is an awesome framework but finally I decided to move away from it and created my own blog engine(Rhyble), on which this blog is running now.

Rhyble is built using Asp.Net MVC3, NHiberanate and it is running Appharbor

You might ask why I want reinvent the wheel again because we have many blog engines available today. Jeff Atwood answered that question here - Why does every man and his dog want to code a blogging engine?

These were my objectives when I started creating Rhyble

  1. Focus on the most important functionalities, doesn’t want to create another wordpress with truck full of unwanted things
  2. Improve the performance. Now I have YSlow rating of 94 compared to 65
    image
  3. I didn’t wanted to go through the existing blog engines code base, which is more time consuming than creating a new one

YSlow previous and current ratings

More over it is a nice feeling if you have something you own. Now I have platform of my own and next things should be blogging frequently.

That’s it for the day.

Web Usability – Avoid an Extra Page Load with OpenSearch

Now a days most of the websites, blogs or any applications that are on internet will have a search functionality which is great!!!. Before the Omnibox concept was introduced by google chrome, if we want to search something in google, as a user I need to go to www.google.com and type the search query. After the introduction of Omnibox, user don’t need to open the google website instead you could do the search from the address bar itself. From the usability point of view, it is a great functionality IMHO.

From the point of google search application, they have done it smartly. As a web developer how could you provide the same usability feature to your own website. Some of the website I frequently visits has done like this.

StackOverflow Opensearch

If you are in google chrome, after you type the stackoverflow.com a message will be displayed on the address bar saying that Press Tab to search Stack Overflow. If you press tab, you can directly type the search query in the address bar itself and pressing enter will show the results. This basically allows you to do a quick search, instead of going to the website and finding the search box and pressing search button(a long process is it? Smile)

Recently I was working on a hobby project called ifscfinder , which is a website were you could search for a Indian Finacial System Code of any banks in India. It simply provide a search box where user could enter the Bank/Branch name and it will list the banks that matches the query. So I wanted to have the same feature like stackoverflow in my ifscfinder too.

After googling for sometime, I found about the opensearch which helps to achieve this functionality. You could read more about opensearch from here http://www.opensearch.org

What I had do was, create an xml file(OpenSearch description document), it will have URL format which needs to be called when user enter a search query. ifscfinder xml file looks like this

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>IFSC Finder</ShortName>
<Description>Search IFSC: Find Indian Financial System Code of a Bank</Description>
<InputEncoding>UTF-8</InputEncoding>
<Url type="text/html"
template="http://ifscfinder.apphb.com/Search?q={searchTerms}"/>
</OpenSearchDescription>

After this is created, I upload it the website. In order for the browser to sense whether my website opensearch, I had to add link tag to the head element

<link rel="search" type="application/opensearchdescription+xml" title="IFSCFinder.com" href="/opensearchdescription.xml" />

With this ifscfinder has got a nice quick search option in google chrome

ifscfinder opensearch

Firefox also detect the opensearch , which mean you could add this site to the search engine list in firefox

Firefox Opensearch

IE9 doesn’t care about this at all(don’t know why!!!)