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.
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.
I am not going to explain in detail about this, but you can follow the links below to know more about it
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
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
// a handler that is passed an assertion after the user logs in via the // browserid dialog functiongotVerifiedEmail(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
///<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) { thrownew 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.
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.
I am not going to explain in detail about this, but you can follow the links below to know more about it
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
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
// a handler that is passed an assertion after the user logs in via the // browserid dialog functiongotVerifiedEmail(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
///<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) { thrownew 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.
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
PublicSub AttachToWebServer() Dim attached AsBoolean = False Dim project As EnvDTE.Project = GetStartupProject()
If (project IsNothing) Then MsgBox("Couldn't find a web project that can be attached") Return EndIf
attached = AttachToProcess(project)
If (Not attached) Then MsgBox("Couldn't attach to the process") EndIf EndSub
PrivateFunction GetStartupProject() As EnvDTE.Project Dim startUpProject AsString = DTE.Solution.Properties.Item("StartupProject").Value
ForEach currentProject As EnvDTE.Project In DTE.Solution.Projects If currentProject.Name = startUpProject Then Return currentProject EndIf Next ReturnNothing EndFunction
PrivateFunction AttachToProcess(ByVal project As EnvDTE.Project) AsBoolean Dim serverProcessNamePattern AsString ' 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 > 0Then serverProcessNamePattern = ".*iisexpress.exe" Else' Real IIS serverProcessNamePattern = ".*w3wp.exe" EndIf
Else' Assume development web server serverProcessNamePattern = ".*WebDev.WebServer\d+.EXE" EndIf
ForEach process In DTE.Debugger.LocalProcesses If (Regex.IsMatch(process.Name, serverProcessNamePattern)) Then process.Attach() attached = True ExitFor EndIf Next
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
PublicSub AttachToWebServer() Dim attached AsBoolean = False Dim project As EnvDTE.Project = GetStartupProject()
If (project IsNothing) Then MsgBox("Couldn't find a web project that can be attached") Return EndIf
attached = AttachToProcess(project)
If (Not attached) Then MsgBox("Couldn't attach to the process") EndIf EndSub
PrivateFunction GetStartupProject() As EnvDTE.Project Dim startUpProject AsString = DTE.Solution.Properties.Item("StartupProject").Value
ForEach currentProject As EnvDTE.Project In DTE.Solution.Projects If currentProject.Name = startUpProject Then Return currentProject EndIf Next ReturnNothing EndFunction
PrivateFunction AttachToProcess(ByVal project As EnvDTE.Project) AsBoolean Dim serverProcessNamePattern AsString ' 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 > 0Then serverProcessNamePattern = ".*iisexpress.exe" Else' Real IIS serverProcessNamePattern = ".*w3wp.exe" EndIf
Else' Assume development web server serverProcessNamePattern = ".*WebDev.WebServer\d+.EXE" EndIf
ForEach process In DTE.Debugger.LocalProcesses If (Regex.IsMatch(process.Name, serverProcessNamePattern)) Then process.Attach() attached = True ExitFor EndIf Next
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
Click on the “Attach to Process” menu under the Debug menu
Select the correct process from the list of available processes
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
PublicSub AttachToDevelopmentServer() Dim attached AsBoolean = False Dim process As EnvDTE.Process ForEach process In DTE.Debugger.LocalProcesses If (process.Name.EndsWith("WebDev.WebServer20.EXE")) Then process.Attach() attached = True ExitFor EndIf Next
If (Not attached) Then MsgBox("Couldn't attach to the process") EndIf
EndSub
If you don’t know to how to create a macro, these are the steps for doing it
In Visual Studio Go To the Tools menu
Then select the Macros and then Macros IDE (Short cut is Alt+F11). This will open up a new IDE similar to Visual Studio.
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
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
In Visual Studio, go to the Tool menu, under that select the Customize menu. This will open up the Customize dialog
Select the Commands tab
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
Now click on the “Add Command” button. Then select the Macros from the categories in the Add Command dialog.
Now you will see the list of available macros on the list box on. From that list select your Macro AttachToDevelopmentServer and click OK
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
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.
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
Click on the “Attach to Process” menu under the Debug menu
Select the correct process from the list of available processes
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
PublicSub AttachToDevelopmentServer() Dim attached AsBoolean = False Dim process As EnvDTE.Process ForEach process In DTE.Debugger.LocalProcesses If (process.Name.EndsWith("WebDev.WebServer20.EXE")) Then process.Attach() attached = True ExitFor EndIf Next
If (Not attached) Then MsgBox("Couldn't attach to the process") EndIf
EndSub
If you don’t know to how to create a macro, these are the steps for doing it
In Visual Studio Go To the Tools menu
Then select the Macros and then Macros IDE (Short cut is Alt+F11). This will open up a new IDE similar to Visual Studio.
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
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
In Visual Studio, go to the Tool menu, under that select the Customize menu. This will open up the Customize dialog
Select the Commands tab
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
Now click on the “Add Command” button. Then select the Macros from the categories in the Add Command dialog.
Now you will see the list of available macros on the list box on. From that list select your Macro AttachToDevelopmentServer and click OK
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
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.
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
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
Select the web project which you don’t want to start
Go to the properties window (Shortcut – press F4)
Set “Always Start When Debugging” to False
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.
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
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
Select the web project which you don’t want to start
Go to the properties window (Shortcut – press F4)
Set “Always Start When Debugging” to False
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.
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
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.