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.

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 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

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

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.